Nginxでunix domain socketを使う

Alblenetでnginxを使っていたときは、lxcコンテナだったのでreverse proxyでローカルIPをlxcホストに飛ばしていましたが、A2ホスティングに移したとき、OpenVZだったのでコンテナが作れません。それでポートを使ってreverse proxyで飛ばしていましたが、httpポートが増えて煩雑になることとMySQLではローカルの場合ソケットを使っていてIPポートを使うより高速に動作するので、nginxでもソケットで飛ばせるのではないかと考えて、検索して調べてみました。私が思いつく段階ですでに頭のいい人たちがやっていることがほとんどなので、今回も例にもれず実例が見つかりました。upstreamを使う場合と、proxy_passに指定する方法の2通りありました。

Upstreamの場合

upstream backend {
    server unix:/var/run/mail.sock;
}

...

server {
    listen        443 ssl;
    server_name   mx.hottuna.tk;
...
   proxy_pass http://backend;

Proxy_passの場合

server {
    listen        443 ssl;
    server_name   mx.hottuna.tk;
...
   proxy_pass http://unix:/var/run/mail.sock;

バックエンドサーバ例

server {
    #listen         83;
    listen         unix:/var/run/mail.sock;
    server_name    mx.hottuna.tk;
...

ディストリビューションによって違いがあるのかもしれませんが、debianだと正常にサーバをシャットダウンできません。ソケットが残っていて再度立ち上げるときに次のようなエラーを吐きます。


Sep 30 12:51:32 hottuna nginx[4658]: nginx: [emerg] bind() to unix:/var/run/mail.sock failed (98: Address already in use)
Sep 30 12:51:32 hottuna nginx[4658]: nginx: [emerg] bind() to unix:/var/run/mail.sock failed (98: Address already in use)
Sep 30 12:51:33 hottuna nginx[4658]: nginx: [emerg] bind() to unix:/var/run/mail.sock failed (98: Address already in use)
Sep 30 12:51:33 hottuna nginx[4658]: nginx: [emerg] bind() to unix:/var/run/mail.sock failed (98: Address already in use)
Sep 30 12:51:34 hottuna nginx[4658]: nginx: [emerg] bind() to unix:/var/run/mail.sock failed (98: Address already in use)

これも検索すると解決方法があり、サーバを止めるときにTERMシグナルを使うことです。具体的には次のようにします。

/lib/systemd/system/nginx.service


#ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
ExecStop=-/sbin/start-stop-daemon --quiet --stop --signal TERM --pidfile /run/nginx.pid

ファイルを変更したらsystemdのコマンドを実行します。

systemctl daemon-reload

これでnginxでドメインソケットが使えるようになりました。

問題点

設定したあとに気がついたのですが、unix domain socketのバッファーは小さいので、転送量がある時点で限界に達するということです。詳しくは他のサイトで詳細があるのでそちらを参照してください。