Network

[NGINX 쿡북] 3. 트래픽 관리

noahkim_ 2025. 4. 1. 16:26

데릭 디용기 님의 "NGINX 쿡북" 책을 정리한 글입니다.


0. 소개

  • 웹 트래픽 컨트롤러: 트래픽 경로를 결정하고 여러 속성값을 이용해 흐름을 제어할 수 있음

 

기능
  • 특정 비율로 분기
  • 요청 빈도, 연결 수, 대역폭 등을 제한

 

1. A/B 테스트

split_client 모듈

  • 트래픽을 특정 비율로 나누는 모듈

 

split_clients "${remote_addr}AAA" $variant {
    20.0% "backendv2";
    * 	  "backendv1";
}

location / {
    proxy_pass http://$variant
}
구성 요소 설명
"${remote_addr}AAA"
사용자 IP 주소 ($remote_addr)와 문자열 "AAA"를 결합하여 해시 생성
$variant 요청을 분배할 변수
20.0% "backendv2"; 전체 요청 중 20%를 "backendv2"로 보냄
* "backendv1"; 나머지 80%를 "backendv1"로 보냄

 

2. GeoIP 모듈과 데이터베이스 활용하기

설치

1. GeoIP2 모듈 설치

git clone https://github.com/leev/ngx_http_geoip2_module.git

brew install geoip2
brew install libmaxminddb

 

 

2. GeoIP2 모듈 빌드하기

nginx -V 2>&1 | egrep  "^configure" | cut -d: -f2 > /tmp/nginx_build_options.txt
echo " --with-http_geoip_module" >> /tmp/nginx_build_options.txt

# ngx_http_geoip2_module 빌드하기
sh -c "./configure $(cat /tmp/nginx_build_options.txt) --add-dynamic-module=/path/to/ngx_http_geoip2_module"
make modules
  • 빌드 플래그를 기존의 nginx와 일치시켜줘야 함
  • geoip를 동적 모듈로 추가해주기

 

2. GeoIP2 사이트에서 country & city 정보 다운로드 (csv format)

3. 동적 모듈 적용하기 (설정 파일)

load_module modules/ngx_http_geoip_module.so

http {
    geoip2 /usr/local/etc/nginx/geoip/GeoLite2-Country.mmdb { # 국가 데이터베이스를 불러옴
    	auto_reload 5m; # 5분마다 새로 로드
        
        $geoip2_metadata_country_build metadata build_epoch; # 빌드 날짜를 저장하는 변수
        
        $geoip2_data_country_code default=KR         # 변수에 IP 주소 기반 국가 코드를 저장함
          source=$variable_with_ip country iso_code; 
        $geoip2_data_country_name country name en;   # 변수에 IP 주소 기반 국가 이름을 저장함
    }
    
    geoip2 /usr/local/etc/nginx/geoip/GeoLite2-City.mmdb {   # 도시 데이터베이스를 불러옴
    	$geoip2_data_city_name default=Seoul city names en;  # 변수에 IP 주소 기반 도시 이름을 저장함
    }
    
    # GeoIP2에서 가져온 정보를 FastCGI 서버에 전달
    fastcgi_param COUNTRY_CODE $geoip2_data_country_code; 
    fastcgi_param COUNTRY_NAME $geoip2_data_country_name;
    fastcgi_param CITY_NAME $geoip2_data_city_name;
}
  • 다운로드받은 데이터베이스를 직접 이용할 수 있음

 

내장 변수

GeoIP2 모듈에서 사용 가능한 내장 변수를 쓸 수 있게 해줌

변수 설명 예제 값
$geoip2_metadata_country_build GeoIP2 데이터베이스의 빌드 날짜 (epoch) 1696891200
$geoip2_data_country_code 방문자의 국가 코드 (ISO 3166-1 alpha-2) DE, CN, BR
$geoip2_data_country_name 방문자의 국가 이름 Germany, China, Brazil
$geoip2_data_city_name 방문자의 도시 이름 Berlin, Tokyo
$geoip2_data_region_name 방문자의 지역/주 이름 California, Seoul
$geoip2_data_region_code 방문자의 지역 코드 (ISO 3166-2) CA, 11
$geoip2_data_latitude 방문자의 위도 (도시 기반) 48.8566
$geoip2_data_longitude 방문자의 경도 (도시 기반) 2.3522
$geoip2_data_timezone 방문자의 타임존 America/New_York
$geoip2_data_asn 방문자의 ASN (Autonomous System Number) AS15169
$geoip2_data_isp 방문자의 ISP (Internet Service Provider) Google LLC
$geoip2_data_organization 방문자의 소속 조직 Google Cloud
$geoip2_data_connection_type 방문자의 네트워크 유형 Cable/DSL
$geoip2_data_is_proxy 방문자가 프록시를 사용하는지 여부 yes / no

 

 

3. 국가 단위 접근 차단하기

http {
    map $geoip_country_code $country_access {
        "US"  	 0;
        default  1;        
    }
    
    server {
        if ($country_access = '1') { return 403; }
    }
}

 

 

4. 프록시 서버로부터 온 트래픽의 사용자 IP 찾기

http {
    # ============ 설정 =============
    
    geoip2_proxy 10.0.16.0/26; # 프록시 서버의 IP 대역 지정 (CIDR 표기법)
    geoip2_proxy_recursive on; # 최종 사용자의 IP 확인 (X-Forwarded-For 헤더값을 순차적으로 탐색)
}

geoip2_proxy

  • 프록시 서버를 통해 요청이 전달되면 nginx가 직접 클라이언트 IP를 확인할 수 없음
  • 프록시 서버는 대신 X-Forwarded-For 헤더에 클라이언트 IP를 담아서 전달함
  • X-Forwarded-For 헤더값을 추출하기 위해 사용

 

5. 연결 제한하기

http {
    # ============ 설정 =============
    
    limit_conn_zone $binary_remote_addr zone=limitbyaddr:10m;
    limit_conn_status 429;
    
    server {
        # ...
        limit_conn limitbyaddr 40;
    }
}

 

지시어 설명
limit_conn_zone 공유 메모리 영역을 생성
키(사용자 IP 등)를 바이너리 형태로 변환하여 저장
$binary_remote_addr 사용자 IP를 바이너리 형태로 변환한 값 (키 역할)
limit_conn_status 제한 초과 시 응답할 HTTP 상태 코드 지정
limit_conn
특정 공유 메모리 영역에 대해 최대 동시 연결 수 제한

 

6. 요청 빈도 제한하기

http {
    # ============ 설정 =============
    
    limit_req_zone $binary_remote_addr zone=limitbyaddr:10m rate=3r/s;
    limit_conn_status 429;
    
    server {
        # ...
        limit_req limitbyaddr 40;
    }
}

 

지시어 설명
limit_req_zone 요청 속도 제한을 위한 공유 메모리 영역을 생성
$binary_remote_addr 사용자 IP를 바이너리 형태로 변환 (키 역할)
zone=limitbyaddr:10m 공유 메모리 이름(limitbyaddr)과 크기(10MB, 약 160,000개 IP 저장 가능) 지정
rate=3r/s 1초당 3개의 요청만 허용 (r/s: requests per second)
limit_conn_status 제한 초과 시 반환할 HTTP 상태 코드
limit_req 특정 공유 메모리(limitbyaddr)에서 허용할 최대 요청 대기열 크기 지정

 

7. 전송 대역폭 제한하기

server {
    location /download/ {
    	limit_rate_after 10m;
        limit_rate 1m;
    }
}

 

지시어 설명
limit_rate_after 지정된 크기(바이트 단위) 이후부터 대역폭 제한 적용
limit_rate 클라이언트당 초당 다운로드 속도를 제한 (바이트 단위)

 

 

 

 

출처