nginx proxy serving 이슈

JUNE 15, 2024

1. 구조 파악

구조가 좀 복잡하다…

  1. 모바일에서 요청시에 제일 먼저 webapp nginx 로 요청이 들어오고
  2. 사용자 인증을 위해 에서 kakaotalk pilsner server 프록시 하고
  3. pilsner 서버에서 계정 인증 후 webapp server 로 또 프록시 된다.
  4. 그리고 webapp으로 프록시된 요청은 실제 api 서버로 요청을 하게된다.

요청 흐름도)

모바일webapp server -(proxy)→ 필스너 서버 -(proxy)→ webapp server -(proxy)→ 디지털카드 api server

응답 흐름도)

디지털카드 api server -(proxy res)→ webapp server -(proxy res)→ 필스너서버 -(proxy res)→ webapp server → 모바일

02 001


2. 이슈 내용

  • 간헐적으로 모바일에서만 정적파일(js, css, html) 서빙시에 타임아웃 발생 또는 css가 깨진 화면이 노출

3. 원인

  • talk-pilsner OS upgrade를 작업을 위해 gslb 내 vip 하나를 Down 하였고,
  • webapp nginx 는 talk-pilsner dns의 변경사항을 감지하고 못하고 down 된 vip로 요청.
  • nginx는 proxy pass 할 talk-pilsner 도메인의 vip 목록을 서버 실행시 캐싱하여 계속 사용하기 때문에 down된 vip로 요청

02 002


4. 조치 내용

  • dns resolve 설정을 추가하여 talk-pilsner 도메인의 ip를 주기적으로 가져오도록 설정
  • 인증이 불필요한 정적 파일은 talk-pilsner를 타지 않도록 수정.
resolver 10.20.30.40 valid=10s;
 
server {
    location / {
        set $talk_pilsner "talk-pilsner.kakao.com";
        proxy_pass http://$talk_pilsner;
    }
}

5. 참고 내용 - nginx 에서 도메인명을 이용하여 서비스를 검색하는 방법

5-1. proxy_pass 지시어에 도메인명 사용

가장 간단한 방법이지만 가장 유연성이 떨어지는 방법이며 다음과 같은 단점이 있다.

  • 도메인 이름을 확인할 수 없는 경우 서버가 실행되지 않는다.
  • 재시작 할때까지 DNS 레코드를 캐시하고 레코드의 TTL도 무시한다.
  • 로드 밸런싱 알고리즘을 지정할 수 없다.
server {
    location / {
        proxy_pass http://talk-pilsner.kakao.com;
    }
}

5-2. Upstream Server Group에 도메인명 사용

로드 밸런싱 알고리즘을 지정할 수 있다. (ex> least_conn)

max_fails 를 지정하여 연속 요청이 지정한 횟수에 다다르면 서버가 다운 된것으로 표시.

다음과 같은 단점이 여전히 존재

  • 도메인 이름을 확인할 수 없는 경우 서버가 실행되지 않는다.
  • 재시작 할때까지 DNS 레코드를 캐시하고 레코드의 TTL도 무시한다.
upstream talk_pilsner {
    least_conn;
 
    server talk-pilsner.kakao.com max_fails=3;
}
 
server {
    location / {
        proxy_pass http://talk_pilsner;
    }
}

5-3. 변수에 도메인 이름 지정

도메인 이름을 다시 확인하는 빈도를 제어할 수 있다.

resolver valid 설정을 통해 지정된 시간마다 도메인 이름을 다시 확인 하도록 할수 있다.

도메인 이름을 확인 할 수 없을때 nginx 재시작 없이 서비스 탐색을 재시도 하기때문에 첫번째 방법의 두가지 단점을 보완할수 있다.

단, 로드 밸런싱 알고리즘을 지정 할 수 없다.

nginx plus를 사용하지 않는다면 가장 유연성이 높은 방법이다.

resolver 10.20.30.40 valid=10s;
 
server {
    location / {
        set $talk_pilsner "talk-pilsner.kakao.com";
        proxy_pass http://$talk_pilsner;
    }
}

작업 기록 블로그