NGINX Controller API Management Module과 Kong: 성능 비교

NGINX | 2019년 5월 06일

API 관리(APIM) 시장은 경쟁이 치열합니다. 최신 전체 수명 주기 API 관리 부문 Gartner 매직 쿼드런트에서는 22개 공급업체를 평가했으며, 이 중 7개 업체가 리더 쿼드런트에 포함되었습니다. 기존 시장에서 경쟁하려면 경쟁사와 차별화하고 두각을 나타낼 수 있는 확고한 입지를 구축해야 합니다. 그렇다면 NGINX의 API 관리 솔루션은 무엇이 다를까요?

NGINX의 목표는 가볍고 성능이 뛰어난 소프트웨어를 만드는 것입니다. NGINX Open Source는 세계에서 가장 트래픽이 많은 사이트에서 가장 선호하는 웹 서버로 자리 잡았습니다. 이벤트 기반 아키텍처가 연결마다 프로세스나 스레드를 생성하는 웹 서버보다 확장성이 뛰어나기 때문입니다. 또한 NGINX Open Source는 업계에서 가장 널리 사용되는 API 게이트웨이로, Apigee, Axway, IBM DataPower, Kong, Red Hat 3scale, Torry Harris 등의 APIM 솔루션에서 API 트래픽을 처리하는 인프라 구성 요소입니다.

The NGINX Controller API 관리 모듈은 고성능 APIM 솔루션입니다. 이 블로그에서는 고성능으로 잘 알려진 경쟁 제품인 Kong과 성능을 비교해 보겠습니다. Kong은 NGINX를 기반으로 구축되었으며 Lua를 사용해 API 기능을 구현하는 반면, API 관리 모듈은 NGINX Plus 모듈로 구현된 네이티브 고성능 기능만을 사용합니다. NGINX의 API 관리 솔루션은 데이터 플레인과 컨트롤 플레인을 분리하는 혁신적인 아키텍처를 기반으로 구축되었습니다. 모든 API 호출은 컨트롤 플레인과 상호 작용할 필요 없이 API 게이트웨이(데이터 플레인) 역할을 하는 NGINX Plus에서 직접 처리됩니다. 따라서 남북 및 동서 트래픽 모두에서 고성능 API 트래픽 중개가 가능합니다.

결과를 살짝 미리 공개하자면, NGINX Controller API Management Module은 Kong보다 성능이 2배 뛰어납니다.

이번 테스트에 사용된 하드웨어와 실험실 공간을 제공해 주신 Intel에 특별히 감사드립니다. 전체 테스트 및 하드웨어에 대한 자세한 내용은 부록에서 확인할 수 있습니다.

단일 요청에 추가되는 지연 시간

이 테스트에서는 크기가 0KB 및 1KB인 파일에 대해 API 관리자가 단일 요청에 추가하는 지연 시간을 비교했습니다. 단일 HTTP 요청을 전송하기 위해 curl을 사용했습니다(자세히 보기).

Kong은 API Management Module에 비해 지연 시간을 증가시킵니다. 0KB 파일의 경우 44%, 1KB 파일의 경우 24% 증가합니다.

초당 API 호출 수

표준 HTTP 확장성 지표는 초당 요청 수(RPS)입니다. APIM 환경에서 이에 해당하는 지표는 초당 API 호출 수입니다. wrk를 사용하여 300개의 연결에서 3분 동안 0KB 또는 1KB 파일에 대한 요청을 연속으로 전송했습니다(자세히 보기).

API Management Module은 Kong보다 뛰어난 성능을 보였으며, 1KB 응답 기준으로 초당 2.6배 더 많은 API 호출을 처리했습니다.

CPU 사용량

API 관리 모듈은 CPU를 더 효율적으로 사용하므로 Kong보다 지연 시간이 짧고 초당 더 많은 API 호출을 처리합니다. 초당 API 호출 수를 늘려 가며 CPU 사용량을 측정했습니다. 단일 코어를 사용했기 때문에 초당 API 호출의 절대적인 수는 22개 코어를 사용한 이전 테스트보다 훨씬 적습니다(자세히 보기).

Kong은 사실상 초당 5,000회의 API 호출이 한계입니다. 이보다 호출량이 많아지면 지연 시간이 눈에 띄게 급증하며, 이는 시스템이 최대 부하 상태임을 나타냅니다. 초당 5,000회 호출 시 CPU 사용률은 93%로, API Management Module보다 73% 높습니다.

JWT 사용 시 초당 API 호출 수

마지막 테스트에서는 각 API 게이트웨이가 API 요청 인증에 선호되는 방식인 JSON 웹 토큰(JWT)을 얼마나 잘 검증하는지 측정합니다. 가장 중요한 API 엔드포인트에는 인증이 적용될 가능성이 높으므로, 이 테스트는 실제 환경의 구성을 더욱 가깝게 재현합니다.

두 게이트웨이 모두에 HS256으로 서명된 동일한 JWT를 사용했습니다(자세히 보기).

API 관리 모듈은 초당 JWT 인증 API 호출을 Kong보다 2배 이상 많이 처리합니다.

NGINX Controller의 작동 방식

NGINX Controller는 NGINX Plus 데이터 플레인을 관리하는 컨트롤 플레인 솔루션입니다. NGINX Controller를 사용하면 로드 밸런서, API 게이트웨이 또는 서비스 메시 환경의 프록시로 사용되는 NGINX Plus의 전체 수명 주기를 관리할 수 있습니다. NGINX Controller의 API Management Module을 사용하면 API를 정의, 게시, 보호, 모니터링 및 분석할 수 있습니다.

내부적으로 NGINX Controller는 NGINX Plus 구성을 생성하여 기반 NGINX Plus 데이터 플레인에 게시합니다. 핵심 구성 로더는 구성을 메모리에 저장하는 매우 효율적인 메커니즘을 갖추고 있어 API Management Module이 API에 높은 성능을 제공할 수 있습니다.

결론

많은 기업이 이미 NGINX Open Source를 API 게이트웨이로 사용하고 있습니다. Capital One은 NGINX Open Source를 사용하여 하루 120억 건의 API 호출 이상을 처리할 수 있도록 확장했습니다. 실제로 Kong을 비롯한 많은 경쟁업체가 자사의 APIM 솔루션 내부에서 NGINX Open Source를 사용합니다. 네이티브 고성능 NGINX 구성과 NGINX Plus 모듈을 기반으로 한 경량 설계 덕분에 API Management Module은 NGINX 파생 제품을 사용하는 경쟁 솔루션보다 더 뛰어난 확장성을 제공합니다.

지연 시간은 최종 사용자 경험을 평가하는 가장 중요한 지표 중 하나입니다. 지연 시간이 길면 앱의 응답성이 떨어져 사용자가 불편을 겪게 됩니다. API Management Module은 Kong에 비해 사용자 요청에 추가되는 지연 시간이 20~30% 더 짧습니다. 또한 시스템 리소스를 더 효율적으로 사용하여 동일한 워크로드에서 Kong보다 CPU 사용량이 40% 더 적습니다.

부록

토폴로지

모든 테스트는 단순한 플랫 레이어 2 네트워크에서 10GbE 링크로 연결된 세 대의 개별 머신을 사용하여 수행했습니다.

사용된 하드웨어

테스트에는 다음 하드웨어가 사용되었습니다. 세 대의 머신은 모두 동일한 사양이었습니다. 하이퍼스레딩은 사용하지 않았습니다. 이전 테스트에서는 하이퍼스레딩 사용에 따른 성능 차이가 크지 않았습니다.

CPU네트워크메모리
Intel® Xeon(R) CPU E5‑2699 v4 @ 2.20GHz, 22코어Intel Ethernet Controller 10‑Gigabit X540‑AT2128GB

사용된 소프트웨어

테스트에는 다음 소프트웨어가 사용되었습니다:

  • NGINX Controller API Management Module 버전 2.
  • Kong Open Source 버전 1.0.0. Kong Enterprise는 테스트하지 않았지만, 추가 기능 중 테스트와 관련된 기능은 없습니다(예: Kong Open Source와 Kong Enterprise는 동일한 JWT 플러그인을 사용함).
  • curl 버전 7.61.0.
  • Docker 버전 18.09.1. 관리를 간소화하기 위해 Kong과 API Management Module을 모두 Docker 컨테이너에서 실행했습니다. Docker를 사용하면 성능이 약 30% 저하되는 것으로 나타났지만, 상대적인 성능을 비교하는 것이므로 성능 저하보다 Docker 사용의 이점이 더 컸습니다.
  • mpstat systat 패키지 버전 12.0.1.
  • wrk 버전 4.1.0이며, 다음 지침에 따라 설치되었습니다.

NGINX 구성

테스트에는 다음 NGINX 구성을 사용했습니다.

upstream my_upstream {    keepalive 60;    server API-server:80;    keepalive_requests 3000000;    keepalive_timeout 300;}server {    listen 8000;    access_log off;    keepalive_requests 3000000;    keepalive_timeout 300;     tcp_nodelay on;    location /test {        set $apimgmt_environment 4;        set $apimgmt_definition 3;        set $upstream my_upstream;        set $upstream_protocol http;        rewrite ^ /_devel_4 last;    }    location = /_devel_4 {        internal;        set $apimgmt_definition_name my_api;        set $apimgmt_environment_name devel;        proxy_intercept_errors on;        proxy_http_version 1.1;        proxy_set_header Connection "";        proxy_pass $upstream_protocol://$upstream/0kb;      # 0-KB file        #proxy_pass $upstream_protocol://$upstream/1kb.bin; # 1-KB file    }}

성능을 극대화하기 위해 다음과 같이 설정했습니다. 다음 섹션에서 자세히 설명하듯이 Kong 구성에도 유사한 설정을 적용했습니다.

  • keepalive_requests 및 keepalive_timeout은 TCP 연결 설정으로 인한 오버헤드를 최소화하기 위해 높은 값으로 설정했습니다.
  • tcp_nodelay을 활성화하여 Nagle 알고리즘을 비활성화함으로써 성능을 소폭 개선했습니다.
  • access_log는 비활성화되었습니다. 이를 활성화하면 성능이 약 10% 저하됩니다.
  • 적절한 크기의 파일을 요청하기 위해 두 개의 proxy_pass 지시어를 사용했습니다.

Kong 구성

이전 섹션에서 설명한 NGINX 구성의 설정과 일치하도록 다음 구성 지시문을 kong.conf.default에 추가했습니다.

nginx_http_tcp_nodelay=onnginx_http_keepalive_requests=3000000nginx_http_keepalive_timeout=300proxy_access_log=off

API 서버로 연결되는 경로를 생성하기 위해 다음 Kong API 호출을 실행했습니다. 첫 번째 명령은 이름이 test인 서비스를 생성하고, 두 번째 명령은 서버를 가리키는 /test 경로를 생성합니다.

$ curl -X POST http://localhost:8001/services/ --data 'name=test' --data 'url=http://API-server:80/0kb'$ curl -X POST http://localhost:8001/services/test/routes --data 'paths[]=/test'

다음 명령은 각각 서비스와 라우트의 구성을 표시합니다. JSON 출력을 더 쉽게 읽을 수 있도록 출력을 jq 도구로 파이프합니다.

$ curl localhost:8001/services/ | jq '.'{  "next": null,  "data": [    {      "host": "172.20.40.32",      "created_at": 1556770191,      "connect_timeout": 60000,      "id": "f4629d56-550b-4b37-aa59-66d931aa6f37",      "protocol": "http",      "name": "test",      "read_timeout": 60000,      "port": 80,      "path": "/0kb",      "updated_at": 1556770191,      "retries": 5,      "write_timeout": 60000    }  ]}$ curl localhost:8001/services/test/routes | jq '.'{  "next": null,  "data": [    {      "created_at": 1556770191,      "methods": null,      "id": "a7b417af-ccd4-48f7-b787-ae19490194dc",      "service": {        "id": "f4629d56-550b-4b37-aa59-66d931aa6f37"      },      "name": null,      "hosts": null,      "updated_at": 1556770191,      "preserve_host": false,      "regex_priority": 0,      "paths": [        "/test"      ],      "sources": null,      "destinations": null,      "snis": null,      "protocols": [        "http",        "https"      ],      "strip_path": true    }  ]}

테스트 방법론

단일 요청에 추가되는 지연 시간

단일 요청 지연 시간 테스트에는 curl을 사용했습니다. 기준값을 설정하기 위해 먼저 API 게이트웨이를 거치지 않고 API 서버에 요청했습니다. 그런 다음 각 API 게이트웨이를 API 서버 앞에 두고 동일한 요청을 보내, 각 게이트웨이로 인해 추가되는 지연 시간을 측정했습니다.

$ curl -w "@curl-latency.txt" -o /dev/null -s http://target-server

The contents of curl-latency.txt의 내용:

    time_namelookup:  %{time_namelookup}n       time_connect:  %{time_connect}n    time_appconnect:  %{time_appconnect}n   time_pretransfer:  %{time_pretransfer}n      time_redirect:  %{time_redirect}n time_starttransfer:  %{time_starttransfer}n                    ----------n         time_total:  %{time_total}n

The chart in 단일 요청에 추가된 지연 시간 차트에는 밀리초 단위의 time_total 값이 표시됩니다. 다음은 출력 예시입니다:

$ curl -w "@curl-latency.txt" -o /dev/null -s http://192.0.2.1/api-endpoint    time_namelookup:  0.000035       time_connect:  0.000364    time_appconnect:  0.000000   time_pretransfer:  0.000401      time_redirect:  0.000000 time_starttransfer:  0.001701                    ----------         time_total:  0.001727

초당 API 호출 수

초당 API 호출 수를 테스트하기 위해 wrk를 사용했습니다. 이는 저희가 자주 사용하는 확장 가능한 벤치마킹 도구입니다. 다양한 매개변수 조합을 시도한 결과, 다음 조합에서 API Management Module과 Kong 모두 최고의 성능을 보였습니다:

$ wrk -t 22 -c 300 -d 180 http://target-server

이 명령은 22개의 wrk 스레드(코어당 1개)와 스레드 전체에 걸쳐 총 300개의 연결을 생성합니다. -d 매개변수는 테스트 지속 시간을 지정하며, 여기서는 180초(3분)입니다. 출력 예시:

$ wrk -t 22 -c 300 -d 180 http://192.0.2.1/api-endpointRunning 3m test @ http://192.0.2.1/api-endpoint  22 threads and 300 connections  Thread Stats   Avg      Stdev     Max   +/- Stdev    Latency    13.96ms    7.84ms 279.85ms   77.37%    Req/Sec     0.96k   298.23     1.88k    68.55%  3769861 requests in 3.00m, 36.25GB readRequests/sec:  20934.34Transfer/sec:    206.16MB

CPU 사용량

초당 API 호출 수를 측정하기 위해 mpstat(이 용도로 사용되는 표준 Linux 도구)로 CPU 사용량을 테스트하면서 wrk 명령을 실행했습니다. 다음은 가독성을 위해 두 줄로 나눈 출력 예시입니다:

$ mpstatLinux 4.18.0-13-generic (nbdw38) 	04/29/2019 	_x86_64_	(88 CPU)03:34:50 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  ...03:34:50 PM  all    0.04    0.00    0.02    0.00    0.00    0.03    0.00  ...      ... %guest  %gnice   %idle      ...   0.00    0.00   99.91

JWT 사용 시 초당 API 호출 수

초당 API 호출 수를 측정하기 위해 wrk 명령어로 JWT 성능을 테스트했으며, JWT를 Authorization: Bearer HTTP 헤더에 삽입하기 위해 -H 매개변수를 추가했습니다. 이 블로그 게시물의 안내에 따라 JWT와 JSON 웹 키(JWK)를 생성하고, JWT를 test.jwt라는 파일에 저장했습니다.

$ wrk -t 22 -c 300 -d 180 -H "Authorization: Bearer `cat test.jwt`" http://target-server


공유
태그: F5 NGINX, Tech, 2019

작성자 소개

관련 블로그 게시물

시청하기: KubeCon North America 2023에서의 NGINX Gateway Fabric
NGINX | 2023. 11. 30.

시청하기: KubeCon North America 2023에서의 NGINX Gateway Fabric

이 영상에서는 KubeCon의 NGINX 부스를 찾아가, 저희가 공개한 Kubernetes Gateway API 구현을 살펴봅니다.

F5 NGINX로 대규모 WAF 플릿을 확인하고 관리하는 2가지 방법
NGINX | 2023. 03. 23.

F5 NGINX로 대규모 WAF 플릿을 확인하고 관리하는 2가지 방법

앱 보안을 강화하는 두 가지 방법을 소개합니다. NGINX Management Suite를 통해 WAF 운영에 대한 가시성을 높이고, NGINX App Protect WAF를 활용해 코드형 보안을 구현하는 것입니다.

Ingress 컨트롤러 선택 가이드, 4부: NGINX Ingress Controller 옵션
NGINX | 2021. 09. 27.

Ingress 컨트롤러 선택 가이드, 4부: NGINX Ingress Controller 옵션

개발 주체, 개발 철학, 프로덕션 환경 준비도, 보안 및 지원을 기준으로 어떤 NGINX Ingress 컨트롤러가 가장 적합한지 알아보세요.

진화하는 공격 환경에 NGINX App Protect Denial of Service가 적응하는 방법
NGINX | 2021. 07. 06.

진화하는 공격 환경에 NGINX App Protect Denial of Service가 적응하는 방법

NGINX App Protect Denial of Service(DoS)가 계층 7 DoS 공격을 방어하기 위해 완화 방법을 실시간으로 조정하는 방식을 설명합니다. 정상적인 사용자 행동과 서버 상태에 대한 모델을 생성하여 공격을 나타내는 이상 징후를 감지하고 맞춤형 완화 시그니처를 적용할 수 있습니다.

NGINX Instance Manager를 활용한 대규모 구성 업데이트 및 인증서 관리
NGINX | 2021. 06. 30.

NGINX Instance Manager를 활용한 대규모 구성 업데이트 및 인증서 관리

NGINX Instance Manager 버전 1.0에는 두 가지 새로운 기능이 도입되었습니다. NGINX 인스턴스에 태그와 사용자 역할을 지정하면 전체 그룹에 구성을 한 번에 적용할 수 있습니다. 인증서 검사는 만료 예정인 인증서를 감지하여 서비스 중단을 방지할 수 있도록 인증서를 교체할 수 있게 해줍니다.

Netflix가 자사 CDN의 핵심으로 NGINX를 선택한 이유
NGINX | 2015. 03. 25.

Netflix가 자사 CDN의 핵심으로 NGINX를 선택한 이유

Netflix가 글로벌 콘텐츠 전송 네트워크인 Open Connect의 스트리밍 미디어 기술로 NGINX를 선택한 이유를 NGINX 개발자 Gleb Smirnoff에게서 알아보세요.