【问题标题】:Use SO_REUSEPORT with Phoenix将 SO_REUSEPORT 与 Phoenix 一起使用
【发布时间】:2019-07-09 20:44:32
【问题描述】:

我对不使用 Elixir/Erlang 热升级的零停机部署系统感兴趣(由于代码运行时数据迁移的复杂性)。

我听说在将服务器绑定到适配器时可以使用 SO_REUSEPORT 选项,这样我就可以运行绑定到相同地址和端口的同一应用程序的两个实例。我的意图是将版本 2 与正在运行的版本 1 部署在同一台服务器上,启动版本 2,然后正常停止版本 1,这应该允许传入连接自然地开始专门连接到版本 2。

无论这是否完全按照我的计划工作 - 我的目的是测试此配置,知道它在不同操作系统上的行为不同 - 我想知道配置 Phoenix 执行此操作所需的具体步骤,因为这似乎是:gen_tcp 中的低级配置。

如果有办法配置操作系统或 Erlang VM 以在默认启用此选项的情况下建立所有连接,那就更好了。

【问题讨论】:

  • 在 Erlang/OTP 源代码中没有提到 SO_REUSEPORT,所以我相信即使现在使用原始 :gen_tcp 也是不可能的(除了在 NIF 中滚动你自己的包装器)。
  • 也许选项是 S_REUSEADDR 而不是 SO_REUSEPORT。无论如何,我见过有人亲自做某事,效果与我上面描述的完全相同,无论是使用一个标志还是另一个标志,但在 Mac 上。他能够启动两个 Elixir 进程,第二个进程改变了输出,当第一个进程终止时,输出立即切换到第二个进程的输出,没有停机时间。我知道这是可能的,我只是不知道怎么做,如果它只在 Mac 上是可能的,我认为在 Linux 上应该也是如此,如果不是我所要求的。
  • 他是在用 Phoenix 还是用 raw gen_tcp 或其他什么东西? (gen_tcp 至少有一个reuseaddr。)
  • @Dogbert IIRC 这是一个新的 Phoenix 应用程序,尽管他是否编辑了 Phoenix 应用程序代码/配置或以不同的方式启动该应用程序,我不记得了。

标签: network-programming erlang elixir phoenix-framework


【解决方案1】:

您应该以{:raw, protocol, option_num, value_bin} 格式为套接字指定原始 SO_REUSEPORT 标志 gen_tcp option/raw 并将其传递给底层传输。

请注意,mac/linux 的标志是不同的。在您的 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]]]

在 Phoenix 1.4.9 上测试过,但我想旧版本也应该没问题。 以下是已使用选项的相应文档。

【讨论】:

    猜你喜欢
    • 2015-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多