docker containerを使ったAPI系のサーバのdeployをする際にSO_REUSEPORTが使えるか調べた。
結論
しんどそう。(できないとは言ってない)
- http(s)に限って言えばできないことはなさそう
- そもそもcontainerの話なんだけど、epmdとかそういうのケアしなくっていいんだっけ問題もありそう。
メモ
- phoenixが使っているHTTP serverはcowboy
- sslはrevese proxyに任せるとして80番のsocket listenerはranch
-
:ranch.connect
は:gen_tcp.connect
なのでgen_tcpのoptionsみる - reuseportはなさそうだけどrawってのがある
- https://github.com/erlang/otp/blob/master/lib/kernel/src/gen_tcp.erl#L85-L89
-
{:raw, 1, 15, <<1, 0, 0, 0>>}
とかつけたらいい?
- どこに渡せばいいか
- https://github.com/phoenixframework/phoenix/blob/v1.2/lib/phoenix/endpoint/server.ex#L17
- https://github.com/phoenixframework/phoenix/blob/master/lib/phoenix/endpoint/cowboy_handler.ex#L81
- https://github.com/elixir-lang/plug/blob/master/lib/plug/adapters/cowboy.ex#L136-L143
- https://github.com/ninenines/ranch/blob/master/src/ranch.erl#L104-L109
- https://github.com/ninenines/ranch/blob/master/src/ranch_listener_sup.erl#L30-L42
- ranch_conns_sup と ranch_acceptors_supをsupervise
- この時点でTransOptsがranch_acceptors_supに渡るのみ
- https://github.com/ninenines/ranch/blob/master/src/ranch_acceptors_sup.erl#L35
- ついにlisten!!!
- https://github.com/ninenines/ranch/blob/master/src/ranch_tcp.erl#L86-L87
- というわけで、configのMyApp.Endpointに書いておけばうけとってもらえそう?
config :my_app, MyApp.Endpoint, [
http: [
{:port, 4000},
{:raw, 1, 15, <<1, 0, 0, 0>>}
]
]
- Keyword.deleteが呼ばれたタイミングで無事死亡
- とりあえず動作確認だけしたかったので、ranch_tcpにダイレクトに渡してみる
- https://github.com/ninenines/ranch/blob/master/src/ranch_tcp.erl#L87
- 実はmacで実験してるので
{:raw, 16#ffff, 16#0200, <<1, 0, 0, 0>>
で試してる...
--- [binary, {active, false}, {packet, raw}, {reuseaddr, true}])).
+++ [binary, {active, false}, {packet, raw}, {reuseaddr, true}, {:raw, 1, 15, <<1, 0, 0, 0>>}])).
- これで同じportを使ってphoenixを多重起動しても
eaddrinuse
で怒られることはなかった。