HAProxy 와 Nginx 의 로드밸런싱
NGINX
Nginx 는 대표적인 웹서버인 Apache 의 문제점을 해결하면서 만들어진 웹서버로 비동기 방식으로 개발되어 가볍고 빠른 것으로 유명한 오픈소스 어플리케이션이다. Nginx 는 http 나 reverse proxy 같은 기능 외에도 load balancer 기능 또한 강력하다.
# Load Balancing
upstream target-server {
least_conn;
server [서버주소1] weight=5 max_fails=3 fail_timeout=10s;
server [서버주소2] weight=10 max_fails=3 fail_timeout=10s;
}
server {
listen 80;
listen [::]:80;
server_name front.local;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location / {
proxy_next_upstream error http_503;
proxy_pass http://target-server;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Host $host;
proxy_redirect off;
}
}
Nginx 로드 밸런싱은 upstream 이라는 옵션으로 설정할 수 있는데, least_conn
은 연결이 가장 적은 서버로 트래픽을 전달하는 역할을 한다. 설정할 수 있는 옵션은 다음과 같다.
옵션 | 설명 |
---|---|
p_hash | 같은 방문자로부터 도착한 요청은 항상 같은 업스트림 서버가 처리 할 수 있게 한다. |
weight=n | 업스트림 서버의 비중을 나타낸다. 이 값을 2로 설정하면 그렇지 않은 서버에 비해 두배 더 자주 선택된다. |
max_fails=n | n으로 지정한 횟수만큼 실패가 일어나면 서버가 죽은 것으로 간주한다. |
fail_timeout=n | max_fails가 지정된 상태에서 이 값이 설정만큼 서버가 응답하지 않으면 죽은 것으로 간주한다. |
down | 해당 서버를 사용하지 않게 지정한다. `ip_hash;` 지시어가 설정된 상태에서만 유효하다. |
backup | 모든 서버가 동작하지 않을 때 backup으로 표시된 서버가 사용되고 그 전까지는 사용되지 않는다. |
출처: 생활코딩
다만, Nginx 의 유료 버젼인 Nginx Plus 를 사용하지 않는 이상 헬스체크가 불가능하기 때문에 실제 서버의 상태를 체크하는 API 를 만들어서 상황에 따라 스위칭하는 고가용성을 위한 동작에는 용이하지 않다.
HAProxy
Haproxy 는 L4, L7 과 같은 하드웨어 로드밸런서를 대체하기 위한 오픈소스 소프트에어로 이름처럼 Reverse Proxy 를 기반으로 로드밸런싱을 하기에 매우 강력하고 또 가벼운 어플리케이션이다. HA (High Availability) 라는 이름처럼 고가용성을 위하여 설계되었다. Nginx 로드밸런싱과 다른 점은 헬스체크라고 볼 수 있는데, 특정 API 에 접근하여 서버 상태를 점검하고, 문제가 있으면 다른 node 로 트래픽을 넘겨줄 수 있는 기능을 한다.
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
user haproxy
group haproxy
daemon
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 5000
timeout server 5000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
listen stats
bind *:70
stats enable
stats uri /?stats=this-is-stats
frontend load-balancer
bind *:80
mode http
acl my-url hdr(host) -i front.local
http-request deny if !my-url
default_backend server
backend server
mode http
option forwardfor
# 헬스체크
option httpchk GET /
http-check expect status 200
default-server inter 1s fall 3 rise 2
# 로드 밸런싱
balance roundrobin
server server-blue [서버주소1] check
server server-green [서버주소2] check
로드밸런싱은 Nginx 와 동일하게 round-robin 으로 설정했고, health check 는 특정 url 에 http status 코드를 설정하여 간단하게 적용할 수 있다. acl
옵션을 통해 access control 도 간단하게 처리할 수 있고, nginx 의 deny 기능 또한 유사한 형태로 간단하게 처리할 수 있다. 또한 haproxy 는 stats 이라고 하는 페이지를 기본적으로 제공하는데, 어떤 서버에 접속되고 작동하고 있는지 확인하기 편리하다. 단, uri 가 공개되면 곤란하니 방화벽으로 제한하거나, .htpasswd
같은 방식을 사용할 것.
마지막으로 헬스체크에 대해 조금 더 자세하게 설명하면, default-server inter 1s fall 3 rise 2
라고 하는 것은 다음과 같이 해석할 수 있다. 1초 마다 서버에 접속하여 헬스체크를 행하되 3번 실패하면 접속 불가로 판단하고 2번 성공하면 정상 상태로 간주하여 트래픽을 연결해준다. option httpchk GET /
은 http GET
으로 [서버주소]/
요청을 날려서 http-check expect status 200
에 따라 200 OK
에 해당하는 응답이 나올시 정상 상태라고 판단하게 된다.
결론
간단하게 Nginx 와 HAProxy 의 로드밸런싱에 대해서 알아보았다. Nginx 자체의 로드밸런싱도 훌륭하지만, 굳이 웹 서버로서의 역할이 필요가 없다면 (캐싱이라거나 캐싱, 혹은 캐싱이라거나...) HAProxy 로드 밸런싱이 헬스체크가 가능하기도 하고 좀 더 가벼우니 필요에 따라 선택하면 좋을 것이다. 단, SSL 을 사용해야 하는 경우 HAProxy 는 1.5 버젼 부터 지원하니 꼭 잊지 말자. 삽질 엄청 함