Nginx 高同時接続設定とパフォーマンス最適化の実践

网络协议

Nginx 高同時接続:アーキテクチャから実践まで

Nginxはイベント駆動・非ブロッキングI/Oアーキテクチャにより、単一サーバーで数万の同時接続を処理できます。しかし、デフォルト設定ではその潜力を十分に発揮できず、本番ワークロードに向けた深いチューニングが必要です。

最適化領域 キーパラメータ 影響範囲
プロセスモデル worker_processes, worker_connections 同時接続容量
イベントモデル use epoll, multi_accept イベント処理効率
負荷分散 upstream, proxy_next_upstream トラフィック分散とフォールトトレランス
バッファとタイムアウト proxy_buffers, keepalive_timeout メモリと接続再利用
圧縮 gzip, gzip_comp_level 転送帯域幅
セキュリティ limit_req, limit_conn トラフィック防護

1. Nginxアーキテクチャ:イベント駆動とワーカープロセス

Master-Workerモデル

NginxはMaster-Workerマルチプロセスアーキテクチャを採用:

  • Masterプロセス:設定読み込み、ポートバインド、Worker管理(fork/シグナル/リロード)
  • Workerプロセス:独立してリクエストを処理、1つのWorkerクラッシュが他に影響しない
# Nginxプロセス構造の確認
# ps aux | grep nginx
# root      1234  nginx: master process
# www-data  1235  nginx: worker process
# www-data  1236  nginx: worker process

イベント駆動モデル

NginxはReactorパターンに基づき、I/O多重化技術を使用:

I/Oモデル プラットフォーム パフォーマンス
epoll Linux 最適、O(1)イベント通知
kqueue FreeBSD/macOS 優秀、epollに類似
select 汎用 低い、fd_set上限1024
poll 汎用 普通、上限なし但し線形スキャン
events {
    use epoll;
    worker_connections 65535;
    multi_accept on;
    accept_mutex off;
}

multi_accept onはWorkerが全ての新規接続を一度に受け取るようにし、システムコールを削減。accept_mutex offは高同時接続時のサンダリングハード問題を回避(Linux 3.9+はSO_REUSEPORTをサポート)。


2. 核心同時接続設定

worker_processes

# CPUコア数を自動検出(推奨)
worker_processes auto;

# または手動指定(通常CPUコア数またはその2倍)
worker_processes 8;

チューニングのヒント

  • 通常autoに設定し、CPUコア数と一致させる
  • CPU集約型ワークロード(SSL、gzip):コア数に一致
  • I/O集約型ワークロード:2倍のコア数を検討

worker_connections

events {
    worker_connections 65535;
}

最大同時接続数 = worker_processes × worker_connections。システムのファイルディスクリプタ制限も調整が必要:

# 一時的な変更
ulimit -n 65535

# 永続的な変更(/etc/security/limits.conf)
* soft nofile 65535
* hard nofile 65535

worker_rlimit_nofile

# ワーカープロセスあたりの最大ファイルディスクリプタ数
worker_rlimit_nofile 65535;

完全な基本設定

user www-data;
worker_processes auto;
worker_rlimit_nofile 65535;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
    use epoll;
    worker_connections 65535;
    multi_accept on;
    accept_mutex off;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile      on;
    tcp_nopush    on;
    tcp_nodelay   on;
    keepalive_timeout 65;
    keepalive_requests 100;
}

3. 負荷分散アルゴリズムの詳細

基本設定

upstream backend {
    server 10.0.0.1:8080 weight=5;
    server 10.0.0.2:8080 weight=3;
    server 10.0.0.3:8080 weight=2;
    server 10.0.0.4:8080 backup;
}

5つのスケジューリングアルゴリズムの比較

アルゴリズム ディレクティブ 特徴 ユースケース
ラウンドロビン (デフォルト) 順次分配、均等 バックエンド性能が同一
加重ラウンドロビン weight=N 重み比で分配 バックエンド性能に差異
最小接続 least_conn 接続数が最も少ないサーバーに優先分配 長接続/リクエスト時間に差異
IPハッシュ ip_hash 同一IPを同一サーバーに固定 セッション維持が必要
ランダム random ランダム選択 ステートレスサービス
一貫性ハッシュ hash $key consistent 一貫性ハッシュリング キャッシュサーバー

least_conn設定

upstream api_backend {
    least_conn;
    server 10.0.0.1:8080;
    server 10.0.0.2:8080;
    server 10.0.0.3:8080;
}

ip_hash設定

upstream web_backend {
    ip_hash;
    server 10.0.0.1:8080;
    server 10.0.0.2:8080;
    server 10.0.0.3:8080;
}

注意ip_hashbackupweightをサポートしません。本番環境では一貫性ハッシュの使用を推奨。

一貫性ハッシュ設定

upstream cache_backend {
    hash $request_uri consistent;
    server 10.0.0.1:8080;
    server 10.0.0.2:8080;
    server 10.0.0.3:8080;
}

4. アップストリームヘルスチェック

パッシブヘルスチェック(内蔵)

upstream backend {
    server 10.0.0.1:8080 max_fails=3 fail_timeout=30s;
    server 10.0.0.2:8080 max_fails=3 fail_timeout=30s;
    server 10.0.0.3:8080 max_fails=3 fail_timeout=30s;
}
パラメータ 意味 デフォルト
max_fails 失敗回数の閾値、超過で利用不可とマーク 1
fail_timeout 利用不可マークの持続時間 10s

アクティブヘルスチェック(nginx-upstream-check-module)

upstream backend {
    server 10.0.0.1:8080;
    server 10.0.0.2:8080;

    check interval=3000 rise=2 fall=3 timeout=1000 type=http;
    check_http_send "HEAD /health HTTP/1.0\r\n\r\n";
    check_http_expect_alive http_2xx http_3xx;
}

proxy_next_upstreamフォールトトレランス

proxy_next_upstream error timeout http_502 http_503 http_504;
proxy_next_upstream_timeout 10s;
proxy_next_upstream_tries 3;

5. バッファとタイムアウトのチューニング

プロキシバッファ

proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 16k;
proxy_busy_buffers_size 32k;
パラメータ 意味 推奨値
proxy_buffer_size レスポンスヘッダバッファサイズ 4k-8k
proxy_buffers レスポンスボディバッファ数とサイズ 8 16k
proxy_busy_buffers_size ビジーバッファサイズ proxy_buffers合計の半分

タイムアウト設定

proxy_connect_timeout 5s;
proxy_send_timeout 10s;
proxy_read_timeout 30s;

client_body_timeout 12s;
client_header_timeout 12s;
send_timeout 10s;

keepalive_timeout 65s;
keepalive_requests 100;

アップストリームKeepaliveコネクションプール

upstream backend {
    server 10.0.0.1:8080;
    server 10.0.0.2:8080;
    keepalive 32;
    keepalive_requests 100;
    keepalive_timeout 60s;
}

server {
    location / {
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_pass http://backend;
    }
}

keepalive 32は各Workerがバックエンドとの32個のアイドル長接続を維持し、頻繁なTCPハンドシェイクを回避。


6. Gzip圧縮の最適化

gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_min_length 1024;
gzip_http_version 1.1;
gzip_types
    text/plain
    text/css
    text/xml
    text/javascript
    application/json
    application/javascript
    application/xml
    application/xml+rss
    application/vnd.ms-fontobject
    application/x-font-ttf
    font/opentype
    image/svg+xml;
gzip_buffers 16 8k;
gzip_disable "msie6";
パラメータ 説明 推奨値
gzip_comp_level 圧縮レベル 1-9 4-6(CPUと圧縮率のバランス)
gzip_min_length 最小圧縮長 1024(小ファイルは圧縮で逆に大きくなる)
gzip_types 圧縮するMIMEタイプ 必要に応じて追加、画像は除外
gzip_buffers 圧縮バッファ 16 8k

7. 静的ファイルサービとキャッシュ

静的ファイル最適化

server {
    listen 80;
    server_name static.example.com;
    root /var/www/static;

    location / {
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;

        open_file_cache max=10000 inactive=20s;
        open_file_cache_valid 30s;
        open_file_cache_min_uses 2;
        open_file_cache_errors on;

        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    location ~* \.(js|css)$ {
        expires 7d;
        add_header Cache-Control "public, immutable";
    }

    location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ {
        expires 365d;
        add_header Cache-Control "public, immutable";
    }
}

open_file_cacheの説明

パラメータ 意味
max=N キャッシュ最大ファイルディスクリプタ数
inactive=T キャッシュエントリの寿命
valid=T キャッシュ有効性チェック間隔
min_uses=N inactive期間内の最小アクセス回数
errors ファイル検索エラーをキャッシュするか

8. SSL/TLSパフォーマンス最適化

セッションキャッシュ

ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets on;

shared:SSL:10m — 全Workerが10MBのセッションキャッシュを共有、約40,000セッションをキャッシュ可能。

OCSP Stapling

ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

完全なSSL設定

server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate     /etc/nginx/ssl/example.com.pem;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers on;

    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets on;

    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;

    ssl_buffer_size 4k;
}

9. レート制限と防護

リクエストレート制限(limit_req)

limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/s;

server {
    location /api/ {
        limit_req zone=api_limit burst=200 nodelay;
        proxy_pass http://backend;
    }
}
パラメータ 意味
rate=100r/s IPあたり毎秒100リクエスト
burst=200 200リクエストのバーストを許可
nodelay バーストリクエストを遅延させず、超過は即座に拒否

同時接続数制限(limit_conn)

limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

server {
    location /api/ {
        limit_conn conn_limit 50;
        proxy_pass http://backend;
    }
}

帯域幅制限

location /download/ {
    limit_rate 500k;
    limit_rate_after 10m;
}

最初の10MBは速度制限なし、その後500KB/sに制限。


10. リバースプロキシ設定

server {
    listen 80;
    server_name api.example.com;

    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_redirect off;
        proxy_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 16k;
    }

    location /ws/ {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_read_timeout 3600s;
    }
}

11. 一般的なエラーのトラブルシューティング

502 Bad Gateway

原因:Nginxがバックエンドサービスに接続できない。

# バックエンドサービスが稼働しているか確認
curl -I http://10.0.0.1:8080/health

# Nginxエラーログの確認
tail -f /var/log/nginx/error.log | grep 502

# 一般的な原因:
# 1. バックエンドサービスが未起動またはクラッシュ
# 2. バックエンドポートの設定ミス
# 3. バックエンドの過負荷で接続拒否
# 4. SELinux/ファイアウォールによるブロック

504 Gateway Timeout

原因:バックエンドサービスのレスポンスタイムアウト。

# タイムアウトを増加
proxy_connect_timeout 10s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
# トラブルシューティング手順
# 1. バックエンドのレスポンス時間を確認
curl -o /dev/null -s -w "time_total: %{time_total}\n" http://backend/api
# 2. バックエンドログでスロークエリを確認
# 3. ネットーク遅延を確認
ping -c 5 10.0.0.1

429 Too Many Requests

原因:レート制限ルールのトリガー。

# カスタムレート制限レスポンス
limit_req_status 429;

12. セキュリティ強化

セキュリティレスポンスヘッダ

add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

DDoS緩和

limit_req_zone $binary_remote_addr zone=ddos:10m rate=30r/s;
limit_conn_zone $binary_remote_addr zone=ddos_conn:10m;

server {
    limit_req zone=ddos burst=50 nodelay;
    limit_conn ddos_conn 30;

    client_body_buffer_size 16k;
    client_max_body_size 1m;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 8k;
}

機密パスのブロック

location ~ /\.(git|svn|env) {
    deny all;
    return 404;
}

location ~* /(wp-admin|phpmyadmin|adminer) {
    deny all;
    return 404;
}

13. パフォーマンスベンチマーク

wrkベンチマーク

# wrkのインストール
git clone https://github.com/wg/wrk.git
cd wrk && make && sudo cp wrk /usr/local/bin/

# ベンチマーク(12スレッド、400接続、30秒間)
wrk -t12 -c400 -d30s http://example.com/

# レイテンシ分布付き
wrk -t12 -c400 -d30s --latency http://example.com/

# POSTリクエストテスト
wrk -t4 -c200 -d10s -s post.lua http://example.com/api

abベンチマーク

# Apache Benchのインストール
# Ubuntu: apt install apache2-utils

# ベンチマーク(200同時接続、10000リクエスト)
ab -n 10000 -c 200 http://example.com/

# Keep-Alive付き
ab -n 10000 -c 200 -k http://example.com/

ベンチマーク結果の分析

指標 意味 参考値
Requests/sec 毎秒処理リクエスト数 静的アセット > 10000
Latency (p99) 99パーセンタイルレイテンシ < 100ms
Transfer/sec 毎秒転送データ量 ワークロードに依存
Socket errors 接続エラー数 0であるべき

14. FAQ

Q: worker_processesをautoに設定後、Worker数がCPUコア数と一致しない?

A: auto/proc/cpuinfoから利用可能なコア数を読み取ります。コンテナでcgroup CPU制限が設定されている場合、Nginx 1.19+のみがcgroup制限を検出します。旧バージョンは手動設定が必要です。

Q: worker_connectionsを65535に設定後、実際の同時接続数が上がらない?

A: システム制限も調整が必要:ulimit -nnet.core.somaxconnnet.ipv4.tcp_max_syn_backlogfs.file-max

Q: ip_hashと一貫性ハッシュのどちらを選ぶべきか?

A: ip_hashはシンプルですがweight/backupをサポートせず、スケール時に大量のセッション移行が発生します。一貫性ハッシュはスケール時に隣接ノードのみ影響 — キャッシュ層に推奨。

Q: gzip_comp_levelはいくつに設定すべきか?

A: 4-6が最適。レベル1-3は圧縮率が低く、7-9はCPU消費が大幅に増加するが圧縮率の向上は微々たるもの。実際のテストではレベル6と9の圧縮率差は2-3%のみだが、CPU消費は50%以上増加。

Q: Nginxのリアルタイムステータスを監視するには?

A: stub_statusモジュールを有効化し、Prometheus + Grafanaまたはngxtopツールでリアルタイム監視。

location /nginx_status {
    stub_status on;
    access_log off;
    allow 127.0.0.1;
    deny all;
}

Q: リクエストを落とさずNginxをグレースフルリロードするには?

A: nginx -s reloadを使用。Masterが設定をリロードし、新しいWorkerを起動、古いWorkerは現在のリクエスト処理完了後に終了。


おすすめツール:/encode/base64で設定ファイルをエンコード、/encode/hashで設定ハッシュチェックサムを生成、/json/formatでNginx JSONログをフォーマット。

ブラウザローカルツールを無料で試す →

#Nginx#高并发#性能优化#负载均衡#教程