4

我对 erlang/otp 世界还很陌生,所以我想这是一个非常基本的问题。不过,我想知道执行以下操作的正确方法是什么。

目前,我有一个高级主管的申请。后者将监督调用 gen_tcp:accept 的工作人员(睡在上面),然后为每个接受的连接生成一个进程。注意:对于这个问题,listen() 在哪里完成是无关紧要的。

我的问题是关于使这些工作人员(在 gen_tcp:accept 上睡觉的工作人员)尊重 otp 设计原则的正确方法,以便他们可以处理系统消息(处理关闭、跟踪等),根据什么我在这里读过:http ://www.erlang.org/doc/design_principles/spec_proc.html

所以,

  • 是否可以为此使用 gen_fsm 或 gen_server 等可用行为之一?我的猜测是否定的,因为阻塞调用 gen_tcp:accept/1。是否仍然可以通过指定接受超时来做到这一点?如果是这样,我应该把 accept() 调用放在哪里?
  • 或者我应该像上面链接中的示例一样从头开始编码(即:不使用现有行为)?在这种情况下,我想到了一个调用 gen_tcp:accept/2 而不是 gen_tcp:accept/1 的主循环(即:指定超时),然后立即编写一个接收块,这样我就可以处理系统消息。这是正确的/可以接受的吗?

提前致谢 :)

4

3 回答 3

1

由于 Erlang 是事件驱动的,因此处理像 accept/{1,2} 那样阻塞的代码是很尴尬的。

就个人而言,我会有一个主管,它有一个gen_server听众,另一个主管接受工人。Handroll an accept worker to timeout ( gen_tcp:accept/2),有效地轮询,(尴尬的部分)而不是接收状态消息。

这样,如果一个工人死亡,它会被它上面的主管重新启动。如果侦听器死了,它会重新启动,但不会在重新启动依赖于该侦听器的工作树和主管之前。当然,如果最高主管死了,它会重新启动。但是,如果您supervisor:terminate_child/2在树上,那么您可以有效地禁用该套接字的侦听器和所有接受器。稍后,supervisor:restart_child/2可以重新启动整个 listener+acceptor 工作池。

如果你想要一个应用程序来为你管理这个,cowboy实现了上面的。尽管是面向 http 的,但它很容易支持自定义处理程序来代替要使用的任何协议。

于 2012-05-18T20:10:50.687 回答
1

我实际上在另一个问题中找到了答案:使用 OTP 原则的非阻塞 TCP 服务器和这里http://20bits.com/article/erlang-a-generalized-tcp-server

编辑:对我有帮助的具体答案是:https ://stackoverflow.com/a/6513913/727142

于 2012-05-19T15:40:57.850 回答
0

您可以将其设置为类似于此的 gen_server:https ://github.com/alinpopa/qerl/blob/master/src/qerl_conn_listener.erl 。

如您所见,此进程正在执行 tcp 接受并处理其他消息(例如 stop(Pid) -> gen_server:cast(Pid,{close})。)

HTH,阿林

于 2012-05-17T19:51:06.763 回答