マルチスタックWebサーバー環境の構築と運用管理

Webサーバーとリバースプロキシの構築 (Nginx)

Nginxをコンパイルする際、運用環境に応じたモジュールを静的または動的に組み込む必要があります。以下は、SSL、HTTP/2、ストリーミング、および画像処理機能を有効にしたコンパイルオプションの例です。

# ./configure \
  --prefix=/usr/local/web/nginx \
  --user=webuser \
  --group=webuser \
  --with-http_ssl_module \
  --with-http_v2_module \
  --with-http_realip_module \
  --with-http_gzip_static_module \
  --with-http_sub_module \
  --with-stream_ssl_preread_module \
  --with-http_image_filter_module=dynamic \
  --with-pcre \
  --with-file-aio \
  --with-http_stub_status_module

Nginxのメイン設定ファイル(nginx.conf)では、ワーカープロセスの最適化、接続数の制限、およびGzip圧縮の設定を行います。セキュリティのためバージョン情報の非表示も推奨されます。

user webuser;
worker_processes  4;
worker_rlimit_nofile 65535;

events {
    use epoll;
    multi_accept on;
    worker_connections  4096;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    log_format  json_combined  escape=json '{'
        '"time_local":"$time_local",'
        '"remote_addr":"$remote_addr",'
        '"request":"$request",'
        '"status": "$status",'
        '"body_bytes_sent":"$body_bytes_sent",'
        '"request_time":"$request_time",'
        '"http_referrer":"$http_referer",'
        '"http_user_agent":"$http_user_agent"'
    '}';

    sendfile        on;
    tcp_nopush      on;
    tcp_nodelay     on;
    keepalive_timeout  65;
    server_tokens   off;

    # Gzip Settings
    gzip on;
    gzip_min_length 1024;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
    gzip_disable "msie6";

    # Proxy Settings
    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_connect_timeout      90;
    proxy_send_timeout         90;
    proxy_read_timeout         90;

    include /usr/local/web/nginx/conf.d/*.conf;
}

アプリケーションごとのバーチャルホスト設定(conf.d/app.conf)では、PHP-FPMへの転送設定や静的リソースのキャッシュ制御を行います。

upstream backend_php {
    server unix:/var/run/php-fpm.sock;
}

server {
    listen       8080;
    server_name  example.com;
    root   /var/www/html/public;
    index  index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass   backend_php;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }

    location ~* \.(jpg|jpeg|gif|png|css|js|ico|xml)$ {
        expires       30d;
        access_log    off;
    }
}

PHP環境の構築とチューニング

PHPおよびPHP-FPMのインストール後、パフォーマンスと安定性を確保するために設定ファイルを調整します。ソースコードからビルドする場合のconfigure例は以下の通りです。

# ./configure \
  --prefix=/usr/local/php \
  --enable-fpm \
  --with-fpm-user=webuser \
  --with-fpm-group=webuser \
  --enable-mysqlnd \
  --with-pdo-mysql=mysqlnd \
  --with-openssl \
  --with-zlib \
  --with-curl \
  --enable-mbstring \
  --enable-gd \
  --enable-sockets

PHP-FPMのプール設定(www.conf)では、サーバーリソースに合わせてプロセス管理方式を設定します。動的管理(dynamic)の場合、アイドル時の最小プロセス数と最大負荷時のプロセス数を定義します。

[www]
user = webuser
group = webuser
listen = /var/run/php-fpm.sock
listen.owner = webuser
listen.group = webuser
listen.mode = 0660

pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35

php_admin_value[error_log] = /var/log/php-fpm/error.log
php_admin_flag[log_errors] = on
php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/session

サービスの制御は以下のコマンドで行います。

# 起動
/usr/local/php/sbin/php-fpm

# 停止 (シグナル送信)
kill -INT `cat /var/run/php-fpm.pid`

# 再起動 (設定再読み込み)
kill -USR2 `cat /var/run/php-fpm.pid`

ログ管理とローテーション

アプリケーションログがディスク容量を圧迫しないよう、logrotateを設定します。以下はNginxとアプリケーションログのローテーション設定例です。

/usr/local/web/nginx/logs/*.log {
    daily
    rotate 30
    missingok
    notifempty
    compress
    delaycompress
    sharedscripts
    postrotate
        /bin/kill -USR1 `cat /usr/local/web/nginx/logs/nginx.pid 2>/dev/null` 2>/dev/null || true
    endscript
}

/var/log/app/*.log {
    daily
    rotate 14
    copytruncate
    compress
    missingok
    notifempty
}

共有ストレージの構成 (NFS)

複数のWebサーバー間で静的リソースやアップロードファイルを共有するため、NFSサーバーを構築します。エクスポート設定(/etc/exports)では、特定のネットワークセグメントに対して読み書き権限を付与します。

/data/shared/assets  192.168.1.0/24(rw,sync,no_root_squash,no_subtree_check)
/data/uploads       192.168.1.0/24(rw,sync,no_root_squash,no_subtree_check)

クライアント側では、mountコマンドまたは/etc/fstabを用いて自動マウントを設定します。

# 手動マウント
mount -t nfs 192.168.1.10:/data/shared/assets /var/www/html/public/assets

# 自動マウント設定 (/etc/fstab)
192.168.1.10:/data/shared/assets /var/www/html/public/assets nfs defaults 0 0

Node.jsアプリケーションの実行

Node.jsのバイナリを展開し、パスを通します。本番環境では永続化ツールやnohupを用いてバックグラウンドでプロセスを実行します。

# 環境設定
wget https://nodejs.org/dist/v16.x/node-v16.x-linux-x64.tar.gz
tar -xzf node-v16.x-linux-x64.tar.gz -C /usr/local/
ln -s /usr/local/node-v16.x-linux-x64/bin/node /usr/bin/node
ln -s /usr/local/node-v16.x-linux-x64/bin/npm /usr/bin/npm

# アプリケーションの起動
cd /opt/webapp/frontend
npm install --production
nohup npm run start > /var/log/nodejs/app.log 2>&1 &

# プロセス停止
ps -ef | grep node
kill -9 [PID]

Javaバックエンドサービスの実行

Javaアプリケーション(Spring Bootなど)をJARファイルとして実行します。ヒープサイズやGCアルゴリズムを適切に設定し、メモリリークを防ぐ監視を行います。

# 環境変数設定 (/etc/profile.d/java.sh)
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk
export PATH=$PATH:$JAVA_HOME/bin

# サービス起動コマンド
nohup java -server \
  -Xms1024m -Xmx1024m \
  -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m \
  -XX:+UseG1GC \
  -jar /opt/webapp/api-service.jar \
  --spring.profiles.active=prod \
  > /dev/null 2>&1 &

ディレクトリ構成と配置

本番環境における主要なファイルとディレクトリの配置場所は以下の通りです。

区分 パス 説明
Web Root /var/www/html/public ドキュメントルート
Nginx Config /usr/local/web/nginx/conf/ Nginx設定ファイル
PHP Logs /var/log/php-fpm/ PHP-FPMエラーログ
App Logs /var/log/app/ アプリケーションログ
Shared Data /data/shared/ NFSマウントポイント
Java Apps /opt/webapp/ JavaバックエンドJAR配置先

タグ: nginx php-fpm Java Node.js NFS

7月19日 02:48 投稿