[unicorn]socket通信で高速化

TIPS

前回のブログで予告した、一歩進んだ本番環境向けの最適化テクニック「UNIXソケット通信への切り替え」をステップ・バイ・ステップで解説します。

これまで構築した環境では、NginxからGunicornへの転送に http://127.0.0.1:8000 という「ネットワーク(TCPポート)」を経由していました。これを .sock という特殊なファイル(UNIXドメインソケット) を介した通信に切り替えることで、サーバー内部の不要なネットワーク処理をバイパスし、通信の高速化とセキュリティの向上(外部からのポートアクセスの遮断) を同時に実現できます。

一見難しそうに見えますが、変更するポイントは「Gunicornの起動コマンド」と「Nginxの設定ファイル」の2箇所だけです。それでは順を追って設定していきましょう!

ステップ1:Gunicornの起動コマンドを変更する

まずは、Gunicornに「ポートを開くのではなく、ソケットファイルを作ってそこでリクエストを待って」と指示を出します。

前回のコマンドは以下の通りでした。

gunicorn --bind 127.0.0.1:8000 app:app -D

これを、以下のように変更します。

gunicorn --bind unix:app.sock app:app -m 007 -D

💡 ここがポイント!

  • unix:app.sock127.0.0.1:8000 の代わりに指定します。コマンドを実行したディレクトリ(例: /home/ubuntu/my_python_app)の直下に app.sock というファイルが自動生成されます。
  • -m 007(または --umask 007)新しく作られる .sock ファイルのアクセス権限(パーミッション)を調整する非常に重要なオプションです。これをつけることで、この後設定するNginxがこのソケットファイルを読み書きできるようになります(これがないと「502 Bad Gateway」のエラー原因になります)。

ステップ2:Nginxの設定ファイルを変更する

次に、Nginx側の「転送先」をネットワークポートから、先ほど指定した .sock ファイルの絶対パスへ書き換えます。

Nginxの設定ファイル(例: /etc/nginx/sites-available/default)を開き、location / の中の proxy_pass を以下のように修正します。

server {
    listen 80;
    server_name your_domain_or_IP;

    location / {
        # 元の設定: proxy_pass http://127.0.0.1:8000;
        
        # UNIXソケットへの転送設定(必ず「絶対パス」でソケットファイルを指定)
        proxy_pass http://unix:/home/ubuntu/my_python_app/app.sock;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

※ /home/ubuntu/my_python_app/app.sock の部分は、ご自身の環境のアプリが置いてある絶対パスに書き換えてください。

書き換えたら、保存して閉じます。

ステップ3:【最重要】パーミッションの壁をクリアする

UNIXソケット通信へ切り替える際、最も多くの人が嵌まる罠が「Nginxがソケットファイルにアクセスできない問題」です。

Linuxでは、Nginxは通常 www-data という専用のユーザー(およびグループ)で実行されています。そのため、ソケットファイルが置いてあるディレクトリ自体(今回の例では my_python_app やその親ディレクトリ)に対して、Nginxがアクセスできる権限を持っている必要があります。

手っ取り早く安全に解決するために、Nginxの実行ユーザー(www-data)を、あなたのユーザーグループ(例: ubuntu)に追加してあげましょう。

# Nginxユーザーを、現在のログインユーザー(例: ubuntu)のグループに追加
sudo usermod -aG $USER www-data

※このコマンドを実行した後は、設定を反映させるために一度Nginx(またはサーバー自体)を再起動する必要があります。

ステップ4:設定を反映して動作確認

すべての準備が整いました。古いGunicornプロセスを一度終了させ、新しい設定で両者を立ち上げ直します。

1. 古いGunicornを停止して再起動

# 稼働中のGunicornを一度すべて終了
pkill gunicorn

# 仮想環境に入っていることを確認し、UNIXソケットモードで起動
source venv/bin/activate
gunicorn --bind unix:app.sock app:app -m 007 -D

起動後、ディレクトリ内に app.sock というファイルが生成されているか ls コマンドなどで確認してください。

2. Nginxの再起動

# 設定ファイルの構文チェック
sudo nginx -t

# エラーがなければNginxを再起動
sudo systemctl restart nginx

3. ブラウザで確認

ドメインまたはIPアドレスにアクセスし、前回同様にFlaskアプリの画面が表示されれば移行完了です!

もし「502 Bad Gateway」と表示されてしまった場合は、/var/log/nginx/error.log のエラーログを確認してください。大半は「Permission denied」と出ており、ステップ3の権限設定(ディレクトリの階層全体の権限、またはGunicorn起動時の -m 007 の付け忘れ)が原因です。

まとめ

ネットワーク経由(TCP)からUNIXソケットへの変更により、サーバーのメモリやCPUのオーバーヘッドが削減され、アクセスが集中した際のパフォーマンスが向上します。

「同じサーバー内でWebサーバーとアプリサーバーを同居させる」という構成であれば、このUNIXソケット通信がもっとも洗練された設定です。

コメント

タイトルとURLをコピーしました