I am interested in a zero-downtime deployment system that does not use Elixir/Erlang hot upgrades (due to the complexity of data migrations while the code is running).
I have heard that I may be able to use the SO_REUSEPORT option when binding the server to the adapter, such that I can run two instances of the same application bound to the the same address and port. My intent is to deploy version 2 on the same server as a running version 1, start version 2, and then gracefully stop version 1, which should allow incoming connections to naturally begin connecting exclusively to version 2.
Regardless of whether this works exactly as I plan - my intent is to test this configuration knowing that it behaves differently on different OSes - I would like to know the specific steps necessary to configure Phoenix to do this, as this seems to be a lower-level configuration within :gen_tcp
.
If, alternatively, there is a way to configure the OS or Erlang VM to make all connections with this option enabled by default, that would be even better.
You should specify raw SO_REUSEPORT flag for a socket in the format {:raw, protocol, option_num, value_bin}
gen_tcp option/raw and pass it to the underlying transport.
Please note, that flags are different for mac/linux. In your config.exs:
so_reuseport =
case :os.type() do
{:unix, :linux} -> {:raw, 1, 15, <<1::32-native>>}
{:unix, :darwin} -> {:raw, 0xffff, 0x0200, <<1::32-native>>}
end
config :yourapp, YourApp.Endpoint,
http: [port: {:system, "PORT"}, transport_options: [socket_opts: [so_reuseport]]]
Tested on Phoenix 1.4.9, but I guess older versions should be ok too. Here are the corresponding docs for used options.
http
Phoenix.Endpoint — Phoenix
v1.4.9
transport_options
Plug.Cowboy — PlugCowboy
v2.1.0
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With