UNIXドメインソケット
UNIXドメインソケットってなに?
ソケットの1つ
ネット通信で使うソケットの一種。UNIXドメインソケット以外には TCP/IPとかがある
他のソケットと比べたメリット
サーバー内に閉じた通信を高速に行える
開いたプロセスが死ぬと消える
TCPなどのポート番号を占有しない
ファイルパス上にエントリポイントを持てるので、ディレクトリごとに作れる
新アプリに切り替えるときに、新しUNIXドメインソケットのエントリポイントを作っておいて、呼び出し元(Nginx等)で切り替えるとダウンタイム無しで切り替えられる、とか。
UNIXドメインソケットの作り方
Pythonコードの場合:
code:server.py
import socket
s = socket.socket(socket.AF_UNIX)
s.bind('/tmp/test.sock')
s.listen(1)
conn, addr = s.accept() # client.pyからの接続待ち(接続されたら関数から戻る)
message = conn.recv(255) # client.pyから送られた文字列を受け取る(受け取ったら関数から戻る)
print(message)
code:client.py
import socket
s = socket.socket(socket.AF_UNIX)
s.connect('/tmp/test.sock')
s.send(b'hello') # server.pyへメッセージを送信する
code:bash
$ ls -laF /tmp/test.sock
srwxr-xr-x 1 user wheel 0 4 10 16:19 /tmp/test.sock=
$ file /tmp/test.sock
/tmp/test.sock: socket
起動オプションで gunicorn --bind unix:/path/to/file.sock で作られる
UNIXドメインソケットの消し方
プロセスが死ぬと、ソケットは勝手に消える
ソケットを閉じると、エントリポイントは消える
UNIXドメインソケットファイルって何?
サーバー内で通信するためのエントリポイント。実体はファイルではない
UNIXドメインソケットで使うためのファイルは人間がviとかtouchとかで作るものではない
ファイルシステムを観察してみよう
code:shell
$ ls -laF /var/run
...
lrwxr-xr-x 1 user user 72 4 3 01:47 docker.sock@ -> /path/to/docker.sock
...
srw-rw-rw- 1 root daemon 0 4 3 00:54 syslog=
-rw-r--r--@ 1 root daemon 3 4 3 00:54 syslog.pid
...
末尾に = が付いてるファイルがあれば、それがUNIXドメインソケット
逆に、socketとして使おうとしているファイルに = が付いていないなら、それはsocketではないのでうまくいかない
例えば
file /var/run/syslog= と実行すると No such file or directory エラーになる
file /var/run/syslog なら /var/run/syslog: socket
まとめ
= はファイル名の一部ではない
Unixドメインソケットなら、見分けるために = が付く
ちなみに、シンボリックリンクなら @ が付く
ls -laF で表示した結果に = が付いてないなら、それはsocketではなく普通のファイル
普通のファイルがあっても unix domain socketとして使えるわけじゃない
トラブルシューティング
gunicornのUNIXドメインソケットファイルが見つからない!
Ningxから unix:/var/run/gunicorn.sock で指定したら No such file or directoryと出たので、手動で gunicorn.sock を用意してみた
gunicornの起動コマンドはこうなっていた
code:shell
$ gunicorn -b 0.0.0.0:8000 apps.wsgi:application
これだと TCPでのバインドされているため、UNIXドメインソケットファイルは作られない
参考