SO_REUSEPORT ソケットオプション
Linux Kernel3.9(BSDでは割と以前から実装されていたけど)で取り込まれたSO_REUSEPORT
ソケットオプションは、異なるプロセスで同一のポートにbindできるようになるので、いろいろおもしろいことができそう。
https://lwn.net/Articles/542629/
これがmerge commit
試しにRubyでSO_REUSEPORT
を使うサーバを書いてみた。
もちろんKernelを3.9以降にアップデートしないと動かない。
Ubuntuだと、script書いてくれてる人がいるので楽にUbuntu Kernelをアップデートできる。
http://dl.dropboxusercontent.com/u/47950494/upubuntu/kernel-3.10.9
require 'socket' SO_REUSEPORT = 15 s = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0) s.setsockopt(Socket::SOL_SOCKET, SO_REUSEPORT, 1) s.bind(Addrinfo.tcp("127.0.0.1", 10080)) s.listen(5) while true do conn, addr = s.accept puts "Connected to #{Process.pid}" data = conn.recv(1024) conn.send("HTTP/1.1 200 OK", 0) conn.close end
で、これを10プロセスほど起動して、apache benchでつないでみる。
$ for i in `seq 10` do ruby so_reuseport_opt.rb & done $ ab -n 10000 -c 10 localhost:10080/ This is ApacheBench, Version 2.3 <$Revision: 1430300 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking localhost (be patient)...Connected to 3476 Connected to 3334 Connected to 4875 Connected to 3531 Connected to 3531 Connected to 4879 Connected to 4869 Connected to 2891 Connected to 4870 Connected to 4868 Connected to 4866 ...
カーネル側でバランシングしてくれていることがわかる。 使いどころとして、
- 単純なpreforkモデルでパフォーマンスを出したいアプリケーション
- システム管理系のアプリケーションで、プロセスを落とせないけど、新しいversionを使いたくて、同時に新しいものも起動させてから、古いversionのプロセスを落とす(hotswapしたい)
などが作れそう。