본문 바로가기

프로젝트/버그, 성능개선

guincorn 메모리 누수 현상 해결하기 ( gunicorn memory leak )

회사에서 운영하고있는 채점 서버 모니터링중에 메모리 사용 평균이이 비 정상적으로 높은것을 확인하였다. 

 

?

 

원인 파악을 위해 각 채점서버에 접속해서 서버 상태를 파악해보기로 하였다. 

top

왼쪽- 채점서버1, 오른쪽- 채점서버2

 

여기에서 이상한걸 발견할수 있었다. 

core=$(grep --count ^processor /proc/cpuinfo)
n=$(($core*2))
exec gunicorn --workers $n --threads $n --error-logfile /log/gunicorn.log --time 600 --bind 0.0.0.0:8080 server:app

 

기존에 gunicorn을 기동하는 코드는 각 cpu core수 *2 로 운영하기 떄문에 gunicorn이 5개 (마스터노드  1 + 워커 4) 로 운영되어야하는데 비정상적으로 gunicorn의 개수가 많은것을 파악하였다. 

 

추가적으로 해당 gunicorn 관련 로그들을 파악하고 나서 구글링 끝에 gunicorn에는 고질적인 메모리 누수 현상이 있다는것을 알수 있었다. 

 

수많은 메모리 누수 간증(?), 공식 github issue에도 관련 내용들이 있었다.

 

 

해당 내용을 해결하기 위해 관련 2가지 내용을 추가하였다. 

exec gunicorn --workers $n --threads $n --error-logfile /log/gunicorn.log --timeout 600 --bind 0.0.0.0:8080 --max-requests 1000 --max-requests-jitter 50 server:app

 

max-requests 

 

워커가 처리할 요청의 최대 수를 설정한다.  max-requests 1000은 1000건을 처리하고 워커가 재시작된다. 재시작?을 한다는 점이 썩 반갑지는 않았지만 내부에서도 인정하고 이를 위한 대한 대책이니 해당 max-request를 넣어주었다. 

 

max-requests-jitter

 

기존 max-requests 값에 랜덤한 숫자를 추가해서 워커가 재시작되는 시점을 무작위 한다.

해당 내용을 넣어주는 이유는 모든 워커 ( 나의 경우 4개의 워커 노드) 가 동시에 재시작되는것을 막기위해 워커마다 다른시점에 재시작되도록 한다.

 

 

해당 내용을 넣어주고 며칠 후에 top를 통해 확인한 결과

 

 

워커노드의 갯수가 안정적이며 메모리 사용치 또한 안정적으로 변경된것을 확인할수 있다.