nginx 로 cluster 를 구성 및 load balancer 설정하는 방법 정리


upstream 설정

cluster 에 참여하는 서버 정보와 포트를 upstream 지시자로 설정하며 첫 번째 설정한 서버가 우선적으로 응답을 처리함.

http {
    server_names_hash_bucket_size 64;
    # server_name_in_redirect off;

    include /etc/nginx/mime.types;
 
	## 
	upstream phpserver {
		## LB method
		# least_conn, ip_hash;
    
		## fastcgi 를 사용하는 경우
	    #server unix:/var/run/php/php7.0-fpm.sock;
	    #server fpm-server-ip:9000;
        
		## proxy 를 사용하는 경우
    	server was1-ip:1234;
	    server was2-ip:1234;
	}       
CODE

nginx 를 여러 개 사용하여 클러스터를 구성할 경우 upstream 에 was 의 ip 를 기술하지 말고 /etc/hosts 에 alias 를 주고 사용하는 것이 아래 예제처럼 nginx.conf 를 동일하게 사용할 수 있으므로 권장. 

nginx1

nginx2는 100 이 main was 이며 100 이 장애일 경우 101 로 전환

/etc/hosts

192.168.10.100 was1
192.168.10.101 was2
BASH


nginx2

nginx2는 101 이 main was

/etc/hosts

192.168.10.101 was1
192.168.10.100 was2
BASH


공통 nginx.conf

http {
	upstream app1-was {
    	server was1:9000;
	    server was2:9000 backup;
	}


    upstream app2-was {
    	server was1:8080;
	    server was2:8080 backup;

	}
}
CODE

이제 위 nginx.conf 를 git 에 넣어서 배포하면 동일한 설정으로 각각 was 를 배분해서 사용할 수 있음


Load Balancing method

Round robin(RR)

기본 설정이며 upstream 서버를 RR 방식으로 순회하며 서비스.


RR + Server Weights

클러스터내에 특정 서버가 최근에 도입해서 장비 사양이 좋은 경우 이 서버에서 처리량을 늘릴 필요가 있음.

이렇게 일부에 가중치를 줄 경우 다음과 같이 weight 항목에 가중치를 설정하며 설정하지 않을 경우 기본 값은 1임.

upstream phpserver {		
    	server was1-ip:1234 weight=5;
	    server was2-ip:1234 ;
		server 192.0.0.1 backup;
}       
CODE

was1 서버에 5번 요청한 후에 was2 서버에 요청.

backup 으로 지정된 서버는 메인 서버가 다 fault 일 경우에만 서비스.

Server Slow Start

최근에 장애로부터 복구한 서버에 요청이 폭주하지 않도록 slow_start 에 주어진 시간만큼 기다려 줌.

upstream backend {
	server was1-ip:8080 slow_start=30s;
	server was2-ip:1234;
    server 192.0.0.1 backup;
}
CODE

slow_start 기능은 nginx Plus 를 구매해야 사용할 수 있음


least connection

가장 클라이언트 연결 갯수가 적은 서버로 전달하는 설정.

upstream backend {
	least_conn ;
	server was1-ip:8080 slow_start=30s;
	server was2-ip:1234;
    server 192.0.0.1 backup;
}
CODE

ip hash

클라이언트 IP 를 hash 해서 특정 클라이언트는 특정 서버로 연결하는 설정. session clustering 이 구성되지 않은 경우 유용하나 부하가 골고루 분산되지 않고 특정 서버에 몰릴 수 있는 위험이 있습니다.

upstream backend {
	ip_hash;

	server was1-ip:8080 slow_start=30s;
	server was2-ip:1234;
    server 192.0.0.1 backup;
}
CODE


server block 설정

proxy_pass 사용시

  • proxy 를 사용할 경우 다음과 같이 proxy_pass 에 설정한 upstream 을 http:// 로 설정
  • proxy_next_upstream 에 에러 처리할 항목과 http 코드를 지정하며 gateway 에러 코드인 502, 503, 504 추가

  • 500 에러는 운영자 판단에 의해 추가

server {
    listen 80;
    server_name laravel53.app;

    index index.html index.htm index.php;

    charset utf-8;

    location ~ \.php$ {
        proxy_pass http://phpserver;
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
   }

CODE

fastcgi_pass 사용시

  • fastcgi_pass 에 upstream 이름 설정(http:// 제외)
  • fastcgi_next_upstream 을 사용하고 fastcgi 는 502, 504 를 지원하지 않으므로 http_502, http_504 키워드를 제외.
upstream backend {
    server unix:/var/run/php/php7.0-fpm.sock;
    server localhost:9001;
}
 
server {
    listen 80;
    server_name laravel53.app;

    index index.html index.htm index.php;

    charset utf-8;

    location ~ \.php$ {
        fastcgi_pass phpserver;
        fastcgi_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
   }

CODE

테스트

  1. proxy_pass 방식과 Round Robin 으로 설정했을때 테스트가 편리하며 두 개의 web app 를 준비

    composer create-project --prefer-dist laravel/laravel cluster1
    composer create-project --prefer-dist laravel/laravel cluster2
    CODE
  2. 각각 두개의 라라벨 standalone 서버를 구동

    cluster1 $ php artisan server --port 1234
    cluster2 $ php artisan server --port 1235
    CODE
  3. 브라우저로 연결하여 정상 동작 확인
  4. cluster1 웹 app 에 연결하여 다음 명령어 수행하여 503 응답 발생

    $ php artisan down
    CODE
  5. 브라우저로 연결하여 정상 동작 확인
  6. nginx log 를 확인하여 다음과 같이 upstream 에 연결 못한 로그가 남았는지 확인

    2016/10/12 07:39:32 [error] 2112#2112: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 192.168.10.1, server: laravel53.app, request:
    "GET /hello HTTP/1.1", upstream: "http://127.0.0.1:1234", host: "laravel53.app"

같이 보기

Ref