NGINX + Express.js 부하테스트때 만난 에러

ghwany·2021년 7월 1일
2

nginx

목록 보기
2/2

Artillery로 NGINX + Express.js 부하테스트때 만난 502에러

NGINX와 Node.js의 Express앱 성능 테스트 중 HTTP STATUS 502ETIMEDOUT 에러를 만나게 되었습니다.

  • 502 BAD GATEWAY : upstream으로 부터 유효하지 않은 응답을 받으면 발생
  • ETIMEDOUT : socket으로 서버와 연결 시도 중 제한시간 안에 연결이 진행되지 않으면 발생

1. 180초 동안 100명이 초당 10회 요청 결과

시나리오 완료도 못하고 502에러...

누락된 요청 : 265(ETIMEDOUT) * 스레드 100개 = 26500 (약14%)
502 BAD REQUEST : 40772 (약22%)
👎 67272/180000 (약36%)

All virtual users finished
Summary report @ 14:28:08(+0900) 2021-06-30
  Scenarios launched:  1800
  Scenarios completed: 1535
  Requests completed:  153500
  Mean response/sec: 638.11
  Response time (msec):
    min: 4
    max: 9987
    median: 527
    p95: 1407
    p99: 2201
  Scenario counts:
    0: 1800 (100%)
  Codes:
    200: 112728
    502: 40772
  Errors:
    ETIMEDOUT: 265

2. 어떤 부분이 문제일까?

NGINX, upstream과의 기본 연결 설정?

upstream was {
    server express:3000;
}

NGINX에서 위 설정 처럼 upstream에 별도의 설정을 하지 않는다면 같은 사용자의 요청에 매번 NGINX와 upstream사이에 TCP Handshake로 세션을 수립하고 Response 후 소켓을 끊게 됩니다.
TPS가 높은 서버에서는 아래와 같은 문제가 발생할 수 있습니다.

생성할 수 있는 local 소켓이 부족해진다.

TCP로 연결이 설정되면 local 및 remote host 모두 소켓이 생성됩니다. local 포트는 운영체제에서 사용할 수 있는 범위 내에서 무작위로 선택되는데 생성할 수 있는 범위 이상 소켓을 생성하면 오류가 발생합니다.
그렇다면 현재 운영체제의 최대 소켓 생성 개수는 몇 개 일까요? linux의 경우 아래 명령어를 통해 확인할 수 있습니다.

stsctl -a | grep somaxconn

...
net.core.somaxconn = 1024
...

어떻게 해야할까?

1. linux 운영체제에 설정된 최대 소켓 생성 개수를 늘려준다?

  • 당장 해결될 수 있겠지만 TPS가 더 증가하면 동일한 문제가 발생할 수 있습니다. 성능적인 측면은 여전히 해결되지 않습니다.
    ⚠️ (1 User, N Request - N TCP Handshake)

2. NGINX에 upstream과의 연결이 지속될 수 있도록 설정해준다?

  • NGINX와 upstream 간에 keepalive로 소켓을 유지한다면 같은 User의 요청들 마다 TCP Handshake를 하지 않아도 되고 local 소켓이 무한정 생성되지 않기 때문에 해결할 수 있어 보입니다.
    👍 (1 User, N Request - 1 TCP Handshake)

3. NGINX upstream에 keepalive를 설정해보자.

upstream was {
    server express:3000;
    keepalive 64;
}

200 OK : 180000 (100%)

All virtual users finished
Summary report @ 14:34:36(+0900) 2021-06-30
  Scenarios launched:  1800
  Scenarios completed: 1800
  Requests completed:  180000
  Mean response/sec: 988.96
  Response time (msec):
    min: 2
    max: 769
    median: 16
    p95: 72
    p99: 133
  Scenario counts:
    0: 1800 (100%)
  Codes:
    200: 180000

Artillery에서 -o [filepath] 옵션으로 결과를 json으로 저장할 수 있는데 artillery report [filepath] 명령을 통해 예쁜 차트를 가진 html파일로 변환할 수 있습니다.

완벽히 예쁜 차트는 아니지만...

RPS(TPS)는 상승, Latency(p95)는 확연히 줄어들고 HTTP STATUS 502ETIMEDOUT 에러가 사라진 것을 볼 수 있습니다.
upstream의 keepalive는 일반적이라면 16~64를 설정하지만 Traffic이 몰리거나 사용자가 지속적으로 자주 요청하는 웹서버의 경우 1000이상 설정한다고도 합니다.
높은 만큼 리소스 자원을 많이 할애하니 성능 테스트를 통해 적절한 keepalive를 찾는 것이 중요하다고 생각합니다.

잘못된 내용, 피드백은 환영입니다!

profile
개발이 하고싶다

0개의 댓글