API管理(APIM)市場には、多くのベンダーがひしめいています。最新の「フルライフサイクルAPI管理部門のGartner Magic Quadrant」では、22社のベンダーが評価され、そのうち7社がリーダー・クアドラントに位置付けられています。既存市場で競争するには、競合他社との差別化を図り、際立つための確固たるポジションを確立する必要があります。では、NGINXの「API管理」ソリューションは何が違うのでしょうか。
NGINXは、軽量で高性能なソフトウェアの開発を目指しています。NGINX Open Sourceは、世界で最もアクセスの多いサイトで広く採用されるWebサーバーとなっています。これは、接続ごとにプロセスやスレッドを生成するWebサーバーよりも、イベント駆動型アーキテクチャの方が優れたスケーラビリティを発揮するためです。また、NGINX Open Sourceは業界で最も広く普及しているAPIゲートウェイでもあり、Apigee、Axway、IBM DataPower、Kong、Red Hat 3scale、Torry HarrisなどのAPIMソリューションでAPIトラフィックを処理するインフラストラクチャコンポーネントです。
The NGINX Controller API Management Moduleは、高性能なAPIMソリューションです。このブログでは、そのパフォーマンスを、高性能で知られる競合製品のKongと比較します。KongはNGINXを基盤とし、Luaを使用してAPI機能を実装しています。一方、API Management Moduleは、NGINX Plusモジュールとして実装されたネイティブの高性能機能のみを使用しています。NGINXのAPI管理ソリューションは、データプレーンとコントロールプレーンを分離する革新的なアーキテクチャを採用しています。すべてのAPI呼び出しは、APIゲートウェイ(データプレーン)として機能するNGINX Plusによって、コントロールプレーンとのやり取りを必要とせずに直接処理されます。これにより、南北方向と東西方向の両方のトラフィックで、APIトラフィックを高いパフォーマンスで仲介できます。
結果を少しだけご紹介します。NGINX Controller API Management Moduleは、Kongの2倍のパフォーマンスを発揮します。
本テストで使用したハードウェアとラボスペースをご提供いただいたIntelに、心より感謝申し上げます。テストとハードウェアの詳細については、付録をご覧ください。
単一リクエストに追加されるレイテンシ
このテストでは、サイズが0 KBと1 KBのファイルについて、APIマネージャーによって単一のリクエストに追加されるレイテンシーを比較しました。単一のHTTPリクエストの送信には、curlを使用しました(詳細)。

Kongでは、API Management Moduleと比較して、0 KBのファイルで44%、1 KBのファイルで24%、レイテンシが増加します。
1秒あたりのAPI呼び出し数
HTTPの標準的なスケーラビリティ指標は、1秒あたりのリクエスト数(RPS)です。APIMでは、これに相当する指標として1秒あたりのAPI呼び出し数を使用します。wrkを使用し、300接続で0 KBまたは1 KBのファイルに対して3分間、リクエストを連続送信しました(詳細)。

API Management ModuleはKongを上回り、1 KBのレスポンスで1秒あたり2.6倍のAPIコールを処理しました。
CPU使用率
API Management ModuleはCPUをより効率的に使用するため、Kongよりもレイテンシーが低く、1秒あたりに処理できるAPI呼び出し数が多くなります。1秒あたりのAPI呼び出し数を段階的に増やしながら、CPU使用率を測定しました。今回は1コアを使用したため、1秒あたりのAPI呼び出し数の絶対値は、22コアを使用した前回のテストよりも大幅に少なくなっています(詳細)。

Kongの実質的な上限は毎秒5,000件のAPI呼び出しです。これを超える呼び出し量ではレイテンシーが顕著に急増し、システムが最大負荷に達していることが示されます。毎秒5,000件の呼び出し時のCPU使用率は93%で、API Management Moduleより73%高くなっています。
JWT使用時の1秒あたりのAPI呼び出し数
最後のテストでは、APIリクエストの認証方法として推奨されるJSON Web Token(JWT)を、各APIゲートウェイがどの程度適切に検証できるかを測定します。最も重要なAPIエンドポイントには認証が設定される可能性が高いため、このテストは実環境の構成をより忠実に再現しています。
両方のゲートウェイで、HS256を使用して署名した同じJWTを使用しました(詳細)。

API Management Moduleは、JWT認証済みAPI呼び出しを1秒あたり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を使用して、1日あたり120億件を超えるAPI呼び出しに対応できる規模まで拡張しています。実際、Kongをはじめとする多くの競合企業も、APIMソリューションの基盤にNGINX Open Sourceを使用しています。ネイティブの高性能なNGINX設定とNGINX Plusモジュールを基盤とする軽量設計により、API Management ModuleはNGINX派生の競合製品よりも優れたスケーラビリティを実現します。
レイテンシーは、エンドユーザーエクスペリエンスを左右する最も重要な指標の1つです。レイテンシーが高いとアプリの応答性が低下し、ユーザーの不満につながります。API Management Moduleによってユーザーリクエストに加わるレイテンシーは、Kongと比較して20~30%低くなります。また、システムリソースをより効率的に使用し、同じワークロードでのCPU使用量をKongより40%削減します。
付録
トポロジー

すべてのテストは、シンプルなフラット構成のレイヤー2ネットワーク上で、10 GbEリンクにより接続された3台の独立したマシンを使用して実施しました。
使用したハードウェア
テストには以下のハードウェアを使用しました。3台のマシンはすべて同一構成です。ハイパースレッディングは使用していません。以前のテストでは、ハイパースレッディングによるパフォーマンスの大きな違いは確認されませんでした。
| CPU | ネットワーク | メモリ |
|---|---|---|
| Intel® Xeon(R) CPU E5‑2699 v4 @ 2.20GHz、 22コア | Intel Ethernet Controller 10‑Gigabit X540‑AT2 | 128 GB |
使用したソフトウェア
テストには、以下のソフトウェアを使用しました。
- NGINX Controller API Management Moduleバージョン 2。
- Kong Open Source version 1.0.0。Kong Enterpriseはテストしていませんが、その追加機能はいずれも今回のテストには関係しません(たとえば、Kong Open SourceとKong Enterpriseでは同じJWTプラグインが使用されています)。
curlバージョン 7.61.0。- Docker version 18.09.1。管理を容易にするため、KongとAPI Management Moduleの両方をDockerコンテナ内で実行しました。Dockerを使用するとパフォーマンスが約30%低下することがわかりましたが、相対的なパフォーマンスを比較するため、Dockerを使用するメリットがパフォーマンス低下の影響を上回ると判断しました。
mpstat(systatパッケージのバージョン12.0.1)wrkversion 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%低下します。- 適切なファイルサイズをリクエストするために、2つの「
proxy_pass」ディレクティブを使用しました。
Kongの設定
以下の設定ディレクティブをkong.conf.defaultに追加し、前のセクションで説明したNGINX設定と一致させました。
nginx_http_tcp_nodelay=onnginx_http_keepalive_requests=3000000nginx_http_keepalive_timeout=300proxy_access_log=offAPIサーバーへのルートを作成するため、次のKong API呼び出しを実行しました。最初のコマンドでは「test」という名前のサービスを作成し、2つ目のコマンドではサーバーを参照するルート「/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-serverThe 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「単一リクエストに追加されるレイテンシ」のグラフには、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.0017271秒あたりのAPI呼び出し数
1秒あたりの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.16MBCPU使用率
CPU使用率は、mpstat(CPU使用率を測定するための標準的なLinuxツール)を使用し、1秒あたりのAPI呼び出し数を測定するwrkコマンドの実行中にテストしました。以下は出力例です(読みやすいように2行に分けています)。
$ 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.91JWT使用時の1秒あたりのAPI呼び出し数
JWTのパフォーマンスを、1秒あたりのAPI呼び出し数を測定するwrkコマンドでテストしました。その際、JWTを-HパラメーターでAuthorization: Bearer HTTPヘッダーに挿入しました。JWTとJSON Web Keys(JWKs)は、こちらのブログ記事の手順に従って生成し、JWTをtest.jwtという名前のファイルに保存しました。
$ wrk -t 22 -c 300 -d 180 -H "Authorization: Bearer `cat test.jwt`" http://target-server著者について

関連するブログ記事
チュートリアル:NGINXを使用してアプリケーション向けにOpenTelemetryを構成する
OpenTelemetryを使用してNGINXサーバーの状態と健全性をより明確に把握することで、問題のトラブルシューティングを行い、Webアプリケーションのパフォーマンスを向上できます。
AkitaのNGINX Plus認定モジュールでAPIエンドポイントの問題を特定・修正
Akita SoftwareのAPIオブザーバビリティ向け新しいNGINX Plus Certified Moduleを活用して、APIエンドポイントの問題をより迅速に特定し、修正できます。
JavaプロジェクトをスキャフォールディングしてKubernetesネイティブアプリを構築する方法
Red HatのシニアプリンシパルデベロッパーアドボケイトであるDaniel Oh氏が、Javaプロジェクトをゼロから構築するためのひな形を作成し、Kubernetesネイティブアプリケーションとしてビルドする方法を解説します。
F5 NGINXaaS for Azureのご紹介:Microsoft Azureでネイティブに利用できるSaaS型ロードバランシング
NGINXaaS for Azureは、NGINX PlusをAzureネイティブのSaaSとして利用できるサービスです。NGINXの設定を容易にリフト&シフトできるため、クラウド導入とモダンアプリの展開を加速できます。

SELinuxでNGINXおよびNGINX Plusを使用する
Red Hat Enterprise Linux(RHEL)および関連ディストリビューションでSecurity-Enhanced Linux(SELinux)を有効にすると、デフォルト設定によりNGINXとNGINX Plusの一部の操作が制限されます。この記事では、すべての機能を利用できるようにSELinuxの設定を変更する方法について説明します。
NGINX PlusによるAWS Auto Scalingグループの負荷分散
新しいnginx-asg-sync統合ソフトウェアにより、NGINX PlusはAWS Auto Scalingグループの負荷を直接分散できるため、クラウドでの負荷分散がさらに柔軟になります