Erlang OTP 主管 gen_tcp - error,eaddrinuse
Posted
技术标签:
【中文标题】Erlang OTP 主管 gen_tcp - error,eaddrinuse【英文标题】:Erlang OTP supervisor gen_tcp - error,eaddrinuseErlang 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 的回答,即使我的回答有帮助,应该用于您的服务器。 【参考方案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 端口并可能产生问题。作为侦听的一个选项,它被广泛用于重新建立异常关闭套接字(例如崩溃)的侦听服务器。以上是关于Erlang OTP 主管 gen_tcp - error,eaddrinuse的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Erlang/OTP 中将主管的孩子 pid 共享给另一个孩子