Edited at

調べなきゃ寝れない!と調べたら余計に寝れなくなったソケットの話

More than 5 years have passed since last update.


課題

最近良く名前を聞くようになったソケット通信が速度が早くて良い的な話をしてたものの、ソケットってそんなに最近出てきたようなことだっけか?と曖昧になったので調べなきゃ寝れない!ということで調べてみた


プロトコルの種類

通信といえばTCP/UDPだろうと再度確認

プロトコル
概要
備考

TCP/IP
信頼性が高い
データグラム(電文)が届いたかどうかを誤りチェックしていて、届いていない場合は再送要求をする。
到着順序が保証されていて、到着したデータは並べ替えられる。
それらが失敗した場合はエラーになるようになっている

UDP/IP
基本的な通信
データグラム(電文)は一方的に送信され、相手に届いたかどうかのチェック等はしない。
エラーの検知はしない。変な受信データもただ破棄されるのみのため、その分単純で高速。

ただ、ソケットの話はここでは出てこない


ソケットはどこの話か?

ソケットのタイプ

osi.png

OSI参照モデルではセッション層部分。TCP/UDPより上のレイヤーだった。


あれ?ソケットって普通の通信じゃね?

ソケットにも種類があるのか調べてみた。

ソケット
概要
特定方法
通信箇所

INETドメイン
ネットワーク上でマシンを越えてのプロセス間通信
IPアドレス+ポート番号
他マシンと通信可

UNIXドメイン
同じマシン上で動いているプロセスが通信を行うためのソケット。
アドレス・名前空間としてファイルシステムを使用している。
ファイルシステム内のinodeとしてプロセスから参照される。
ファイル名で一致
自マシンのみ

なるほど、最近ソケット通信、ソケット通信と言ってるのはUNIXドメインソケットの事か!


UNIXドメインソケットって何がいいの?

Performance Analysis of Various Mechanisms for Inter-process Communicationに素晴らしい検証があった。


It was hypothesized that pipes would have the highest throughtput due to its limited functionality, since it is half-duplex, but this was not true. For almost all of the data sizes transferred, Unix domain sockets performed better than both TCP sockets and pipes, as can be seen in Figure 1 below.

On some machines, Unix domain sockets reached transfer rates as high as 1500 MB/s.


osnet_cs_binghamton_edu_publications_TR-20070820_pdf-2.png

UNIXドメインソケットは、TCPソケット(INETドメインソケット)よりも遥かにスループットが優れてるらしい。Solaris(UltraSPARC processor)ではアーキテクチャの違いからUNIXドメインソケットのほうが遅いらしい。

よし、これで寝れる

Redis コア開発者 @pnoordhuis のツイート


TIL that "an abstract socket address is distinguished by the fact that sun_path[0] is a null byte ('\0')". Anybody knows why this exists?


えーと、抽象名前空間ソケット??まだ、UNIXドメインソケットにも種類があるのか?


UNIXドメインソケットの種類

unix - sockets for local interprocess communication

種類
概要

ファイルシステムパス名(pathname)
きっと一番知られている一般的な手法。bind(2)を使用して、NULL終端(\0)されたファイルシステム上のパスに結びつけることができる。ファイルを使用しているため、パーミッションを調整する必要がある。サーバプロセスが終了するときには、unlink(2)で名前を削除し、場合によってはそれが参照しているファイルも削除するのがお作法。

無名(unnamed)

bind(2)を使ってパス名に結び付けることができないストリーム型のソケットは名前を持たない。socketpair(2)を使うと、名前のついていない CONNECTED なソケットのペアが生成される。fork してファイルディスクリプターを繋ぎ直してあげれば、pipe で実現するのと同じような双方向のプロセス間通信ができる。

抽象名前空間(abstract)
sun_pathにファイルシステムのパスではなく、NULLバイト(\0)であることで区別される。NULLバイト以降に名前(文字列)を渡すが、ファイルパス名とは関係ない。ファイルシステムと紐付いていないので、 ファイルシステムのパーミッションなどに関係なくソケット通信できてしまう。Linuxでのみ利用可能。unlink(2)で終了する必要がない。


どのUNIXドメインかを見極めるには

$netstat -al --protocol=unix で確認する


ファイルシステムパス名

I-Node path部分にファイルパス名が表示されている

Active UNIX domain sockets (only servers)

Proto RefCnt Flags Type State I-Node Path
unix 2 [ ACC ] STREAM LISTENING 154823 /var/lib/mysql/mysql.sock


無名

I-Nodeは割り振られるが、pathは表示されない

Active UNIX domain sockets (only servers)

Proto RefCnt Flags Type State I-Node Path
unix 3 [ ] STREAM CONNECTED 175322


抽象名前空間

I-Node path部分に@がついた名前が表示される

Active UNIX domain sockets (only servers)

Proto RefCnt Flags Type State I-Node Path
unix 2 [ ACC ] STREAM LISTENING 6653 @/com/ubuntu/upstart


UNIXドメインソケットをサポートしているサービス

ミドルウェア
概要
種類
使用方法
連携ミドルウェア

Nginx
web server
pathname
server divective
unicorn, gunicorn, php-fpm, etc...

Unicorn
ap server
pathname
Public Instance Methods

Mysql
db server
pathname

Redis
KVS
pathname
How fast is Redis?

Memcached
KVS
pathname
Using memcached

upstart
deamon
abstract

sytemd
deamon
abstract

OS?
kernelプロセス?
unnamed


まとめ

ソケット通信は今度からUNIXドメインソケット通信と言うこと(どのマニュアルにもちゃんと書いてあったけど笑)。TCPで接続することばっかりやってきたので、気にもしてなかったがKVSとかの接続はUNIXドメインソケット通信にしたらもう少し効率よく使えるのではないかと。まだまだ、調べたらいろいろありそうなので継続調査。

もう寝ます笑