【问题标题】:Erlang OTP supervisor gen_tcp - {error,eaddrinuse}Erlang OTP 主管 gen_tcp - {error,eaddrinuse}
【发布时间】:2014-07-10 06:39:19
【问题描述】:

我看不到将主管添加到崩溃的 gen_tcp:listen-thread 会如何实际上重新启动该工作程序。由于崩溃会使我想听的端口暂时无用。当发生崩溃并且我尝试手动重新启动我的应用程序时,我收到“{error,eaddrinuse}”。我还没有为这个工人实施任何主管,因为我看不到它是如何工作的。

如何重新启动 gen_tcp:listen?

【问题讨论】:

  • 有时看起来即使套接字已关闭,端口仍在使用一段时间。不知道为什么。
  • @rvirding - 显然是在套接字上有挂起连接的情况下。如果没有挂起的连接,它应该立即进入 CLOSED 状态。 Alexander - 请参阅 Paul 关于使用 reuseaddr 的回答,即使我的回答有帮助,应该用于您的服务器。

标签: erlang restart erlang-otp erlang-supervisor gen-tcp


【解决方案1】:

管理 gen_tcp 套接字的进程是 gen_server 吗?如果是这样,它会让您的生活更轻松。

如果是 gen_server,请将 process_flag(trap_exit, true) 添加到您的 init 函数中。这使得当您的进程“崩溃”时,它会在实际退出进程之前调用terminate/2 回调函数。使用此方法,您可以在终止函数中手动关闭您的侦听套接字,从而避免烦人的端口清理延迟。

如果您不使用 gen_server,同样的原则仍然适用,但您必须更加明确地捕捉错误。

【讨论】:

  • 或者,您也可以在与“接受者”不同的进程中启动侦听套接字。除了充当套接字的存储之外,所述进程应该什么都不做,从而确保它永远不会崩溃。这是因为可以从多个进程同时调用gen_tcp:accept
  • 感谢您的快速回复!我将尝试添加一个陷阱,因为我正在运行 gen_server (应该提到这一点)。关于拆分接受/侦听 - 如果我的应用程序崩溃,这实际上就足够了吗?
  • 如果整个应用程序崩溃,那么即使您将责任分开,您也会遇到同样的问题。但是,通过仅在您真正需要的地方指定 trap_exit 并允许您的客户端进程在适当的时候正常崩溃,您仍然会从中受益。另外,一定要看看牧场(github.com/extend/ranch),它可以为你处理很多这样的事情。
【解决方案2】:

在大多数情况下,由于侦听套接字链接到控制进程(创建它的进程),该进程的终止将很好地关闭套接字并允许您在同一端口上再次侦听。

对于所有其他情况,您应该将{reuseaddr, true} 选项传递给gen_tcp:listen/2。实际上,您的应用程序的侦听套接字在崩溃后会短暂保持活动状态,并且此选项允许您在此期间重用地址。

【讨论】:

  • reuseaddr 的目的与您建议的目的不同。它可能确实可以用于此目的,但如果使用不当也可能产生令人讨厌的副作用。
  • reuseaddr 正是阻止 OP 的原因,并且是不可捕获的崩溃所必需的。牧场也使用此选项。
  • reuseaddr 的目的是允许服务器重新使用已经使用的端口,是的,但是有更好的方法来解决这个特定问题,即正确清理监听套接字终止,牧场会这样做。更好地使用reuseaddr 用于管理数千个短期客户端的大容量服务器。
  • 其实,我相信大多数情况下都会进行适当的清理,而不会捕获出口,并且OP确实需要reuseaddr。我不相信牧场陷阱退出来对监听套接字进行适当的清理。
  • 对,你是牧场不使用它(仔细检查来源)。话虽如此,只要没有挂起的连接,正确的清理确实可以防止“已使用”问题,因此在这种情况下帮助他。就我而言,我将reuseaddr 选项与同名的系统级TCP 选项混为一谈,它全局 允许重用TIME_WAIT-ing 端口并可能产生问题。作为侦听的一个选项,它被广泛用于重新建立异常关闭套接字(例如崩溃)的侦听服务器。
猜你喜欢
  • 2019-02-22
  • 2011-08-12
  • 2012-04-02
  • 2012-09-21
  • 1970-01-01
  • 2013-05-06
  • 2013-11-01
  • 2014-12-21
  • 2014-12-24
相关资源
最近更新 更多