NGINX Plus Key-Value Store를 사용하여 동적으로 대역폭 제한하기

Key-Value Store 기능은 HTTP용 NGINX Plus Release 13에 도입되었으며 Release 14에서 TCP 및 UDP로 확장되었습니다. Key-Value Store를 사용하면 구성을 다시 로드하거나 NGINX Plus를 다시 시작할 필요 없이 NGINX Plus가 모든 종류의 기준에 따라 트래픽을 처리하는 방법을 사용자 지정할 수 있습니다.

NGINX Plus R16 이상에서 Key-Value Store는 클러스터의 모든 NGINX Plus 인스턴스에서 동기화될 수 있습니다. (클러스터의 상태 공유는 다른 NGINX Plus 기능에서도 사용할 수 있습니다.)

이 포스트에서는 애플리케이션 성능 목표를 지원하기 위해 Key-Value Store를 사용하여 다양한 사용자 범주에 대해 서로 다른 대역폭 제한을 적용하는 방법을 설명합니다. 이 방법은 흔히 class of service 라는 것을 구현하는 한 가지 방법입니다.

목차

1. 대역폭 조절(Bandwidth Limit)
2. Dynamic Bandwidth Limiter 구성
3. NGINX Plus API를 사용하여 Key-Value Store 업데이트
4. Key-Value Store 관련 사용 사례
5. 전체적인 NGINX 구성 샘플

1. 대역폭 조절(Bandwidth Limit)

웹 애플리케이션에서 대역폭(Bandwidth)을 조절하는 데에는 여러 가지 이유가 있습니다. 예를 들어 전자상거래 사이트에서 더 많은 일반 사용자를 위해 대역폭(Bandwidth)을 조절하여 구매를 앞두고 있는 사용자 경험(UX)을 향상시킬 수 있습니다. 이는 또한 사이트 성능을 저하 시키려는 악의적인 사용자로부터 합법적인 모든 사용자를 보호합니다.

이 예에서는 로그인하지 않은 사용자에 대해 대역폭(Bandwidth) 제한을 최소로 설정하고 로그인한 사용자에 대해서는 제한을 더 높게 설정했으며, 로그인하여 장바구니 항목에 있는 사용자에 대한 제한은 그보다 더 높게 설정했습니다.

The NGINX Plus API and key-value store can be used to set dynamic bandwidth limits on website visitors based on their class of service

사용자 범주별로 대역폭(Bandwidth)을 조정하기 위해 만드는 도구를 Dynamic Bandwidth Limiter라고 합니다. NGINX Plus의 두 가지 주요 기능을 사용하여 작동합니다.

  • 첫 번째는 NGINX 및 NGINX Plus의 핵심 기능인 응답 속도를 제한하는 기능입니다. limit_rate 지시어 또는 $limit_rate 변수를 사용하여 최대 처리량을 지정합니다. 이 변수의 장점은 예제와 같이 조건에 따라 다른 비율을 설정할 수 있다는 것입니다.
  • 두 번째 기능은 NGINX Plus의 Key-Value Store입니다. NGINX Plus Key-Value Store 에는 임의의 JSON 형식의 키(Key)와 값(Value)이 포함될 수 있으며 빠른 액세스를 위해 메모리에 저장됩니다.

2. Dynamic Bandwidth Limiter 구성

Dynamic Bandwidth Limiter를 생성하기 위해 NGINX Plus 구성에서 가장 일반적인 사용자(로그인하지 않은 사용자)에 적합한 값으로 기본 제한을 설정했습니다. 대역폭 제한은 Key-Value Store 의 class of service에 고객을 할당하므로 점차적으로 더 중요한 사용자에게 대역폭 제한이 더 관대합니다.

다음 예제에서 keyval_zone 지시문은 ratezone이라는 Key-Value Store에 대해 1MB의 공유 메모리를 할당합니다. keyval 지시문에서 첫 번째 매개변수는 쿠키에 기록된 고객 ID를 Key-Value Store의 조회를 위한 키(Key)로 정의하고 두 번째 매개변수는 $bwlimit 변수가 키(Key)와 연결된 값(해당 고객을 위한 class of service)으로 설정되도록 지정합니다.

$cookie_CUSTERID 변수는 CUSTERID라는 이름의 쿠키를 나타냅니다. 이는 일반적으로 사용자가 로그인할 때 애플리케이션에서 설정하는 사용자를 고유하게 식별하는 간단한 메커니즘입니다. 사용자가 사이트를 탐색할 때 추적하여 세션 지속성(Session persistence)을 제공하는 데 가장 많이 사용됩니다.

Key-Value Store는 NGINX Plus API에 따라 달라지며, 읽기-쓰기 액세스를 위한 write=on 매개변수와 함께 /api location에 api 지시문을 포함하여 활성화됩니다. (다른 location 지시문를 사용하면 내장 NGINX Plus 실시간 활동 모니터링 대시보드를 사용할 수 있으며, NGINX Plus API도 사용됩니다.)

Note: 이 snippet은 API에 대한 액세스를 제한하지 않지만 특히 프로덕션 환경에서 그렇게 하는 것이 좋습니다. 자세한 내용은 NGINX Plus 관리자 가이드를 참조하세요.

keyval_zone zone=ratezone:1M;
keyval $cookie_CUSTOMERID $bwlimit zone=ratezone;

server {
    listen 8080;

    location = /dashboard.html {
        root /usr/share/nginx/html;
    }

    location /api {
        api write=on;
    }
#...
}

그런 다음 map 블록을 사용하여 각 class of service에 대한 대역폭 제한을 정의합니다. keyval 지시문에 의해 설정된 대로 $bwlimit 변수는 외부 애플리케이션에 의해 Key-Value Store에 설정된 고객의 class of service(로그인 사용자를 위한 Bronze, 선호 사용자를 위한 Silver, 쇼핑 카트에 항목이 있는 사용자를 위한 Gold)를 캡처합니다.

map 블록은 로그인하지 않았거나 Key-Value Store 에 항목이 없는 사용자에게 기본 대역폭 제한인 256Kbps를 할당합니다. class of service에 대한 제한은 bronze의 경우 512Kbps, silver의 경우 1Mbps, gold의 경우 무제한 대역폭(0으로 표시)입니다. (애플리케이션 성능에 따라 장바구니 사용자도 제한을 설정할 수 있습니다.) $ratelimit 변수는 대역폭 제한을 캡처합니다.

server 블록의 set 지시문은 기본 내장 $limit_rate 변수를 map 블록에 설정된 $ratelimit 값으로 설정하여 대역폭 제한을 구현합니다.

map $bwlimit $ratelimit {
    bronze 512k;
    silver 1m;
    gold 0;
    default 256k;
}

server {
    #...
    set $limit_rate $ratelimit;
    #... 
}

3. NGINX Plus API를 사용하여 Key-Value Store 업데이트

NGINX Plus API의 HTTP GET, POST 및 PATCH 메서드는 Key-Value Store에 액세스하고 관리하는 데 사용됩니다. 앞서 언급한 바와 같이 이 예에서 외부 애플리케이션은 Key-Value Store를 관리합니다. 예시를 위해 여기서는 curl 명령을 사용하여 가능한 작업을 보여 줍니다.

먼저 GET 메서드를 사용하여 ratezone Key-Value Store가 비어 있는지 확인합니다. 두 번째 curl 명령은 -b 옵션을 사용하여 HTTP Cookie 헤더 값으로 고객 ID를 전달하여 brownie.jpg 파일을 요청합니다. -o 옵션은 /dev/null(실제로 폐기)에 씁니다. 왜냐하면 여기서 포인트는 다운로드 속도를 보는 것이지 실제로 brownie.jpg를 보는 것이 아니기 때문입니다.

Key-Value Store가 비어 있기 때문에 고객에 대한 키가 없으므로 기본 속도 제한인 256Kbps를 받을 것으로 예상합니다. 이는 Current Speed ​​​​열에 보고된 276Kbps 속도로 확인됩니다.

root# curl -X GET localhost:8080/api/1/http/keyvals/ratezone
{}

root# curl -b "CUSTOMERID=CPE1704TKS" -o /dev/null localhost/brownie.jpg
  % Total    % Received % Xferd  Average Speed   Time    Time     Time     Current
                                 Dload  Upload   Total   Spent    Left     Speed
100 1893k  100    1893k 0     0   269k       0  0:00:07 0:00:07 --:--:--     
276k

그런 다음 PATCH 메서드(Method)을 사용하여 고객을 silver class of service 등급으로 승격(promote)하고 다운로드 속도가 다시 증가했는지 확인합니다.

root# curl -X PATCH -d '{"CPE1704TKS":"silver"}' localhost:8080/api/1/http/keyvals/ratezone

root# curl -X GET localhost:8080/api/1/http/keyvals/ratezone
{"CPE1704TKS":"silver"}

root# curl -b "CUSTOMERID=CPE1704TKS" -o /dev/null localhost/brownie.jpg
  % Total    % Received % Xferd  Average Speed   Time    Time     Time     Current
                                 Dload  Upload   Total   Spent    Left     Speed
100 1893k  100    1893k 0     0   1876k      0  0:00:01 0:00:01  --:--:--    
1877k

마지막으로 PATCH 메서드(Method)을 다시 사용하여 고객을 Gold class of service 등급으로 승격(promote)시키고 대역폭(Bandwidth) 제한이 없을 때 다운로드 속도가 급격히 증가하는 것을 확인합니다.

root# curl -X PATCH -d '{"CPE1704TKS":"gold"}' localhost:8080/api/1/http/keyvals/ratezone

root# curl -X GET localhost:8080/api/1/http/keyvals/ratezone
{"CPE1704TKS":"gold"}

root# curl -b "CUSTOMERID=CPE1704TKS" -o /dev/null localhost/brownie.jpg
  % Total    % Received % Xferd  Average Speed   Time    Time     Time     Current
                                 Dload  Upload   Total   Spent    Left     Speed
100 1893k  100    1893k 0     0    192M      0 --:--:-- --:--:-- --:--:--     
205M

4. Key-Value Store 관련 사용 사례

이 예는 고객 ID cookie($cookie_CUSTOMERID)를 사용하여 각 사용자를 식별하고 class-of-service 등급 범주를 할당하는 방법을 보여줍니다. 그러나 이 로직(Logic)는 NGINX 변수($remote_ip, $jwt_claim_sub 등)에 캡처된 거의 모든 값에 적용될 수 있습니다. 일부 변수는 애플리케이션 또는 사용 사례에 따라 다른 변수보다 더 의미가 있습니다. 또한 Key-Value Store를 사용하여 연결 속도를 제한할 수 있습니다. 이는 일반 사용자 또는 악의적인 사용자가 다른 사용자, 특히 구매자에게 부정적인 영향을 미치지 않도록 하는 데 매우 유용합니다.

5. 전체적인 NGINX 구성 샘플

keyval_zone zone=ratezone:1M;
keyval $cookie_CUSTOMERID $bwlimit zone=ratezone;

map $bwlimit $ratelimit {
    bronze 512k;
    silver 1m;
    gold 0;
    default 256k;
}

upstream backend1 {
    zone backend1 64k;
    server 192.168.1.100:443;
}

server {
    listen 8080;

    location = /dashboard.html {
        root /usr/share/nginx/html;
    }

    location /api {
        api write=on;
    }

    location / {
        return 301 /dashboard.html;
    }
}

server {
    listen 80;
    set $limit_rate $ratelimit;

    location /favicon.ico {
        alias /usr/share/nginx/html/nginx-favicon.png;
    }
	
    location = /brownie.jpg {
        root /usr/share/nginx/html;
    }

    location / {
        proxy_set_header Host $host;
        proxy_pass https://backend1;
    }	
}

NGINX Plus Key-Value Store를 직접 사용해 보려면 지금 30일 무료 평가판을 신청하거나 사용 사례에 대해 최신 소식을 빠르게 전달받고 싶으시면 아래 뉴스레터를 구독하세요.