본문 바로가기
관리자

Programming-[Backend]/Django

API Throughput, health check fail: async 요청이 한 번에 많이 들어올 때

728x90
반응형

문제 및 원인

특정 컨테이너의 health check가 주기적으로 fail이 발생했다. 다행히 운영환경은 아니고 테스트 환경이였는데, 로그를 추적해보니 클라이언트 쪽에서 비동기 요청을 한 번에 10개 가량 요청하여(10개 이상/ 1초) 서버에 요청 처리가 쌓인 상태에서 /health 로 헬스 체크가 들어오면 헬스 체크에 실패하는 상황이였다. 문제는 헬스 체크 실패 시 해당 컨테이너를 재시작하는 설정이 적용되어 있어서 컨테이너가 죽다보니 클라이언트에서도 문제가 있다고 알려주었다. 그리고 monitoring 툴인 Pixie로 HTTP 지연을 관찰했을 때 순간적으로 지연이 엄청 늘어나는 것을 볼 수 있었다.

 

해결 및 원리

1. gunicorn worker, thread 개수 늘리기

파이썬은 인터프리터로 싱글 쓰레드에서만 동작한다. 그리고 Global Interpreter Lock(GIL)이 존재해서 하나의 프로세스에서 1개의 스레드만 동작가능하다. 그러나 WSGI 툴인 gunicorn의 worker 개수 또는 스레드 개수를 설정을 통해서 늘려줄 수 있다. 스레드의 개수를 늘리면 여러 개로 분산해서 하나의 스레드가 작업하는 동안 다른 스레드가 작업을 처리할 수 있게 된다.

 

참조에 따르면 공식문서에서 추천하는 worker, thread의 권장 개수는 (2~4) * (core 개수) 정도이다. 또한 CPU 베이스의 작업을 늘릴려면 worker 개수를 늘려야하고, 단순 I/O 베이스 작업을 늘릴려면 thread 개수를 늘려야한다. 그리고 gunicorn은 기본적으로 master process, worker process로 구성된다. master process는 gunicron 자체의 process 이고, 설정한 개수에 따라서 master process를 fork한 worker process들이 생성된다.

 

그리고 worker, thread 개수를 너무 늘리면 문제가 발생할 수 있다고 한다. 우리 팀에서는 다른 방식으로 해결하였다.

 

2. k8s pod container 증가

많은 수의 요청이 비동기적으로 들어오는 프로젝트가 아니라서 worker 개수를 조정하지 않고 k8s 설정을 통해 pod을 늘려주었다. 향후에는 gunicron 설정 자체를 처리하자고 협의했다.

 

 

추가: healthcheck 발생했을 때 추정할 수 있는 원인

- instance나 host에 healthcheck이 안될 정도로 load가 크게 걸림

- Load Balancer가 제대로 동작하지 않아서 특정 컨테이너만 부하가 걸림

- 애플리케이션에서 버그가 발생해서 API가 처리되지 않고 있음

 

 

 

 

참조

https://sonnson.tistory.com/6

728x90
반응형