당사는 최적의 가용성과 안정성을 위해 웹사이트와 앱의 로드 밸런싱을 위해
NGINX Plus와 NGINX 오픈소스를 사용하는 방법에 대해 많은 글을 작성했습니다.
로드 밸런싱는 앱 성능 향상, 규모에 맞는 앱 제공, 컨테이너 및 마이크로서비스 배포를 위한 기본 도구입니다.
이전에는 데이터 센터(레거시 애플리케이션 전송 컨트롤러와 함께), 컨테이너 및 아마존을 포함한
클라우드 환경에서 NGINX Plus를 배포하는 방법에 대해 설명한 적이 있습니다;
웹 서비스(AWS), 구글 클라우드 플랫폼, 마이크로소프트 애저 등 클라우드 환경에서도 마찬가지입니다.
이 글에서는 로드 밸런싱 방법 또는 알고리즘이라고도 하는 NGINX Plus 및 NGINX의 부하 분산 기술에
중점을 두고 다양한 사용 사례에 적합한 방법을 선택하는 방법에 대한 몇 가지 조언을 제공하겠습니다.
NGINX는 네 가지 로드 밸런싱 기술(Round Robin, Hash, IP Hash, 최소 연결),
NGINX;Plus는 하나 더 추가합니다(최소 시간).
HTTP 트래픽에 대한 모든 메서드는 IP 해시를 제외한 TCP(및 NGINX Plus 릴리스 9 이상에서는 UDP)에서도 사용할 수 있습니다.
[편집자 - NGINX Plus R16 및 NGINX Open Source 1.15.1에서는
추가 로드 밸런싱 알고리즘으로 두 가지 선택지가 있는 랜덤을 도입했습니다.
자세한 내용은 블로그의 NGINX와 "두 가지 선택의 힘" 부하 분산 알고리즘을 참조하세요.
로드 밸런싱 기술 검토
로드 밸런싱 구성 방법의 기본 사항을 알고 있다고 가정하지만 다시 한 번 살펴보고 싶으시면 다음 리소스를 확인하세요:
- NGINX Plus 관리자 가이드에 있는 문서에서 전체 개요를 확인할 수 있습니다.
- 고성능 부하 분산는 부하 분산 방법의 효율성을 더욱 향상시킬 수 있는
- NGINX Plus의 향상된 기능에 대한 자세한 설명으로 연결되는 링크입니다.
- NGINX 및 NGINX Plus를 사용한 로드 밸런싱, 1부 및 2부는 간단한 리버스 프록시를
- NGINX Plus의 향상된 기능을 갖춘 종합적인 로드 밸런싱 솔루션으로 구축하는 과정을 안내해 줍니다.
- 로드 밸런싱 솔루션 페이지에는 전자책, 웨비나, 백서 등 다른 리소스로 연결되는 링크가 있습니다.
여기서는 간단하게 설명하기 위해 http 컨텍스트에서 구성하는 HTTP 부하 분산에 중점을 두겠습니다.
TCP 부하 분산은 대신 stream 컨텍스트에서 구성됩니다(NGINX Plus 릴리스 9 이상에서 UDP 부하 분산과 마찬가지로).
HTTP 및 TCP/UDP 부하 분산 장치에는 기능 패리티가 있지만
프로토콜 간의 고유한 차이로 인해 사용 가능한 지시어와 매개 변수가 다소 다릅니다.
자세한 내용은 HTTP 및 TCP/UDP의 업스트림 모듈에 대한 설명서를 참조하세요.
선택적 매개변수나 보조 기능 없이 기본 형태로 보여드리는 두 가지 구성 블록으로 부하 분산을 활성화할 수 있습니다:
서버 블록은 사용자가 정의한 특성을 가진 트래픽을 수신하는 가상 서버를 정의하고 이를 지정된 업스트림 서버 그룹에 프록시합니다. 이 예제에서는 가상 서버가 기본 포트(80)에서 www.example.com로 전송되는 HTTP 트래픽을 수신하고 이를 backend라는 업스트림 서버 그룹에 프록시합니다. 이 블록은 모든 예제에서 동일합니다.
server { server_name www.example.com;
location / {
proxy_pass http://backend;
}
}(NGINX Plus와 NGINX는 FastCGI, memcached, SCGI 및 uwsgi 백엔드 서버도 로드 밸런싱할 수 있습니다.
proxy_pass를 적절한 지시어로 바꿉니다;- fastcgi_pass, memcached_pass, scgi_pass, 또는 uwsgi_pass.)
업스트림 블록은 업스트림 그룹의 이름을 지정하고 호스트 이름,
IP 주소 또는 UNIX 도메인 소켓 경로로 식별되는 해당 그룹에 속하는 서버를 나열합니다.
이 예제에서 backend라는 업스트림 그룹에는 3개의 서버가 포함되어 있습니다: web1, web2, web3입니다.
업스트림 블록은 로드 밸런싱 기술을 지정하는 곳이므로 다음 섹션에서 이 부분을 중점적으로 설명하겠습니다.
예를 들어 기본 방법인 라운드 로빈에 대한 블록은 다음과 같습니다:
upstream backend { server web1;
server web2;
server web3;
}라운드 로빈
라운드 로빈은 NGINX와 NGINX 모두의 기본 로드 밸런싱 기술입니다.
로드 밸런서는 업스트림 서버 목록을 순차적으로 실행하여 각 서버에 다음 연결 요청을 차례로 할당합니다.
다음 샘플 구성의 backend 업스트림 그룹에서 로드밸런서는 처음 세 개의 연결 요청을 web1으로 보냅니다,
web2, web3, 네 번째는 web1, 다섯 번째는 web2 순으로 차례로 전송합니다.
upstream backend { server web1;
server web2;
server web3;
}
server {
server_name www.example.com;
location / {
proxy_pass http://backend;
}
}Hash
해시 방식을 사용하면 각 요청에 대해 로드밸런서는 사용자가 지정한 텍스트와 NGINX 변수의 조합을 기반으로 해시를 계산하고
이 해시를 서버 중 하나에 연결합니다.
해당 해시를 가진 모든 요청을 해당 서버로 전송하므로 이 방법은 기본적인 종류의 세션 지속성를 설정합니다.
upstream backend { hash $scheme$request_uri;
server web1;
server web2;
server web3;
}
server {
server_name www.example.com;
location / {
proxy_pass http://backend;
}
}IP 해시
IP 해시(HTTP에만 사용 가능)는 해시 메서드의 사전 정의된 변형으로,
해시는 클라이언트의 IP 주소를 기반으로 합니다.
ip_hash 지시어를 사용하여 설정합니다.
upstream backend { ip_hash;
server web1;
server web2;
server web3;
}
server {
server_name www.example.com;
location / {
proxy_pass http://backend;
}
}클라이언트에 IPv6 주소가 있는 경우 해시는 전체 주소를 기반으로 합니다.
IPv4 주소가 있는 경우 해시는 주소의 처음 세 옥텟만 기반으로 합니다.
이는 서브네트워크(/24) 범위에서 동적으로 IP 주소를 할당받는 ISP 클라이언트에 최적화하도록 설계되었습니다.
재부팅 또는 재접속 시 클라이언트의 주소가 /24 네트워크 범위의 다른 주소로 변경되는 경우가 많지만
연결은 여전히 동일한 클라이언트를 나타내므로 서버에 대한 매핑을 변경할 이유가 없습니다.
그러나 사이트에 대한 대부분의 트래픽이 동일한 /24 네트워크에 있는 클라이언트에서 발생하는 경우
모든 클라이언트를 동일한 서버에 매핑하기 때문에 IP 해시는 의미가 없습니다.
이 경우(또는 다른 이유로 4개의 옥텟을 모두 해시하려는 경우) 대신 $remote_addr 변수와 함께 해시 방법을 사용하세요.
hash $remote_addr;
최소 연결 수
최소 연결 방법을 사용하면 로드밸런서가 각 서버에 대한 현재 활성 연결 수를 비교하여 연결 수가 가장 적은 서버로 요청을 보냅니다. least_conn 지시어를 사용하여 구성할 수 있습니다.
upstream backend {
least_conn;
server web1;
server web2;
server web3;
}
server {
server_name www.example.com;
location / {
proxy_pass http://backend;
}
}최소 시간
최단 시간 방법(NGINX 'Plus에서만 사용 가능)을 사용하면 로드 밸런서가
각 서버에 대해 현재 활성 연결 수와 과거 요청에 대한 가중 평균 응답 시간이라는
두 가지 메트릭을 수학적으로 결합하여 가장 낮은 값을 가진 서버로 요청을 보냅니다.
최소_시간 지시문에서 선택한 파라미터는 응답 헤더 수신 시간(header) 또는 전체 응답 수신 시간(last_byte
upstream backend { least_time (header | last_byte);
server web1;
server web2;
server web3;
}
server {
server_name www.example.com;
location / {
proxy_pass http://backend;
}
}주석:
TCP 및 UDP 부하 분산(stream 컨텍스트에서)의 경우, least_time 지시어에 이러한 파라미터를 사용하여
3가지 유형의 응답 시간 중에서 선택할 수 있습니다:
- connect - 업스트림 서버에 연결할 시간
- first_byte - 응답 데이터의 첫 바이트를 수신한 시간
- last_byte - 응답 데이터의 마지막 바이트를 수신한 시간
- HTTP 및 TCP/UDP 트래픽 모두에 대해 NGINX Plus R12 이상에서는 각 메트릭에 불완전한 연결을 포함하도록 inflight 매개 변수를 추가하면 이전 릴리스에서 이러한 연결이 기본으로 포함됩니다.
로드 밸런싱 기술 선택
그렇다면 어떤 부하 분산 기술이 웹사이트나 앱에 가장 적합한지 어떻게 알 수 있을까요?
트래픽 패턴은 사이트마다, 심지어 한 사이트 내에서도 하루 중 시간대별로 매우 다양하기 때문에 한 가지 특성(예: 트래픽 폭주 대 안정적, 단시간 연결 대 장기 연결 등)을 기준으로 부하 분산 기술을 선택하는 것은 합리적이지 않습니다. 하지만 고려해야 할 선택의 범위를 좁히는 데 도움이 되도록 각 방법의 장단점을 고려하겠습니다.
테스트 실행을 통한 방법 비교
로드 밸런싱 방법의 하위 집합을 고려할 때 어떤 방법이 트래픽에 가장 적합한지 테스트해 보는 것이 좋습니다.
"최적"이란 일반적으로 클라이언트에 응답을 전송하는 데 걸리는 시간이 가장 짧은 것을 의미하지만 다른 기준이 있을 수 있습니다.
애플리케이션 성능 관리 도구는 이러한 종류의 테스트에 매우 유용합니다.
업스트림 그룹의 각 서버에 대한 그래프가 포함된 사용자 지정 화면을 만들어 테스트 중에 값이 변경될 때 실시간으로 비교할 수 있습니다.
AppDynamics, Datadog, Dynatrace, New Relic 등 여러 APM에서 NGINX Plus 및 NGINX용 사용자 정의 플러그인을 제공합니다.
모든 서버의 용량이 동일한 경우 테스트가 가장 간단합니다.
그렇지 않은 경우 용량이 더 큰 서버가 더 많은 요청을 받도록 서버 가중치를 설정해야 합니다.
아래의 서버가 동일하지 않을 때 가중치 설정하기를 참조하세요.
테스트 중에 확인해야 할 몇 가지 메트릭은 다음과 같습니다:
CPU 및 메모리 로드 - CPU와 메모리 모두에 대해 사용된 총 용량의 비율을 확인합니다.
모든 서버가 균등하게 로드되지 않는다면 트래픽이 효율적으로 분산되지 않는 것입니다.
서버 응답 시간 - 일부 서버의 응답 시간이 다른 서버보다 지속적으로 더 길다면,
더 많은 계산이나 데이터베이스 또는 기타 서비스 호출이 필요한
"무거운" 요청이 불균형하게 해당 서버로 전달되고 있는 것입니다.
부하 분산 기술의 문제라기보다는 잘못된 가중치로 인해 불균형이 발생할 수 있으므로 가중치를 조정해 보세요.
클라이언트에 응답하는 총 시간 - 일부 서버의 시간이 지속적으로 높다는 것은 시간이 많이 걸리는 요청이
불균형적으로 많이 접수되고 있음을 의미합니다. 다시 한 번 가중치를 조정하여 문제가 해결되는지 확인할 수 있습니다.
오류 및 실패한 요청 - 테스트 중 실패한 요청 및 기타 오류의 수가 사이트의 평소보다 많지 않은지 확인해야 합니다.
그렇지 않으면 실제 트래픽이 아닌 오류 조건을 기준으로 결정을 내리게 됩니다.
일부 오류의 경우 서버는 요청이 성공할 때보다 더 빨리 응답을 보낼 수 있습니다.
예를 들어 HTTP 응답 코드 404(파일 없음 찾음)의 경우
서버는 실제 파일이 존재한다면 전송할 수 있는 것보다 훨씬 빠르게 오류를 반환할 수 있을 것입니다.
최소 연결 및 최소 시간 부하 분산 알고리즘을 사용하면 로드 밸런서가 실제로는 제대로 작동하지 않는 서버를 선호하게 될 수 있습니다.
장단점 및 사용 사례
이제 각 부하 분산 기술의 장단점을 살펴보고 특히 적합한 몇 가지 사용 사례를 설명해 보겠습니다.
대부분의 사용 사례에 적합성이 높은 순서대로 설명하겠습니다.
간단히 미리 말씀드리자면, 가장 광범위한 사용 사례에 가장 적합한 옵션은 최소 연결(및 NGINX의 경우 최소 시간)이라고 생각합니다.
해시 및 IP 해시
해시 및 IP 해시 부하 분산 기술은 특정 유형의 클라이언트 요청(해시 값에 캡처됨)과 특정 서버 간에 고정 연결을 생성합니다.
이를 세션 지속성이라고 할 수 있는데, 주어진 해시 값을 가진 모든 요청은 항상 동일한 서버로 이동합니다.
이러한 방법의 가장 큰 단점은 부하를 균등하게 분산하는 것은 물론 서버 간에 요청을 동일한 수로 분배한다는 보장이 없다는 것입니다.
해싱 알고리즘은 가능한 모든 해시 값 집합을 업스트림 그룹의 각 서버에 하나씩 '버킷'으로 균등하게 나누지만
실제로 발생하는 요청에 균등하게 분산된 해시가 있는지 예측할 수 있는 방법이 없습니다.
예를 들어 10개의 클라이언트가 한 사이트에 접속하고 있는데
IP 해시 알고리즘이 그 중 7개 IP 주소의 해시를 web1에, 1개는 web2에, 2개는 web3에 연관시키는 경우가 있다고 가정해 보죠.
web1 서버는 다른 서버를 합친 것보다 두 배 이상 많은 요청을 받게 됩니다.

따라서 세션 유지의 이점이 불균형한 부하로 인한 나쁜 영향보다
클 때는 해시 또는 IP를 사용하는 것이 좋습니다.
이는 NGINX에서 사용할 수 있는 유일한 세션 지속성 형태입니다.
NGINX는 더 정교하고 실제 로드 밸런싱과 함께 작동하는
세 가지 다른 세션 지속성 메커니즘을 제공합니다(sticky 지시어로 구성하면 됩니다).
그러나 다음과 같은 경우에는 세 가지 메커니즘이 작동하지 않으므로
NGINX를 사용하더라도 해시 또는 IP를 선택할 수 있습니다:
브라우저 또는 클라이언트 앱이 쿠키를 허용하지 않고, 애플리케이션에 쿠키 없이 세션 지속성 메커니즘을 사용할 수 있는 방법이 없는 경우. 각 클라이언트(특히 IP 주소)를 특정 서버와 연결하려면 IP 해시 방법을 사용합니다.서버 자체의 캐싱을 활용하기 위해 특정 URL에 대한 요청을 매번 동일한 서버로 보내려고 합니다.
매번 같은 서버에서 파일을 가져오려면 $request_uri 변수와 함께 해시 메서드를 사용하세요.
예를 들어 특정 .php 파일을 제공하는 데 시간이 많이 걸리는 데이터베이스 호출이 여러 번 필요하지만 가져온 데이터는 자주 변경되지 않으므로 캐시가 가능하다고 가정해 보겠습니다. 파일에 대한 모든 요청을 동일한 서버로 보내면 첫 번째 클라이언트만 데이터베이스 호출로 인해 긴 지연 시간을 경험하게 됩니다. 이후의 모든 클라이언트는 캐시에서 데이터를 빠르게 검색할 수 있습니다.
또 다른 장점은 하나의 서버만 특정 데이터 집합을 캐시하면 된다는 것입니다. 모든 서버에서 동일한 데이터를 중복 캐싱하지 않으므로 더 작은 캐시를 사용할 수 있습니다.
IP 해시와 클라이언트 IP 주소가 키에 있을 때 해시가 작동하지 않는 경우가 몇 가지 있습니다:
- 예를 들어 모바일 클라이언트가 WiFi 네트워크에서 셀룰러 네트워크로 전환할 때와 같이
- 세션 중에 클라이언트의 IP 주소가 변경될 수 있는 경우입니다.
- 많은 클라이언트의 요청이 정방향 프록시를 통과하는 경우, 프록시의 IP 주소가 모든 클라이언트에 사용되기 때문입니다.
해시는 결정론적입니다(해싱 알고리즘은 매번 동일한 결과를 산출합니다). 여기에는 몇 가지 긍정적인 측면이 있습니다.
배포의 모든 NGINX Plus 또는 NGINX 인스턴스가 정확히 동일한 방식으로 부하 분산 요청을 하고,
로드 밸런서를 다시 시작할 때에도 해시 대 서버 매핑이 지속된다는 점입니다.
(실제로는 재시작 후 다시 계산되지만 결과는 항상 동일하기 때문에 효과적으로 지속됩니다.)
반면에 업스트림 서버 집합을 변경하면 일반적으로 적어도 일부 매핑이 강제로 다시 계산되어 세션 지속성이 깨집니다.
다시 계산되는 매핑의 수를 다소 줄일 수 있습니다:
- 해시 방법의 경우 consistent 매개 변수를 hash 지시어에 포함시키고,
- NGINX Plus는 ketama 해시 알고리즘을 사용하므로 다시 매핑할 일이 줄어듭니다.
IP 해시 방식의 경우, 업스트림 그룹에서 서버를 일시적으로 제거하기 전에
다음 예의 web2처럼 down 파라미터를 server 지시어에 추가합니다. 서버가 곧 서비스를 재개할 것이라는 가정 하에 매핑은 다시 계산되지 않습니다.업스트림 백엔드 { ip_hash; 서버 웹1; 서버 웹2 다운; 서버 웹3; }
라운드 로빈
앞서 언급했듯이 라운드 로빈은 NGINX 및 NGINX의 기본 로드 밸런싱 방법입니다.
따라서 선택하기 가장 쉬운 방법이며 업스트림 그룹 자체 외에는 아무것도 구성할 필요가 없습니다.
일반적으로 라운드 로빈은 서버 및 요청의 특성으로 인해 일부 서버가 다른 서버에 비해 과부하가 걸릴 가능성이 낮을 때
가장 잘 작동한다는 것이 일반적인 의견입니다.
몇 가지 조건은 다음과 같습니다:
- 모든 서버의 용량이 거의 같을 것. 서버 간 차이가 서버 가중치로 정확하게 표현되는 경우 이 요구 사항은 덜 중요합니다.
- 모든 서버가 동일한 콘텐츠를 호스팅합니다.
- 요청에 필요한 시간이나 처리 능력은 거의 비슷합니다.
- 요청 무게에 큰 차이가 있는 경우 부하 분산 장치가 많은 양의 요청을 연속적으로 빠르게 전송하기 때문에
- 서버에 과부하가 걸릴 수 있습니다.
- 트래픽 양이 서버를 거의 최대 용량에 가깝게 밀어붙일 정도로 많지 않습니다.
- 서버가 이미 과부하 상태인 경우, 이전 글머리 기호에서 설명한 대로 Round & amp; Robin이 요청을 무작위로 분산하면
- 일부 서버가 과부하 상태로 '오버 더 에지'될 가능성이 더 높습니다.
라운드 로빈은 요청이 모든 서버에 동일한 수(또는 적절한 가중치 비율)로 분산되도록 보장하기 때문에
테스트 시나리오에 특히 적합합니다.
일부 다른 방법은 트래픽이 적을 때 항상 트래픽을 균등하게 분배하지 않아 테스트 결과가 왜곡될 수 있습니다.
라운드 로빈에서는 특정 파일에 대한 요청을 동일한 서버에 전송할 방법이 없기 때문에
모든 서버가 광범위한 파일(일반적으로 동료 서버와 동일한 파일 다수를 포함)을 서비스하고
캐싱하게 되어 캐시가 가득 찰 가능성이 높습니다.
마지막으로, 초기 배포를 균일하게 하면 NGINX;Plus에서 세션 지속성 문제를 발견하는 데 도움이 됩니다(sticky 지시어로 구성한 대로).
최소 연결 및 최소 시간
위에서 언급했듯이 최소 연결은 가장 광범위한 사용 사례, 특히 프로덕션 트래픽에 가장 적합한 로드 밸런싱 기술입니다.
이는 고객들의 일화를 통해 뒷받침됩니다. 성능은 안정적이고 예측 가능합니다.
또한 최소 연결은 서버의 용량에 따라 워크로드를 효과적으로 분산합니다.
더 강력한 서버는 요청을 더 빨리 처리하므로 특정 순간에는 용량이 적은 서버보다
처리 중인 연결 수가 더 적을 수 있습니다(또는 처리가 시작되기를 기다리는 중일 수도 있음).
최소 연결은 현재 연결 수가 가장 적은 서버로 각 요청을 보내므로 강력한 서버로 요청을 보낼 가능성이 높습니다.
(그러나 아래의 서버가 동일하지 않을 때 가중치 설정에 설명된 대로 가중치를 설정하면 요청을 훨씬 더 효율적으로 분산할 수 있습니다.)
최소 연결 시간(NGINX와 플러스만 해당)은 최소 연결 시간보다 더 민감한 버전이라고 생각할 수 있습니다.
평균 응답 시간을 포함함으로써 서버의 최근 성능 기록을 고려합니다(실제로는 지수 가중 이동 평균이므로 오래된 응답 시간이 최근 응답 시간보다 평균에 덜 영향을 미칩니다).
최소 시간은 업스트림 서버의 평균 응답 시간이 매우 다른 경우에 특히 적합합니다.
예를 들어 재해 복구를 위해 서로 다른 데이터 센터에 서버를 두고 있는 경우,
응답 속도가 빠른 로컬 서버에 더 많은 요청을 보내는 경향이 있습니다.
또 다른 사용 사례는 서버 성능을 예측할 수 없는 클라우드 환경입니다.

서버가 동일하지 않은 경우 가중치 설정하기
업스트림 그룹의 서버 용량이 서로 다른 경우 서버 가중치 설정의 중요성에 대해 여러 번 언급했습니다.
특히 각 서버에 동일한 수의 요청을 전송하는 라운드 로빈 부하 분산 장치에 특히 중요합니다.
이렇게 하면 성능이 낮은 서버는 과부하가 걸리고 성능이 높은 서버는 부분적으로 유휴 상태가 될 수 있습니다.
가중치를 설정하려면 weight 파라미터를 하나 이상의 서버 블록에 업스트림 지시어를 포함시키면 됩니다.
기본값은 1입니다.
다음과 같은 방식으로 다양한 부하 분산 기술에 대한 가중치 설정의 효과를 생각해 볼 수 있습니다.
설명은 개념적으로 정확하지만 NGINX Plus 코드의 구현이 반드시 표시된 수학 연산을 사용하는 것은 아니라는 점에 유의하세요.
다음은 예제의 업스트림 그룹입니다:
upstream backend {
server web1 weight=6;
server web2 weight=3;
server web3;
}로빈 - 각 서버는 들어오는 요청의 백분율을 가중치의 합으로 나눈 값과 동일한 가중치를 가져옵니다.
이 예에서는 10개의 요청 중 web1이 6개(60%), web2가 3개(30%), web3이 1개(10%)를 가져옵니다.
해시 및 IP 해시 - 가중치가 없으면 해시 알고리즘은 가능한 모든 해시 값 집합을 업스트림 그룹의 각 서버에 하나씩 "버킷"으로 균등하게 나눕니다. 가중치를 사용하면 대신 가중치를 합산하여 가능한 해시 집합을 해당 수의 버킷으로 나누고 각 서버를 가중치에 해당하는 버킷 수와 연결합니다. 이 예제에서는 가능한 해시의 10%가 각각 들어 있는 10개의 버킷이 있습니다.
6개 버킷 (사용 가능한 해시의 60%)/ web1에, 3개 버킷(30%) /web2에, 1개 버킷(10%)
최소 연결 수 및 최소 시간 - 앞서 이러한 알고리즘은 가중치가 없어도 서버 용량에 따라 워크로드를 분산하는데는 매우 효과적이라고 언급했습니다. 가중치를 설정하면 이와 관련하여 성능이 훨씬 더 향상됩니다.
최소 연결 및 최소 시간은 각 요청을 가장 낮은 "점수"(각각 연결 수 또는 연결 수와 시간의 수학적 조합)를 가진 서버로 전송한다는 점을 기억하세요. 가중치를 할당하면 부하 분산 장치는 각 서버의 점수를 가중치로 나눈 후 다시 가장 낮은 값을 가진 서버로 요청을 보냅니다.
다음은 샘플 가중치와 표시된 활성 연결 수를 사용한 최소 연결의 예시입니다: web1의 점수가 100으로 가장 낮고 연결 수가 600으로 web2의 1.5배, web3의 4배 이상임에도 요청을 받습니다.
- web1 - 활성 연결 600개 ÷ 6 = 100
- web2 - 활성 연결 400개 ÷ 3 = 133
- web3 - 125개의 활성 연결 ÷ 1 = 125개
요약
NGINX와 NGINX 플러스에서 사용할 수 있는 로드 밸런싱 기술의 장단점을 검토한 결과,
가장 광범위한 사용 사례에 가장 적합한 방법은 최소 연결(그리고 NGINX 플러스의 경우 최소 시간)이라고 생각됩니다.
그러나 트래픽 및 서버 특성의 고유한 조합에 따라 다른 방법이 더 적합할 수 있으므로
배포 시 여러 가지 방법을 테스트하는 것이 중요합니다.
NGINX;Plus 부하 분산 기능을 직접 사용해 보려면
지금 바로 30일 무료 체험판을 시작하거나 문의하여 사용 사례에 대해 문의하세요.
위 내용과 같이 NGINX Plus를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요
'
당사는 최적의 가용성과 안정성을 위해 웹사이트와 앱의 로드 밸런싱을 위해
NGINX Plus와 NGINX 오픈소스를 사용하는 방법에 대해 많은 글을 작성했습니다.
로드 밸런싱는 앱 성능 향상, 규모에 맞는 앱 제공, 컨테이너 및 마이크로서비스 배포를 위한 기본 도구입니다.
이전에는 데이터 센터(레거시 애플리케이션 전송 컨트롤러와 함께), 컨테이너 및 아마존을 포함한
클라우드 환경에서 NGINX Plus를 배포하는 방법에 대해 설명한 적이 있습니다;
웹 서비스(AWS), 구글 클라우드 플랫폼, 마이크로소프트 애저 등 클라우드 환경에서도 마찬가지입니다.
이 글에서는 로드 밸런싱 방법 또는 알고리즘이라고도 하는 NGINX Plus 및 NGINX의 부하 분산 기술에
중점을 두고 다양한 사용 사례에 적합한 방법을 선택하는 방법에 대한 몇 가지 조언을 제공하겠습니다.
NGINX는 네 가지 로드 밸런싱 기술(Round Robin, Hash, IP Hash, 최소 연결),
NGINX;Plus는 하나 더 추가합니다(최소 시간).
HTTP 트래픽에 대한 모든 메서드는 IP 해시를 제외한 TCP(및 NGINX Plus 릴리스 9 이상에서는 UDP)에서도 사용할 수 있습니다.
[편집자 - NGINX Plus R16 및 NGINX Open Source 1.15.1에서는
추가 로드 밸런싱 알고리즘으로 두 가지 선택지가 있는 랜덤을 도입했습니다.
자세한 내용은 블로그의 NGINX와 "두 가지 선택의 힘" 부하 분산 알고리즘을 참조하세요.
로드 밸런싱 기술 검토
로드 밸런싱 구성 방법의 기본 사항을 알고 있다고 가정하지만 다시 한 번 살펴보고 싶으시면 다음 리소스를 확인하세요:
여기서는 간단하게 설명하기 위해 http 컨텍스트에서 구성하는 HTTP 부하 분산에 중점을 두겠습니다.
TCP 부하 분산은 대신 stream 컨텍스트에서 구성됩니다(NGINX Plus 릴리스 9 이상에서 UDP 부하 분산과 마찬가지로).
HTTP 및 TCP/UDP 부하 분산 장치에는 기능 패리티가 있지만
프로토콜 간의 고유한 차이로 인해 사용 가능한 지시어와 매개 변수가 다소 다릅니다.
자세한 내용은 HTTP 및 TCP/UDP의 업스트림 모듈에 대한 설명서를 참조하세요.
선택적 매개변수나 보조 기능 없이 기본 형태로 보여드리는 두 가지 구성 블록으로 부하 분산을 활성화할 수 있습니다:
서버 블록은 사용자가 정의한 특성을 가진 트래픽을 수신하는 가상 서버를 정의하고 이를 지정된 업스트림 서버 그룹에 프록시합니다. 이 예제에서는 가상 서버가 기본 포트(80)에서 www.example.com로 전송되는 HTTP 트래픽을 수신하고 이를 backend라는 업스트림 서버 그룹에 프록시합니다. 이 블록은 모든 예제에서 동일합니다.
server { server_name www.example.com; location / { proxy_pass http://backend; } }(NGINX Plus와 NGINX는 FastCGI, memcached, SCGI 및 uwsgi 백엔드 서버도 로드 밸런싱할 수 있습니다.
proxy_pass를 적절한 지시어로 바꿉니다;- fastcgi_pass, memcached_pass, scgi_pass, 또는 uwsgi_pass.)
업스트림 블록은 업스트림 그룹의 이름을 지정하고 호스트 이름,
IP 주소 또는 UNIX 도메인 소켓 경로로 식별되는 해당 그룹에 속하는 서버를 나열합니다.
이 예제에서 backend라는 업스트림 그룹에는 3개의 서버가 포함되어 있습니다: web1, web2, web3입니다.
업스트림 블록은 로드 밸런싱 기술을 지정하는 곳이므로 다음 섹션에서 이 부분을 중점적으로 설명하겠습니다.
예를 들어 기본 방법인 라운드 로빈에 대한 블록은 다음과 같습니다:
upstream backend { server web1; server web2; server web3; }라운드 로빈
라운드 로빈은 NGINX와 NGINX 모두의 기본 로드 밸런싱 기술입니다.
로드 밸런서는 업스트림 서버 목록을 순차적으로 실행하여 각 서버에 다음 연결 요청을 차례로 할당합니다.
다음 샘플 구성의 backend 업스트림 그룹에서 로드밸런서는 처음 세 개의 연결 요청을 web1으로 보냅니다,
web2, web3, 네 번째는 web1, 다섯 번째는 web2 순으로 차례로 전송합니다.
Hash
해시 방식을 사용하면 각 요청에 대해 로드밸런서는 사용자가 지정한 텍스트와 NGINX 변수의 조합을 기반으로 해시를 계산하고
이 해시를 서버 중 하나에 연결합니다.
해당 해시를 가진 모든 요청을 해당 서버로 전송하므로 이 방법은 기본적인 종류의 세션 지속성를 설정합니다.
upstream backend { hash $scheme$request_uri; server web1; server web2; server web3; } server { server_name www.example.com; location / { proxy_pass http://backend; } }IP 해시
IP 해시(HTTP에만 사용 가능)는 해시 메서드의 사전 정의된 변형으로,
해시는 클라이언트의 IP 주소를 기반으로 합니다.
ip_hash 지시어를 사용하여 설정합니다.
upstream backend { ip_hash; server web1; server web2; server web3; } server { server_name www.example.com; location / { proxy_pass http://backend; } }클라이언트에 IPv6 주소가 있는 경우 해시는 전체 주소를 기반으로 합니다.
IPv4 주소가 있는 경우 해시는 주소의 처음 세 옥텟만 기반으로 합니다.
이는 서브네트워크(/24) 범위에서 동적으로 IP 주소를 할당받는 ISP 클라이언트에 최적화하도록 설계되었습니다.
재부팅 또는 재접속 시 클라이언트의 주소가 /24 네트워크 범위의 다른 주소로 변경되는 경우가 많지만
연결은 여전히 동일한 클라이언트를 나타내므로 서버에 대한 매핑을 변경할 이유가 없습니다.
그러나 사이트에 대한 대부분의 트래픽이 동일한 /24 네트워크에 있는 클라이언트에서 발생하는 경우
모든 클라이언트를 동일한 서버에 매핑하기 때문에 IP 해시는 의미가 없습니다.
이 경우(또는 다른 이유로 4개의 옥텟을 모두 해시하려는 경우) 대신 $remote_addr 변수와 함께 해시 방법을 사용하세요.
hash $remote_addr;최소 연결 수
최소 연결 방법을 사용하면 로드밸런서가 각 서버에 대한 현재 활성 연결 수를 비교하여 연결 수가 가장 적은 서버로 요청을 보냅니다. least_conn 지시어를 사용하여 구성할 수 있습니다.
upstream backend { least_conn; server web1; server web2; server web3; } server { server_name www.example.com; location / { proxy_pass http://backend; } }최소 시간
최단 시간 방법(NGINX 'Plus에서만 사용 가능)을 사용하면 로드 밸런서가
각 서버에 대해 현재 활성 연결 수와 과거 요청에 대한 가중 평균 응답 시간이라는
두 가지 메트릭을 수학적으로 결합하여 가장 낮은 값을 가진 서버로 요청을 보냅니다.
최소_시간 지시문에서 선택한 파라미터는 응답 헤더 수신 시간(header) 또는 전체 응답 수신 시간(last_byte
upstream backend { least_time (header | last_byte); server web1; server web2; server web3; } server { server_name www.example.com; location / { proxy_pass http://backend; } }주석:
TCP 및 UDP 부하 분산(stream 컨텍스트에서)의 경우, least_time 지시어에 이러한 파라미터를 사용하여
3가지 유형의 응답 시간 중에서 선택할 수 있습니다:
로드 밸런싱 기술 선택
그렇다면 어떤 부하 분산 기술이 웹사이트나 앱에 가장 적합한지 어떻게 알 수 있을까요?
트래픽 패턴은 사이트마다, 심지어 한 사이트 내에서도 하루 중 시간대별로 매우 다양하기 때문에 한 가지 특성(예: 트래픽 폭주 대 안정적, 단시간 연결 대 장기 연결 등)을 기준으로 부하 분산 기술을 선택하는 것은 합리적이지 않습니다. 하지만 고려해야 할 선택의 범위를 좁히는 데 도움이 되도록 각 방법의 장단점을 고려하겠습니다.
테스트 실행을 통한 방법 비교
로드 밸런싱 방법의 하위 집합을 고려할 때 어떤 방법이 트래픽에 가장 적합한지 테스트해 보는 것이 좋습니다.
"최적"이란 일반적으로 클라이언트에 응답을 전송하는 데 걸리는 시간이 가장 짧은 것을 의미하지만 다른 기준이 있을 수 있습니다.
애플리케이션 성능 관리 도구는 이러한 종류의 테스트에 매우 유용합니다.
업스트림 그룹의 각 서버에 대한 그래프가 포함된 사용자 지정 화면을 만들어 테스트 중에 값이 변경될 때 실시간으로 비교할 수 있습니다.
AppDynamics, Datadog, Dynatrace, New Relic 등 여러 APM에서 NGINX Plus 및 NGINX용 사용자 정의 플러그인을 제공합니다.
모든 서버의 용량이 동일한 경우 테스트가 가장 간단합니다.
그렇지 않은 경우 용량이 더 큰 서버가 더 많은 요청을 받도록 서버 가중치를 설정해야 합니다.
아래의 서버가 동일하지 않을 때 가중치 설정하기를 참조하세요.
테스트 중에 확인해야 할 몇 가지 메트릭은 다음과 같습니다:
CPU 및 메모리 로드 - CPU와 메모리 모두에 대해 사용된 총 용량의 비율을 확인합니다.
모든 서버가 균등하게 로드되지 않는다면 트래픽이 효율적으로 분산되지 않는 것입니다.더 많은 계산이나 데이터베이스 또는 기타 서비스 호출이 필요한
"무거운" 요청이 불균형하게 해당 서버로 전달되고 있는 것입니다.
부하 분산 기술의 문제라기보다는 잘못된 가중치로 인해 불균형이 발생할 수 있으므로 가중치를 조정해 보세요.
일부 오류의 경우 서버는 요청이 성공할 때보다 더 빨리 응답을 보낼 수 있습니다.
예를 들어 HTTP 응답 코드 404(파일 없음 찾음)의 경우
서버는 실제 파일이 존재한다면 전송할 수 있는 것보다 훨씬 빠르게 오류를 반환할 수 있을 것입니다.
최소 연결 및 최소 시간 부하 분산 알고리즘을 사용하면 로드 밸런서가 실제로는 제대로 작동하지 않는 서버를 선호하게 될 수 있습니다.
장단점 및 사용 사례
이제 각 부하 분산 기술의 장단점을 살펴보고 특히 적합한 몇 가지 사용 사례를 설명해 보겠습니다.
대부분의 사용 사례에 적합성이 높은 순서대로 설명하겠습니다.
간단히 미리 말씀드리자면, 가장 광범위한 사용 사례에 가장 적합한 옵션은 최소 연결(및 NGINX의 경우 최소 시간)이라고 생각합니다.
해시 및 IP 해시
해시 및 IP 해시 부하 분산 기술은 특정 유형의 클라이언트 요청(해시 값에 캡처됨)과 특정 서버 간에 고정 연결을 생성합니다.
이를 세션 지속성이라고 할 수 있는데, 주어진 해시 값을 가진 모든 요청은 항상 동일한 서버로 이동합니다.
이러한 방법의 가장 큰 단점은 부하를 균등하게 분산하는 것은 물론 서버 간에 요청을 동일한 수로 분배한다는 보장이 없다는 것입니다.
해싱 알고리즘은 가능한 모든 해시 값 집합을 업스트림 그룹의 각 서버에 하나씩 '버킷'으로 균등하게 나누지만
실제로 발생하는 요청에 균등하게 분산된 해시가 있는지 예측할 수 있는 방법이 없습니다.
예를 들어 10개의 클라이언트가 한 사이트에 접속하고 있는데
IP 해시 알고리즘이 그 중 7개 IP 주소의 해시를 web1에, 1개는 web2에, 2개는 web3에 연관시키는 경우가 있다고 가정해 보죠.
web1 서버는 다른 서버를 합친 것보다 두 배 이상 많은 요청을 받게 됩니다.
따라서 세션 유지의 이점이 불균형한 부하로 인한 나쁜 영향보다
클 때는 해시 또는 IP를 사용하는 것이 좋습니다.
이는 NGINX에서 사용할 수 있는 유일한 세션 지속성 형태입니다.
NGINX는 더 정교하고 실제 로드 밸런싱과 함께 작동하는
세 가지 다른 세션 지속성 메커니즘을 제공합니다(sticky 지시어로 구성하면 됩니다).
그러나 다음과 같은 경우에는 세 가지 메커니즘이 작동하지 않으므로
NGINX를 사용하더라도 해시 또는 IP를 선택할 수 있습니다:
브라우저 또는 클라이언트 앱이 쿠키를 허용하지 않고, 애플리케이션에 쿠키 없이 세션 지속성 메커니즘을 사용할 수 있는 방법이 없는 경우. 각 클라이언트(특히 IP 주소)를 특정 서버와 연결하려면 IP 해시 방법을 사용합니다.서버 자체의 캐싱을 활용하기 위해 특정 URL에 대한 요청을 매번 동일한 서버로 보내려고 합니다.
매번 같은 서버에서 파일을 가져오려면 $request_uri 변수와 함께 해시 메서드를 사용하세요.
예를 들어 특정 .php 파일을 제공하는 데 시간이 많이 걸리는 데이터베이스 호출이 여러 번 필요하지만 가져온 데이터는 자주 변경되지 않으므로 캐시가 가능하다고 가정해 보겠습니다. 파일에 대한 모든 요청을 동일한 서버로 보내면 첫 번째 클라이언트만 데이터베이스 호출로 인해 긴 지연 시간을 경험하게 됩니다. 이후의 모든 클라이언트는 캐시에서 데이터를 빠르게 검색할 수 있습니다.
또 다른 장점은 하나의 서버만 특정 데이터 집합을 캐시하면 된다는 것입니다. 모든 서버에서 동일한 데이터를 중복 캐싱하지 않으므로 더 작은 캐시를 사용할 수 있습니다.
IP 해시와 클라이언트 IP 주소가 키에 있을 때 해시가 작동하지 않는 경우가 몇 가지 있습니다:
해시는 결정론적입니다(해싱 알고리즘은 매번 동일한 결과를 산출합니다). 여기에는 몇 가지 긍정적인 측면이 있습니다.
배포의 모든 NGINX Plus 또는 NGINX 인스턴스가 정확히 동일한 방식으로 부하 분산 요청을 하고,
로드 밸런서를 다시 시작할 때에도 해시 대 서버 매핑이 지속된다는 점입니다.
(실제로는 재시작 후 다시 계산되지만 결과는 항상 동일하기 때문에 효과적으로 지속됩니다.)
반면에 업스트림 서버 집합을 변경하면 일반적으로 적어도 일부 매핑이 강제로 다시 계산되어 세션 지속성이 깨집니다.
다시 계산되는 매핑의 수를 다소 줄일 수 있습니다:
IP 해시 방식의 경우, 업스트림 그룹에서 서버를 일시적으로 제거하기 전에
다음 예의 web2처럼 down 파라미터를 server 지시어에 추가합니다. 서버가 곧 서비스를 재개할 것이라는 가정 하에 매핑은 다시 계산되지 않습니다.업스트림 백엔드 { ip_hash; 서버 웹1; 서버 웹2 다운; 서버 웹3; }
라운드 로빈
앞서 언급했듯이 라운드 로빈은 NGINX 및 NGINX의 기본 로드 밸런싱 방법입니다.
따라서 선택하기 가장 쉬운 방법이며 업스트림 그룹 자체 외에는 아무것도 구성할 필요가 없습니다.
일반적으로 라운드 로빈은 서버 및 요청의 특성으로 인해 일부 서버가 다른 서버에 비해 과부하가 걸릴 가능성이 낮을 때
가장 잘 작동한다는 것이 일반적인 의견입니다.
몇 가지 조건은 다음과 같습니다:
라운드 로빈은 요청이 모든 서버에 동일한 수(또는 적절한 가중치 비율)로 분산되도록 보장하기 때문에
테스트 시나리오에 특히 적합합니다.
일부 다른 방법은 트래픽이 적을 때 항상 트래픽을 균등하게 분배하지 않아 테스트 결과가 왜곡될 수 있습니다.
라운드 로빈에서는 특정 파일에 대한 요청을 동일한 서버에 전송할 방법이 없기 때문에
모든 서버가 광범위한 파일(일반적으로 동료 서버와 동일한 파일 다수를 포함)을 서비스하고
캐싱하게 되어 캐시가 가득 찰 가능성이 높습니다.
마지막으로, 초기 배포를 균일하게 하면 NGINX;Plus에서 세션 지속성 문제를 발견하는 데 도움이 됩니다(sticky 지시어로 구성한 대로).
최소 연결 및 최소 시간
위에서 언급했듯이 최소 연결은 가장 광범위한 사용 사례, 특히 프로덕션 트래픽에 가장 적합한 로드 밸런싱 기술입니다.
이는 고객들의 일화를 통해 뒷받침됩니다. 성능은 안정적이고 예측 가능합니다.
또한 최소 연결은 서버의 용량에 따라 워크로드를 효과적으로 분산합니다.
더 강력한 서버는 요청을 더 빨리 처리하므로 특정 순간에는 용량이 적은 서버보다
처리 중인 연결 수가 더 적을 수 있습니다(또는 처리가 시작되기를 기다리는 중일 수도 있음).
최소 연결은 현재 연결 수가 가장 적은 서버로 각 요청을 보내므로 강력한 서버로 요청을 보낼 가능성이 높습니다.
(그러나 아래의 서버가 동일하지 않을 때 가중치 설정에 설명된 대로 가중치를 설정하면 요청을 훨씬 더 효율적으로 분산할 수 있습니다.)
최소 연결 시간(NGINX와 플러스만 해당)은 최소 연결 시간보다 더 민감한 버전이라고 생각할 수 있습니다.
평균 응답 시간을 포함함으로써 서버의 최근 성능 기록을 고려합니다(실제로는 지수 가중 이동 평균이므로 오래된 응답 시간이 최근 응답 시간보다 평균에 덜 영향을 미칩니다).
최소 시간은 업스트림 서버의 평균 응답 시간이 매우 다른 경우에 특히 적합합니다.
예를 들어 재해 복구를 위해 서로 다른 데이터 센터에 서버를 두고 있는 경우,
응답 속도가 빠른 로컬 서버에 더 많은 요청을 보내는 경향이 있습니다.
또 다른 사용 사례는 서버 성능을 예측할 수 없는 클라우드 환경입니다.
서버가 동일하지 않은 경우 가중치 설정하기
업스트림 그룹의 서버 용량이 서로 다른 경우 서버 가중치 설정의 중요성에 대해 여러 번 언급했습니다.
특히 각 서버에 동일한 수의 요청을 전송하는 라운드 로빈 부하 분산 장치에 특히 중요합니다.
이렇게 하면 성능이 낮은 서버는 과부하가 걸리고 성능이 높은 서버는 부분적으로 유휴 상태가 될 수 있습니다.
가중치를 설정하려면 weight 파라미터를 하나 이상의 서버 블록에 업스트림 지시어를 포함시키면 됩니다.
기본값은 1입니다.
다음과 같은 방식으로 다양한 부하 분산 기술에 대한 가중치 설정의 효과를 생각해 볼 수 있습니다.
설명은 개념적으로 정확하지만 NGINX Plus 코드의 구현이 반드시 표시된 수학 연산을 사용하는 것은 아니라는 점에 유의하세요.
다음은 예제의 업스트림 그룹입니다:
로빈 - 각 서버는 들어오는 요청의 백분율을 가중치의 합으로 나눈 값과 동일한 가중치를 가져옵니다.
이 예에서는 10개의 요청 중 web1이 6개(60%), web2가 3개(30%), web3이 1개(10%)를 가져옵니다.
해시 및 IP 해시 - 가중치가 없으면 해시 알고리즘은 가능한 모든 해시 값 집합을 업스트림 그룹의 각 서버에 하나씩 "버킷"으로 균등하게 나눕니다. 가중치를 사용하면 대신 가중치를 합산하여 가능한 해시 집합을 해당 수의 버킷으로 나누고 각 서버를 가중치에 해당하는 버킷 수와 연결합니다. 이 예제에서는 가능한 해시의 10%가 각각 들어 있는 10개의 버킷이 있습니다.
6개 버킷 (사용 가능한 해시의 60%)/ web1에, 3개 버킷(30%) /web2에, 1개 버킷(10%)
최소 연결 수 및 최소 시간 - 앞서 이러한 알고리즘은 가중치가 없어도 서버 용량에 따라 워크로드를 분산하는데는 매우 효과적이라고 언급했습니다. 가중치를 설정하면 이와 관련하여 성능이 훨씬 더 향상됩니다.
최소 연결 및 최소 시간은 각 요청을 가장 낮은 "점수"(각각 연결 수 또는 연결 수와 시간의 수학적 조합)를 가진 서버로 전송한다는 점을 기억하세요. 가중치를 할당하면 부하 분산 장치는 각 서버의 점수를 가중치로 나눈 후 다시 가장 낮은 값을 가진 서버로 요청을 보냅니다.
다음은 샘플 가중치와 표시된 활성 연결 수를 사용한 최소 연결의 예시입니다: web1의 점수가 100으로 가장 낮고 연결 수가 600으로 web2의 1.5배, web3의 4배 이상임에도 요청을 받습니다.
요약
NGINX와 NGINX 플러스에서 사용할 수 있는 로드 밸런싱 기술의 장단점을 검토한 결과,
가장 광범위한 사용 사례에 가장 적합한 방법은 최소 연결(그리고 NGINX 플러스의 경우 최소 시간)이라고 생각됩니다.
그러나 트래픽 및 서버 특성의 고유한 조합에 따라 다른 방법이 더 적합할 수 있으므로
배포 시 여러 가지 방법을 테스트하는 것이 중요합니다.
NGINX;Plus 부하 분산 기능을 직접 사용해 보려면
지금 바로 30일 무료 체험판을 시작하거나 문의하여 사용 사례에 대해 문의하세요.
위 내용과 같이 NGINX Plus를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요
'