idea·blog

SERVER ERROR CLINIC

503 Service Unavailable

서버가 지금은 요청을 받을 수 없다고 스스로 답했습니다. 고장이 아니라 거절이라는 점에서 502와 다릅니다.

이 도구는 여러분의 서버에 접속하지 않습니다. 답한 내용만으로 확인할 순서를 정해주는 도구이며, 실제 로그를 대신하지 않습니다.

  1. 브라우저요청을 보낸 곳
  2. 인터넷이름 찾기·연결
  3. 프록시여기가 의심됩니다
  4. Node·Spring·Django
  5. DB·외부 API앱이 부르는 곳

어느 로그를 볼까 프록시 로그를 먼저 봅니다. 프록시가 스스로 낸 503인지, 앱이 만들어 보낸 503인지에 따라 원인이 완전히 갈립니다.

원인 후보 3

언제 나타나나요?

항상 나면 설정 문제, 몰릴 때만 나면 용량 문제일 때가 많습니다.

가장 먼저 확인할 것

넘겨줄 서버가 하나도 남지 않았다

프록시가 건강검사에 실패한 서버를 목록에서 빼다 보니 전부 빠졌습니다. 그래서 시도조차 하지 않고 503으로 답합니다.

다른 후보가 하나씩 제외되면서 남은 원인입니다.

프록시가 검사하는 그 주소가 실제로 답하는지 직접 확인합니다.

curl -i --max-time 5 http://127.0.0.1:3000/

그다음 건강검사 경로가 앱에 실제로 존재하는지 봅니다. /health를 검사하는데 앱에는 그 경로가 없어 404가 나면 계속 실패로 집계됩니다.

아니라면 다음

받을 수 있는 양을 넘겼다

동시 처리 한도나 대기줄이 가득 차서 새 요청을 즉시 거절합니다. 서버를 지키기 위한 의도된 동작입니다.

부하와 연결 수가 실제로 높은지 봅니다.

uptime && ss -s | head -5

그다음 한도를 올리는 건 그다음입니다. 먼저 요청 하나가 얼마나 오래 자리를 차지하는지 재봅니다.

동시 연결이 늘면 생기는 일

아니라면 다음

점검 모드거나 요청 제한에 걸렸다

설정이 의도적으로 503을 돌려주고 있습니다. 점검 페이지나 요청 수 제한이 켜져 있는 경우입니다.

503을 직접 돌려주는 설정이 있는지 찾습니다.

grep -rn 'return 503\|limit_req\|maintenance' /etc/nginx /etc/caddy 2>/dev/null

그다음 점검 모드를 끄거나, 요청 제한이 정상 트래픽까지 막고 있지 않은지 기준을 다시 잡습니다.

실험을 마쳤다면