コンテンツにスキップ

NGINX 設定

cloud-initプロビジョニングは、完全にパフォーマンス最適化されたNGINX CDNエッジ設定をデプロイします。このページでは、カーネルチューニングからキャッシュ動作、ベンダーヘッダーインジェクションまで、すべての設定レイヤーを説明します。すべての設定は、ピーク172,540 req/sに達する48時間の連続負荷テストで検証されています。

ファイル目的
/etc/sysctl.d/99-cdn-tuning.confLinuxカーネルネットワークチューニング
/etc/systemd/system/nginx.service.d/override.confNGINX用ファイルディスクリプタ制限
/etc/security/limits.d/99-nginx.confwww-dataユーザーのOS レベル制限
/etc/nginx/nginx.confNGINXメイン設定(ワーカー、バッファ、gzip、ロギング)
/etc/nginx/conf.d/cdn-edge.confCDNプロキシ設定(キャッシュ、アップストリーム、ヘッダー)

/etc/sysctl.d/99-cdn-tuning.conf を介してブート時に適用されます。

パラメータデフォルト目的
net.core.somaxconn655354096リッスンバックログキューサイズ
net.core.netdev_max_backlog655351000CPU単位の受信パケットバックログ
net.ipv4.tcp_max_syn_backlog65535256SYNリクエストキュー(バースト時のドロップを防止)
net.ipv4.tcp_tw_reuse12送信接続でTIME_WAITソケットを再利用
net.ipv4.ip_local_port_range1024-6553532768-60999エフェメラルポート範囲(28Kに対して64K)
net.core.rmem_max16 MB212 KB受信ソケットバッファの最大値
net.core.wmem_max16 MB212 KB送信ソケットバッファの最大値
net.ipv4.tcp_rmem4K/87K/16M4K/131K/6Mソケット単位の受信バッファ(最小/デフォルト/最大)
net.ipv4.tcp_wmem4K/65K/16M4K/16K/4Mソケット単位の送信バッファ(最小/デフォルト/最大)
net.ipv4.tcp_fin_timeout1560FIN_WAIT_2タイムアウト(より高速なソケットクリーンアップ)
net.ipv4.tcp_keepalive_time3007200アイドル5分後にキープアライブプローブを開始
net.ipv4.tcp_slow_start_after_idle01アイドル接続でも輻輳ウィンドウを維持
net.ipv4.tcp_max_tw_buckets2000000~65536TIME_WAITソケットの最大数
fs.file-max2097152可変システム全体のファイルディスクリプタ制限
vm.swappiness1060キャッシュデータにはスワップよりRAMを優先
worker_processes auto; # 4 workers on D4s_v5 (1 per vCPU)
worker_rlimit_nofile 65535; # Per-worker file descriptor limit
events {
use epoll; # Linux-optimized event model
worker_connections 8192; # 4 workers x 8192 = 32,768 max concurrent
multi_accept on; # Accept all pending connections per event loop
accept_mutex off; # Not needed with epoll + reuseport
}

/etc/systemd/system/nginx.service.d/override.conf のsystemdオーバーライドで、一致するように LimitNOFILE=65535 を設定します。

proxy_buffering on;
proxy_buffer_size 16k; # Header buffer (handles large CDN headers)
proxy_buffers 64 16k; # 1 MB per connection (64 x 16k)
proxy_busy_buffers_size 256k; # Can send 256k to client while still reading

256kのビジーバッファサイズは重要です — キャッシュされた最大レスポンスサイズを超える必要があります(Juice Shopは75 KB)。元の64k設定は負荷時にシリアライゼーションを引き起こしていました。

gzip on;
gzip_comp_level 4; # Balance: ~85% of max compression at ~40% CPU
gzip_min_length 256; # Skip tiny responses (gzip header overhead)
gzip_vary on; # Vary: Accept-Encoding for correct caching
gzip_proxied any; # Compress all proxied responses
gzip_types text/plain text/css text/javascript text/xml
application/json application/javascript application/xml
application/xml+rss application/atom+xml
application/ld+json application/manifest+json
image/svg+xml;
open_file_cache max=200000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;

キャッシュされたオブジェクトのファイルディスクリプタとメタデータをキャッシュし、ホットファイルに対する stat() および open() システムコールを排除します。

keepalive_timeout 65;
keepalive_requests 100000; # Was 1000 — caused connection recycling at 90K req/s

90K req/sで keepalive_requests 1000 の場合、接続は11秒ごとにリサイクルされ、TIME_WAITソケットが発生していました。100,000に増加することで、この問題を完全に解消しました。

log_format cdn '$remote_addr [$time_local] "$request" $status $body_bytes_sent $upstream_cache_status $request_time';
access_log /var/log/nginx/access.log cdn buffer=256k flush=5s;

cdn ログフォーマットには、レイテンシ分析用の $upstream_cache_status(HIT/MISS)と $request_time が含まれます。バッファードロギング(256k/5sフラッシュ)により、高負荷時のI/Oオーバーヘッドが軽減されます。

アップストリームキープアライブ

Section titled “アップストリームキープアライブ”
upstream origin_backend {
server 20.12.78.159:80;
keepalive 256; # Persistent connections per worker to origin
keepalive_timeout 60s;
keepalive_requests 1000;
}

4ワーカー x 256キープアライブ = オリジンへの1,024のウォーム接続。proxy_http_version 1.1proxy_set_header Connection "" を組み合わせることで、すべてのキャッシュミスにおけるTCPハンドシェイクオーバーヘッドを排除します。

proxy_cache_path /var/cache/nginx/cdn
levels=1:2
keys_zone=cdn_cache:32m
max_size=25g
inactive=24h
use_temp_path=off;
パラメータ目的
keys_zone=cdn_cache:32m32 MB共有メモリ約256,000のキャッシュキーとメタデータを格納
max_size=25g25 GBディスク制限30 GB OSディスクの大部分を使用。制限時にLRUエビクション
inactive=24h24時間非アクティブタイムアウト24時間アクセスされないコンテンツはエビクションされる(TTLとは異なる)
use_temp_path=offキャッシュディレクトリに直接書き込みクロスファイルシステムのファイル移動を回避
proxy_cache cdn_cache;
proxy_cache_valid 200 301 302 4h;
proxy_cache_valid 404 1m;
proxy_cache_key "$scheme$host$request_uri";
proxy_cache_lock on;
proxy_cache_lock_age 3s;
proxy_cache_lock_timeout 3s;
proxy_cache_background_update on;
proxy_cache_use_stale updating error timeout http_500 http_502 http_503 http_504;
proxy_ignore_headers Set-Cookie Cache-Control Expires Vary;
proxy_hide_header X-Cache-Status;
proxy_hide_header Vary;
ディレクティブ目的
proxy_cache_valid 200 301 302 4h4時間TTLキャッシュコンテンツは4時間有効(リフレッシュウェーブによるスループット低下を軽減するために延長)
proxy_cache_lock onサンダリングハード防止未キャッシュURLに対して1リクエストのみがオリジンに送信され、他はキャッシュ充填を待機
proxy_cache_lock_age 3sロックタイムアウト最初のリクエストが3秒以内に完了しない場合、別のリクエストを通す
proxy_cache_background_update onゼロレイテンシリフレッシュバックグラウンドでリフレッシュしながら、即座にステイルコンテンツを提供
proxy_cache_use_staleレジリエンスオリジンエラー(500/502/503/504)時やアップデート中にステイルコンテンツを提供
proxy_ignore_headers強制キャッシュオリジンのSet-Cookie、Cache-Control、Expires、Varyを無視 — CDNがTTLとVary動作を決定(Juice Shopは max-age=0 とトリプル Vary ヘッダーを送信し、効果的なキャッシュを阻害していた)
proxy_hide_header X-Cache-Statusオリジンヘッダーを除去オリジンのNGINXが独自のX-Cache-Statusを追加するため、CDNのキャッシュステータスのみが表示されるように除去
proxy_hide_header Varyキャッシュフラグメンテーションを防止オリジンが複数の Vary: Accept-Encoding ヘッダーを送信。これを除去することで、Accept-Encoding の順列によるキャッシュキーのフラグメンテーションを防止。NGINXの gzip_vary on が正しい単一の Vary ヘッダーを自動的に追加
proxy_read_timeout 30s;
proxy_connect_timeout 10s;
proxy_send_timeout 15s;

負荷時にオリジンにより多くのレスポンス時間を与えつつ、接続問題では素早くフェイルします。

server {
listen 80 reuseport; # Kernel distributes connections across all 4 workers
server_name _;
}

reuseportSO_REUSEPORT を有効にします — カーネルが受信接続をワーカープロセスに直接分散し、acceptミューテックスの競合を排除します。

シミュレーターは、5つの主要CDNベンダーすべてのヘッダーを同時にインジェクトします。これにより、どのCDNをシミュレートしているかに関係なく、F5 XCを任意のベンダーの「Trusted Client IP Header」で設定し、リアルなヘッダーペイロードを確認できます。

業界標準ヘッダー(全CDN共通)

Section titled “業界標準ヘッダー(全CDN共通)”
ヘッダー目的
X-Forwarded-ForクライアントIPチェーン標準転送IP
X-Forwarded-Protohttp または https元のクライアントプロトコル
X-Forwarded-Host元のホスト名元のHostヘッダー
X-Forwarded-Portサーバーポート元のポート
X-Real-IPクライアントIP単一のクライアントIP(nginx慣例)
Via1.1 cdn-simulatorプロキシ識別
ForwardedRFC 7239形式標準化された転送ヘッダー
CDN-Loopcdn-simulatorループ検出
ヘッダー目的
True-Client-IPクライアントIP元のエンドユーザーIPアドレス
X-Akamai-Edgescape複合地理情報文字列georegion、country_code、region_code、city、dma、pmsa、msa、areacode、county、fips、lat、long、timezone、zip、continent、throughput、bw、network、asnum、network_type
X-Akamai-Device-Characteristicsデバイスプロパティbrand_name、model_name、is_mobile、is_tablet、is_wireless_device、device_os、device_os_version、resolution_width、resolution_height
X-Akamai-Request-IDリクエストUUID一意のリクエスト識別子
ヘッダー目的
CF-Connecting-IPクライアントIP真のクライアントIP(常に存在)
CF-IPCountryUS2文字の国コード
cf-ipcitySan Joseクライアントの都市
cf-ipcontinentNA大陸コード
cf-iplatitude / cf-iplongitude座標ジオロケーション
cf-region / cf-region-codeCalifornia / CA地域情報
cf-metro-code807米国メトロコード
cf-postal-code95113郵便番号
cf-timezoneAmerica/Los_AngelesIANAタイムゾーン
Cf-Ray{request_id}-SJCPOP IATAコード付きの一意のレイID
CF-Visitor{"scheme":"https"}訪問者プロトコル情報
cf-bot-score85ボットスコア(1=ボット、99=人間)
cf-verified-botfalse既知の正当なボットフラグ
cf-ja3-hashe7d705a3286e19ea42f587b344ee6865JA3 TLSフィンガープリント
cf-ja4t13d1516h2_8daaf6152771_b0da82dd1658JA4 TLSフィンガープリント
ヘッダー目的
CloudFront-Viewer-AddressIP:portクライアントIPとソースポート
CloudFront-Viewer-CountryUS国コード
CloudFront-Viewer-Country-NameUnited States国名(フル)
CloudFront-Viewer-Country-RegionCA地域コード
CloudFront-Viewer-Country-Region-NameCalifornia地域名(フル)
CloudFront-Viewer-CitySan Joseクライアントの都市
CloudFront-Viewer-Postal-Code95113郵便番号
CloudFront-Viewer-Latitude / Longitude37.33530 / -121.89300ジオロケーション
CloudFront-Viewer-Time-ZoneAmerica/Los_AngelesIANAタイムゾーン
CloudFront-Viewer-Metro-Code807米国メトロコード
CloudFront-Viewer-ASN7018自律システム番号
CloudFront-Viewer-Http-Version2.0クライアントHTTPバージョン
CloudFront-Forwarded-Protohttps元のプロトコル
CloudFront-Viewer-TLSTLSv1.3:TLS_AES_128_GCM_SHA256:sessionResumedTLS詳細
CloudFront-Viewer-JA3-Fingerprinte7d705a3286e19ea42f587b344ee6865JA3 TLSフィンガープリント
CloudFront-Is-Desktop-Viewertrue/falseデバイス検出
CloudFront-Is-Mobile-Viewertrue/falseデバイス検出
CloudFront-Is-Tablet-Viewertrue/falseデバイス検出
CloudFront-Is-SmartTV-Viewerfalseデバイス検出
X-Amz-Cf-IdエンコードされたIDCloudFrontリクエスト識別子
ヘッダー目的
Fastly-Client-IPクライアントIP真のクライアントIP
Fastly-SSL1TLS経由の接続
Fastly-Client1クライアント向けリクエスト(シールドではない)
Fastly-FFcache-sjc3120-SJCキャッシュノード識別
X-Geo-Country-CodeUS国(VCL変数慣例)
X-Geo-Country-Code3USA3文字の国コード
X-Geo-Country-NameUnited States国名(フル)
X-Geo-CitySan Joseクライアントの都市
X-Geo-RegionCA地域コード
X-Geo-Continent-CodeNA大陸
X-Geo-Latitude / X-Geo-Longitude37.3353 / -121.8938ジオロケーション
X-Geo-Postal-Code95113郵便番号
X-Geo-Metro-Code807米国メトロコード
X-Geo-ASN7018自律システム番号
X-Geo-Conn-Speedbroadband接続速度クラス
X-Geo-Conn-Typewired接続タイプ
ヘッダー目的
X-Azure-ClientIPクライアントIPクライアントIPアドレス
X-Azure-SocketIPクライアントIPTCPソケットソースIP
X-Azure-Refエンコードされた参照文字列トラブルシューティング用の一意のリクエスト参照
X-Azure-FDIDa0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1Front Doorリソース識別子
X-Azure-RequestChainhops=1ループ検出ホップカウント

レスポンスヘッダー(クライアントレスポンスに追加)

Section titled “レスポンスヘッダー(クライアントレスポンスに追加)”
ヘッダー目的
X-Cache-StatusHITMISSEXPIREDSTALEUPDATINGこのリクエストのキャッシュ動作
X-CDN-Edgecdn-simulatorこのエッジノードの識別
X-CDN-POPSJCシミュレートされたPoint of Presence IATAコード
X-Served-Bycache-sjc3120-SJCFastly形式のシミュレートされたキャッシュノード
X-Request-IDUUID(リクエストごと)一意のリクエスト識別子

シミュレーターは、NGINXの map ディレクティブを使用して User-Agent ヘッダーからデバイスタイプを検出します:

  • モバイル: iPhone、Android(タブレット以外)、iPod、BlackBerry、Opera Mini、IEMobileにマッチ
  • タブレット: iPad、Androidタブレット、Kindle、PlayBookにマッチ
  • デスクトップ: モバイルにもタブレットにもマッチしない場合のデフォルト

デバイスタイプは以下に反映されます:

  • CloudFront-Is-Desktop-Viewer / CloudFront-Is-Mobile-Viewer / CloudFront-Is-Tablet-Viewer
  • X-Akamai-Device-Characteristicsis_mobileis_tabletis_wireless_device フィールド)
Terminal window
ssh azureuser@<PUBLIC_IP>
# Update upstream server
sudo sed -i 's|server .*;|server NEW_HOST:80;|' /etc/nginx/conf.d/cdn-edge.conf
# Clear cache and reload
sudo rm -rf /var/cache/nginx/cdn/*
sudo nginx -t && sudo systemctl reload nginx

または terraform.tfvarsorigin_host を更新して terraform apply を実行し、再プロビジョニングします。

Terminal window
ssh azureuser@<PUBLIC_IP>
sudo rm -rf /var/cache/nginx/cdn/*
sudo systemctl reload nginx
Terminal window
# Object count and disk usage
sudo find /var/cache/nginx/cdn -type f | wc -l
sudo du -sh /var/cache/nginx/cdn
# Recent access log with cache status
tail -20 /var/log/nginx/access.log
Terminal window
# Real-time connections and socket states
ss -s
# NGINX worker CPU usage
top -bn1 | grep nginx
# Upstream keepalive connections
ss -tn state established dst <ORIGIN_IP> | wc -l
# TIME_WAIT socket count
ss -tn state time-wait | wc -l

パフォーマンスベンチマーク結果

Section titled “パフォーマンスベンチマーク結果”

48時間の連続負荷テストで検証済み:

メトリクス
ピークスループット(キャッシュ済み)172,540 req/s
持続スループット(キャッシュ済み)85,000-103,000 req/s
ピーク接続数15,000同時接続
キャッシュヒット率100%(ウォームアップ後)
負荷時メモリ1.2 GB安定(16 GBの8%)
ピーク時CPU100%(4コア — CPUが上限)
48時間テスト中のエラー0
メモリリーク検出なし
接続リーク検出なし