LabHub
배우기 러닝패스 코스

Tomcat & nginxの運用

アップストリームの負荷分散と障害隔離

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

nginx 업스트림으로 여러 백엔드에 부하를 분산하고, 가중치·세션 고정·장애 격리· Keep-Alive 를 설정하며, 분배 알고리즘을 상황에 맞게 고를 수 있게 됩니다.

왜 중요한가

SI 현장에서 WAS 를 두 대 이상 두는 이유는 성능보다 한 대가 죽어도 서비스가 유지되게 하기 위해서입니다. 그런데 nginx 오픈소스판에는 능동 헬스체크가 없어서, max_fails/fail_timeout 의 의미를 모르면 "죽은 서버로 계속 요청이 간다"는 상황을 만듭니다. 또 업스트림 Keep-Alive 는 세 가지 설정이 모두 있어야 동작하는데 proxy_set_header Connection "" 를 빠뜨려 매 요청마다 새 커넥션을 만드는 시스템이 정말 많습니다. 그러면 TIME_WAIT 소켓이 쌓여 어느 순간 포트가 고갈됩니다.

단계

  1. 준비: Tomcat(8080)에 labhub.war 를 배포하고, /opt/lab/samples/labhub-boot.jar8082 포트로 기동해 둡니다. nginx 는 /root/ng 를 prefix 로 씁니다.
  2. /root/ng/nginx.confupstream app 블록을 만들어 127.0.0.1:8080127.0.0.1:8082 를 넣고, 8088 의 / 가 이 그룹으로 프록시되게 합니다. log_format$upstream_addr 를 반드시 포함시키고 액세스 로그를 /root/ng/logs/access.log 로 보냅니다. http://127.0.0.1:8088/version 이 200 이어야 합니다.
  3. 요청을 20회 보낸 뒤 액세스 로그를 /root/ng/rr.log 로 복사합니다. 서로 다른 업스트림 주소가 2개 이상 기록돼야 합니다.
  4. 127.0.0.1:8080weight=3 을 주고 reload 한 뒤, 액세스 로그를 비우고 요청을 40회 보낸 다음 /root/ng/weight.log 로 복사합니다. 8080 으로 간 요청이 28~32회 사이여야 합니다.
  5. 분배 방식을 ip_hash 로 바꾸고 reload 한 뒤, 로그를 비우고 요청을 20회 보낸 다음 /root/ng/iphash.log 로 복사합니다. 업스트림 주소가 한 종류만 기록돼야 합니다.
  6. ip_hash제거하고(설정 파일에 남아 있으면 안 됩니다), 두 서버 모두에 max_fails=2 fail_timeout=10s 를 설정합니다. 그런 다음 8082 프로세스를 정지시키고 요청을 10회 보냅니다. 10회 모두 200 이어야 합니다.
  7. 업스트림 Keep-Alive 를 설정합니다. upstream 블록에 keepalive 32;, location 에 proxy_http_version 1.1;proxy_set_header Connection "";. 세 가지가 모두 있어야 합니다.
  8. upstream 블록에 least_conn; 을 추가하고 문법 검사를 통과시킵니다.
  9. /root/ng/lb.md 를 작성합니다. 라운드로빈, 가중치, ip_hash, least_conn 네 방식에 대해 각각 언제 쓰는지와 언제 쓰면 안 되는지를 적습니다. 세션 이라는 단어가 반드시 등장해야 하고, 전체 400자 이상이어야 합니다.

참고

업스트림 그룹 구성

/root/ng/nginx.confupstream app 블록을 만들어 127.0.0.1:8080127.0.0.1:8082 를 넣고, 8088 의 / 가 이 그룹으로 프록시되게 합니다. log_format$upstream_addr 를 반드시 포함시키고 액세스 로그를 /root/ng/logs/access.log 로 보냅니다. http://127.0.0.1:8088/version 이 200 이어야 합니다.

upstream 블록은 http 컨텍스트에 둡니다. proxy_pass 에서 그 이름을 URL 처럼 씁니다. 두 백엔드를 모두 기동해 두는 것을 잊지 마세요.

라운드로빈 분배 확인

요청을 20회 보낸 뒤 액세스 로그를 /root/ng/rr.log 로 복사합니다. 서로 다른 업스트림 주소가 2개 이상 기록돼야 합니다.

어느 백엔드로 갔는지는 액세스 로그의 업스트림 주소 변수로 알 수 있습니다. 요청을 충분히 보내고 로그에서 고유 주소 수를 세어 보세요.

가중치 분배

127.0.0.1:8080weight=3 을 주고 reload 한 뒤, 액세스 로그를 비우고 요청을 40회 보낸 다음 /root/ng/weight.log 로 복사합니다. 8080 으로 간 요청이 28~32회 사이여야 합니다.

nginx 의 가중 라운드로빈은 무작위가 아니라 결정적입니다. 가중치 비율이 그대로 분배 비율이 됩니다.

세션 고정

분배 방식을 ip_hash 로 바꾸고 reload 한 뒤, 로그를 비우고 요청을 20회 보낸 다음 /root/ng/iphash.log 로 복사합니다. 업스트림 주소가 한 종류만 기록돼야 합니다.

같은 클라이언트를 같은 백엔드로 보내는 방식입니다. 세션을 WAS 메모리에 두는 레거시 시스템에서 자주 씁니다. 서버가 추가·제거되면 재분배가 일어난다는 단점도 기억하세요.

장애 서버 자동 제외

ip_hash제거하고(설정 파일에 남아 있으면 안 됩니다), 두 서버 모두에 max_fails=2 fail_timeout=10s 를 설정합니다. 그런 다음 8082 프로세스를 정지시키고 요청을 10회 보냅니다. 10회 모두 200 이어야 합니다.

nginx 오픈소스판은 능동 헬스체크가 없고, 실패 횟수 기반의 수동 방식만 있습니다. 백엔드 하나를 실제로 내려 보고 서비스가 유지되는지 확인하세요.

업스트림 Keep-Alive

업스트림 Keep-Alive 를 설정합니다. upstream 블록에 keepalive 32;, location 에 proxy_http_version 1.1;proxy_set_header Connection "";. 세 가지가 모두 있어야 합니다.

세 가지를 함께 설정해야 동작합니다. 하나만 빠져도 매 요청마다 새 커넥션이 생깁니다. 특히 Connection 헤더를 어떻게 처리해야 하는지가 함정입니다.

최소 연결 방식

upstream 블록에 least_conn; 을 추가하고 문법 검사를 통과시킵니다.

요청 처리 시간 편차가 큰 서비스에서 라운드로빈보다 나은 이유를 생각해 보세요.

분배 알고리즘 선택 기준 정리

/root/ng/lb.md 를 작성합니다. 라운드로빈, 가중치, ip_hash, least_conn 네 방식에 대해 각각 언제 쓰는지와 언제 쓰면 안 되는지를 적습니다. 세션 이라는 단어가 반드시 등장해야 하고, 전체 400자 이상이어야 합니다.

각 방식의 장점만 적으면 문서가 아닙니다. 언제 쓰면 안 되는지를 함께 적어야 나중에 판단에 쓸 수 있습니다.