본문 바로가기

DevOps/NGINX

NGINX MSA 디지털 트레이닝 - 3강 : Load Balancing

반응형

강의 동영상 : https://www.youtube.com/watch?v=sLoBvXNPTmk
원본 동영상 : https://www.youtube.com/watch?v=a41jxGP9Ic8

1. What is Load Balancing

1.1 Definition

Load Balancing is defined as the methodical and efficient distribution of network and application traffic across multiple servers in a server farm.

그림과 같이 Load Balancer는 클라이언트와 백엔드 서비스 사이에 위치해서 클라이언트로부터 Request를 받아 해당 Request를 수행할 수 있는 upstream 서비스 또는 Instance로 전달하는 역할을 수행한다

1.2 HTTP Load Balancing in NGINX

  • Client Request를 처리할 Server pool 혹은 group을 설정
  • proxy_pass 명령어를 통해 Client Request가 전달될 Server Pool이나 group을 지정.
  • Server는 IP address + Port number, Domain Name 또는 Unix Socket 으로 정의됨.

2. Load Balancing Configuration

2.1 주요 Directives

  • upstream

    • Server pool 설정
    • HTTP Context 내에 위치
  • proxy_pass

    • request를 정의된 upstream으로 전달.
  • Ex)

    upstream backend_servers { 
        server 192.168.10.1:9001; 
        server 192.168.10.2:9001; 
    } 
    server { 
        listen 80; 
        location / { 
                proxy_pass  http://backend_servers; 
         } 
    }
    • Line 1~4 : 10.1.1.4:9001, 10.1.1.5:9001 두 대의 Backend Server를 backend_servers라는 이름의 pool로 정의.
    • Line 5~10 : 80 port의 root path로 요청된 request를 backend_servers로 정의된 pool로 전달.

2.2 Load Balancing 방식

  • Round Robin
    • Default 방식. 각각의 Request들이 Server Group에 속한 개별 서버로 고르게 전달된다.
    • Ex) 192.168.10.1~3 3개의 서버에 차례대로 Request가 전달되게 된다.
    • upstream backend_servers { server 192.168.10.1:9001; server 192.168.10.2:9001; server 192.168.10.3:9001; }
  • Server Weights
    • 각각의 서버들이 가진 가중치를 더한 후에 (각 서버의 가중치) / (총 가중치) 만큼 개별 서버로 Request들이 분산 전달된다.
    • Ex) 각각 5,3,2의 가중치가 있고 20번의 Request가 오면 192.168.10.1에게 10개(=20 * 5 / (5+3+2))의 Request가 전달되고 192.168.10.2에게 6개(=20 * 3 / (5+3+2)), 192.168.10.3에게 4개(=20 * 2 / (5+3+2))의 Request가 전달되게 된다.
    • upstream backend_servers { server 192.168.10.1:9001 weight=5; server 192.168.10.2:9001 weight=3; server 192.168.10.3:9001 weight=2; }

2.3 Load Balancing 중 Fail 처리

  • Server Pool에 포함된 서버들 중에서 응답하지 않는 것으로 확인되는 서버를 제외할 수 있다.

  • max_fails : 최대 연결 시도 횟수를 저정.. 이 횟수만큼 서버가 응답이 없으면 죽은 것으로 가정해서 Request 전달에서 제외된다.

  • fail_timeout : 최대 연결 실패에 대한 시간 제한 지정 및 다시 재시도 하기까지 Request를 전달하지 않는 시간 지정

  • Ex) 192.168.10.1은 최대 90초 내에 10번의 연결 시도가 실패하게 되면 해당 서버는 죽은 것으로 가정하고 90초 동안은 다시 연결 시도를 하지 않게 된다.

    upstream backend_servers {
        server 192.168.10.1:9001 weight=5 max_fails=10 fail_timeout=90s;
        server 192.168.10.2:9001 weight=3 max_fails=4 fail_timeout=60s; 
        server 192.168.10.3:9001 weight=2 max_fails=2 fail_timeout=30s;
    }

2.4 Advanced Load Balancing in NGINX

  • hash

    • MD5 hash algorithm을 사용해서 Client request 중 하나를 key로 해서 Hash 겂을 계산 하고 그 값에 따라 특정한 서버로 Request전달.

    • Frontend 요청 보다는 backend나 Firewall 뒤에서 사용.

    • Remark : 세션 정보를 유지할 수 있기 때문에 새로운 Server가 추가되거나 기존 서버가 제거될 때는 Hash값이 손상되면서 세션 정보가 손실된다.

    • Ex) Request URI를 기반으로 한 경우 : target URI가 /api/a면 Request가 모두 1번 서버로 전달되고, target URI가 /api/b면 모두 3번 서버로 전달된다.

      upstream backend_servers {
          hash $request_uri;
          server 192.168.10.1:9001;
          server 192.168.10.2:9001;
          server 192.168.10.3:9001;
      }

  • ip_hash

    • 위의 hash와 동일. 단 Client IP를 key로 해서 Hash 값을 생성.

    • Client IP를 key로 사용하기 때문에 특정 Client에서 오는 요청을 특정 Server가 다 처리하게 된다.

    • Remark : 앞단에 Reverse Proxy와 같은 것이 있을 경우 모든 요청이 하나의 서버로만 전달되는 문제가 발생할 수 있음.

    • Ex) 아래와 같이 설정할 경우, 그 아래 그림처럼 A,D 사용자가 보낸 Request는 모두 1번 서버로, B가 보낸 Request는 모두 2번 서버로, C가 보낸 Reques는 모두 3번 서버로 전달하는 식으로 동작한다.

      upstream backend_servers {
          ip_hash;
          server 192.168.10.1:9001;
          server 192.168.10.2:9001;
          server 192.168.10.3:9001;
      }

  • least_conn

    • consecutive connection의 수가 가장 적은 서버로 Request를 전달

    • 연결 수가 동일한 경우 round robin 방식에 의해 서버가 선택됨.

    • Remark. weight가 설정되었을 경우 weight 값을 고려해서 최소 연결수를 계산함. 가중치 1인 1번 서버에 5개의 연결이 있고, 가중치 2인 2번 서버에 8개의 연결이 있으면 (5 / 1) > (8 / 2) 이기 떄문에 2번 서버로 Request가 전달된다.

    • Ex)

      upstream backend_servers {
          least_conn;
          server 192.168.10.1:9001;
          server 192.168.10.2:9001;
          server 192.168.10.3:9001;
      }
  • least_time (NGINX Plus 만 지원)

    • 평균 Response Time이 가장 빠르고 Active Connection 수가 가장 적은 서버로 Request를 전달.

    • 평균 Response Time을 측정할 때 사용하는 인자들에는 다음과 같은 것들이 있다.

      • header : Server에서 첫번째 Byte가 도착하는 시간
      • last_byte : Server에서 전체 Response가 도착하는 시간
      • last_byte inflight : 불완전한 request를 고려해서 Server에서 전체 Response가 도착하는 시간
    • Ex) least_time을 header로 설정한 경우

      upstream backend_servers {
          least_time header;
          server 192.168.10.1:9001;
          server 192.168.10.2:9001;
          server 192.168.10.3:9001;
      }
  • random (NGINX Plus 만 지원)

    • Server를 Random하게 선택해서 Request를 전달.

2.5 Session Persistence

  • NGINX plus에서 제공되는 기능으로 사용자 Session을 식별하고 해당 Session의 요청을 동일한 Server로 라우팅 하는 것을 의미
  • Session Persistence는 'sticky'명령어를 사용해서 3가지 방법으로 제공된다

2.5.1 sticky cookie

  • 맨처음 upstream group response에 대해 Cookie를 추가해서 특정 서버를 식별하고, Client의 다음 Request에서 이 Cookie를 사용할 때 응답을 보낸 Server로 다시 전달될 수 있게 한다.
  • Ex) srv_id라는 Cookie를 설정하고 1시간동안 유지되며, 쿠키를 설정한 Domain과 Path를 정의한 예
  • upstream backend_servers { server 192.168.10.1:9001; server 192.168.10.2:9001; server 192.168.10.3:9001; sticky cookie srv_id expires=1h domain=.abc.com path=/; }
  • Demo에서 lb_example로 정의된 Cookie를 설정해서 Client로 보낸 경우

2.5.2 sticky route

  • 클라이언트로부터의 첫 요청에 대해 "Route"를 할당하고, 이후 요청을 route 인자의 paramter와 비교해서 서버를 식별한다.

  • Route 정보는 cookie나 request URI로부터 가져온다.

  • Ex)

    upstream backend_servers {
            server 192.168.10.1:9001;
            server 192.168.10.2:9001;
            server 192.168.10.3:9001;
            sticky route $route_cookie $route_uri;
    }

2.5.3 sticky learn (?)

  • Request와 Response를 검사해 Session Identifier를 찾고, 이게 어떤 Server와 관련있는 지 "학습"하게 된다.

  • 일반적으로 이런 identifier가 HTTP cookie로 전달되고, 이 값을 통해 해당 Server로 Request가 전달됨.

  • Ex)

    upstream backend_servers {
        server 192.168.10.1:9001;
        server 192.168.10.2:9001;
        server 192.168.10.3:9001;
        sticky learn
                create=$upstream_cookie_examplecookie
                lookup=$cookie_examplecookie
                zone=client_sessions:1m
                timeout=1h
    }

2.6 기타

  • max_conns : 서버가 처리할 수 있는 최대 동시 연결 수를 설정
  • queue : max_conns로 설정한 최대 동시 연결 수를 넘어서 처리되지 않은 요청을 대기 시키는 Queue.
  • Ex)
    • 192.168.10.1은 최대 300개의 연결을 지원하고, 그 이상의 Request중 100개를 queue에 대기시킴.
    • Queue에 대기 상태로 있는 Request 중 70초를 넘는 Request는 HTTPS Status Code 503이 Client에 전달되게 됨.
  • upstream backend_servers { server 192.168.10.1:9001 max_conn=300; server 192.168.10.2:9001; server 192.168.10.3:9001; queue 100 timeout=70; }

3. Demo에서 기록할만한 사항들

  • HTTP Custom Header 추가 : 해당 서버의 ID (Application 1) 정보를 포함한 Response Header 추가

    server {
        listen    9001;
        index   index.html;
        add_header   Custom-Header   "Applicaion 1";
        ...
    }
  • curl -sI [ip-address:port | domain name] : Http Response Data를 제외한 Header 부분만 확인

  • 반복 Request 예제

    while true; do curl -sI <load-balancer-ip:port> | tr -d '\r' | sed -En 's/^Custom-Header: (.*)/\1/p'; sleep 1; done