Web Server

Web ServerはHTTPリクエストを受け付け、静的ファイルの配信やアプリケーションサーバーへのプロキシを担当します。 NginxとApacheのアーキテクチャの違いを理解することで、適切な設定とトラブルシューティングが可能になります。

Nginx vs Apache アーキテクチャ


┌─────────────────────────────────────────────────────────────────────────┐
│                          Nginx (イベント駆動)                            │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│   Master Process (設定読込、Worker管理)                                  │
│         │                                                                │
│         ├── Worker Process 1 ─── Event Loop ─┬─ Connection 1            │
│         │                                    ├─ Connection 2            │
│         │                                    ├─ Connection 3            │
│         │                                    └─ ... (数千接続)          │
│         │                                                                │
│         ├── Worker Process 2 ─── Event Loop ─┬─ Connection N            │
│         │                                    └─ ...                     │
│         │                                                                │
│         └── Worker Process N (通常 = CPU core数)                        │
│                                                                          │
│   特徴: 1 Worker = 数千接続、非ブロッキングI/O、低メモリ消費            │
└─────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────┐
│                    Apache (プロセス/スレッド駆動)                        │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│   【prefork MPM】                    【worker MPM】                      │
│                                                                          │
│   Parent Process                     Parent Process                      │
│         │                                  │                             │
│         ├── Child Process 1 ── Conn 1      ├── Child Process 1          │
│         ├── Child Process 2 ── Conn 2      │     ├── Thread 1 ── Conn 1 │
│         ├── Child Process 3 ── Conn 3      │     ├── Thread 2 ── Conn 2 │
│         └── ...                            │     └── Thread N           │
│                                            │                             │
│   1プロセス=1接続                          └── Child Process 2          │
│   メモリ消費大                                   ├── Thread 1           │
│   mod_php利用可                                  └── Thread N           │
│                                                                          │
│                                      1スレッド=1接続                    │
│                                      preforkより効率的                  │
└─────────────────────────────────────────────────────────────────────────┘
特性NginxApache (prefork)Apache (worker/event)
処理モデルイベント駆動プロセスベーススレッドベース
同時接続数万接続可能数百程度数千程度
メモリ/接続~数KB~数十MB~数MB
静的ファイル非常に高速普通普通
動的コンテンツFastCGI経由mod_php内蔵可FastCGI推奨
.htaccess非対応対応対応
設定リロードダウンタイムなしgraceful restartgraceful restart

Nginx 実践設定

基本構成

# /etc/nginx/nginx.conf

# Workerプロセス数(通常はCPUコア数に合わせる)
worker_processes auto;

# 1 Workerあたりの最大接続数
events {
    worker_connections 4096;    # デフォルト: 512
    use epoll;                  # Linux: epoll使用
    multi_accept on;            # 一度に複数接続受付
}

http {
    # ファイル送信最適化
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    # タイムアウト設定
    keepalive_timeout 65;
    client_body_timeout 60;
    client_header_timeout 60;
    send_timeout 60;

    # バッファサイズ
    client_body_buffer_size 128k;
    client_max_body_size 100m;     # アップロード上限

    # Gzip圧縮
    gzip on;
    gzip_types text/plain text/css application/json application/javascript;
    gzip_min_length 1000;

    include /etc/nginx/conf.d/*.conf;
}

リバースプロキシ設定

# /etc/nginx/conf.d/app.conf

upstream backend {
    # ロードバランシング(デフォルト: round-robin)
    # least_conn;          # 最小接続数
    # ip_hash;             # セッション維持

    server 127.0.0.1:8080 weight=3;
    server 127.0.0.1:8081 weight=1;
    server 127.0.0.1:8082 backup;    # バックアップサーバー

    # ヘルスチェック(Nginx Plus / OpenResty)
    # health_check interval=5s fails=3 passes=2;

    keepalive 32;    # upstream接続をkeep-alive
}

server {
    listen 80;
    server_name example.com;

    # アクセスログ
    access_log /var/log/nginx/app_access.log;
    error_log /var/log/nginx/app_error.log warn;

    # 静的ファイル
    location /static/ {
        alias /var/www/static/;
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    # アプリケーション
    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_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;

        # バッファリング
        proxy_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 32k;
    }

    # PHP-FPM連携
    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;

        # FastCGIタイムアウト
        fastcgi_read_timeout 300;
    }

    # ヘルスチェック用
    location /health {
        access_log off;
        return 200 "OK";
    }
}

パフォーマンスチューニング

# システム設定(/etc/sysctl.conf)
net.core.somaxconn = 65535              # listen backlog上限
net.core.netdev_max_backlog = 65535     # パケットキュー
net.ipv4.tcp_max_syn_backlog = 65535    # SYNキュー

# ファイルディスクリプタ上限(/etc/security/limits.conf)
nginx soft nofile 65535
nginx hard nofile 65535

# Nginx Worker設定
worker_rlimit_nofile 65535;   # Worker単位のFD上限

Apache 実践設定

MPM設定

# /etc/apache2/mods-available/mpm_prefork.conf
# mod_php使用時に必要(1プロセス=1リクエスト)
<IfModule mpm_prefork_module>
    StartServers             5      # 起動時のプロセス数
    MinSpareServers          5      # 最小待機プロセス
    MaxSpareServers         10      # 最大待機プロセス
    MaxRequestWorkers      150      # 最大同時リクエスト
    MaxConnectionsPerChild   0      # 0=無制限(メモリリーク対策で設定推奨)
</IfModule>

# /etc/apache2/mods-available/mpm_event.conf
# PHP-FPM使用時に推奨(高効率)
<IfModule mpm_event_module>
    StartServers             3
    MinSpareThreads         75
    MaxSpareThreads        250
    ThreadsPerChild         25      # 1プロセスあたりのスレッド数
    MaxRequestWorkers      400      # 最大同時リクエスト
    MaxConnectionsPerChild   0
</IfModule>

VirtualHost設定

# /etc/apache2/sites-available/app.conf

<VirtualHost *:80>
    ServerName example.com
    DocumentRoot /var/www/html

    # ログ設定
    ErrorLog ${APACHE_LOG_DIR}/app_error.log
    CustomLog ${APACHE_LOG_DIR}/app_access.log combined

    # ディレクトリ設定
    <Directory /var/www/html>
        Options -Indexes +FollowSymLinks
        AllowOverride All           # .htaccess有効化
        Require all granted
    </Directory>

    # PHP-FPM連携(mod_proxy_fcgi)
    <FilesMatch \.php$>
        SetHandler "proxy:unix:/var/run/php/php8.2-fpm.sock|fcgi://localhost"
    </FilesMatch>

    # リバースプロキシ
    ProxyPreserveHost On
    ProxyPass /api/ http://127.0.0.1:8080/
    ProxyPassReverse /api/ http://127.0.0.1:8080/

    # タイムアウト
    ProxyTimeout 60
</VirtualHost>

# mod_fcgid使用時(レガシー環境)
<IfModule mod_fcgid.c>
    FcgidMaxRequestLen 1073741824    # 1GB(大容量アップロード)
    FcgidIOTimeout 120               # I/Oタイムアウト
    FcgidConnectTimeout 30
    FcgidBusyTimeout 300
</IfModule>

運用・トラブルシューティング

よくあるエラーと対処

502 Bad Gateway

原因: upstream(アプリサーバー)に接続できない

# 確認コマンド
curl -I http://127.0.0.1:8080/health
systemctl status php8.2-fpm
tail -f /var/log/nginx/error.log | grep upstream

504 Gateway Timeout

原因: upstreamからの応答が遅い

# Nginx: proxy_read_timeout を延長
proxy_read_timeout 300;

# PHP-FPM: request_terminate_timeout 確認
; /etc/php/8.2/fpm/pool.d/www.conf
request_terminate_timeout = 300

413 Request Entity Too Large

原因: アップロードサイズ上限超過

# Nginx
client_max_body_size 100m;

# Apache + mod_fcgid
FcgidMaxRequestLen 104857600   # 100MB

# PHP
upload_max_filesize = 100M
post_max_size = 100M

Too many open files

原因: ファイルディスクリプタ枯渇

# 現在の使用状況
ls /proc/$(pgrep -o nginx)/fd | wc -l
cat /proc/$(pgrep -o nginx)/limits | grep "open files"

# 上限引き上げ(/etc/security/limits.conf)
nginx soft nofile 65535
nginx hard nofile 65535

設定変更の適用

# Nginx
nginx -t                     # 設定テスト(必ず実行)
nginx -s reload              # graceful reload(ダウンタイムなし)
systemctl reload nginx       # systemd経由

# Apache
apachectl configtest         # 設定テスト
apachectl graceful           # graceful restart
systemctl reload apache2     # systemd経由

監視すべきメトリクス

メトリクス確認方法閾値目安
Active connections/nginx_statusworker_connections × 80%
Request rateaccess.log解析ベースライン比較
5xx error rateerror.log監視< 1%
Upstream response time$upstream_response_timep99 < 1s

Nginx status module有効化

# /etc/nginx/conf.d/status.conf
server {
    listen 127.0.0.1:8080;
    location /nginx_status {
        stub_status on;
        allow 127.0.0.1;
        deny all;
    }
}

# 出力例
Active connections: 291
server accepts handled requests
 16630948 16630948 31070465
Reading: 6 Writing: 179 Waiting: 106

選定ガイド

Nginxを選ぶケース

  • ✓ 高トラフィック(10K+ 同時接続)
  • ✓ リバースプロキシ/LB用途
  • ✓ 静的コンテンツ配信が多い
  • ✓ メモリリソースを節約したい
  • ✓ コンテナ環境(軽量)

Apacheを選ぶケース

  • ✓ .htaccessが必須(共用ホスティング)
  • ✓ mod_rewrite等の複雑なルール
  • ✓ レガシーmod_php環境
  • ✓ Apache固有モジュールが必要
  • ✓ 中小規模サイト

現代的な構成例


Internet
    │
    ▼
CloudFront / ALB (SSL終端、キャッシュ)
    │
    ▼
Nginx (リバースプロキシ、静的配信)
    │
    ├─→ PHP-FPM (PHP)
    ├─→ Gunicorn (Python)
    └─→ Puma (Ruby)