10

我要解决的问题:拥有一个侦听特定端口的 Erlang TCP 服务器(代码应驻留在某种面向外部的接口/API 中),并且每个传入连接gen_server都应gen_tcp:accept由) gen_server,但我实际上并不想最初生成预定义数量的接受传入连接的进程)。这有可能吗?

4

4 回答 4

10

基本程序

您应该有一个执行以下过程的静态进程(实现为gen_server自定义进程或自定义进程):

  1. 使用监听传入连接gen_tcp:accept/1
  2. 每次它返回一个连接时,告诉主管产生一个工作进程(例如另一个gen_server进程)
  3. 获取此进程的 pid
  4. gen_tcp:controlling_process/2使用新返回的套接字和该 pid调用
  5. 将套接字发送到该进程

注意:必须按此顺序执行此操作,否则新进程可能会在所有权移交之前使用套接字。如果不这样做,当新进程已经接管时,旧进程可能会收到与套接字相关的消息,从而导致丢弃或错误处理的数据包。

监听过程应该只有一个责任,那就是为新的连接产生工人。这个过程在调用时会阻塞gen_tcp:accept/1,这很好,因为启动的工作人员将同时处理正在进行的连接。接受阻塞可确保启动新连接时的最快响应时间。如果该过程需要在其间做其他事情,gen_tcp:accept/2则可以与在超时之间交错的其他操作一起使用。

缩放

  • 您可以让多个进程gen_tcp:accept/1在单个侦听套接字上等待,从而进一步提高并发性并最大限度地减少接受延迟。

  • 另一个优化是预先启动一些套接字工作程序,以在接受新套接字后进一步减少延迟。

  • proc_lib第三也是最后一点,通过使用(更多信息)在您自己的自定义流程中实施 OTP 设计原则,使您的流程更加轻量级。但是,只有在您进行基准测试并得出结论是这种gen_server行为会减慢您的速度时,您才应该这样做。

于 2011-03-27T10:22:52.147 回答
4

问题gen_tcp:accept在于它会阻塞,因此如果您在 agen_server中调用它,则会阻止服务器接收其他消息。您可以尝试通过超时来避免这种情况,但这最终相当于一种最好避免的轮询形式。相反,您可以尝试使用 Kevin Smith 的 gen_nb_server;它使用内部未记录的函数prim_inet:async_accept和其他prim_inet函数来避免阻塞。

于 2011-03-27T01:06:29.057 回答
3

您可能想查看http://github.com/oscarh/gen_tcpd并使用 handle_connection 函数将您获得的进程转换为 gen_server。

于 2011-03-27T15:27:26.207 回答
2

正如史蒂夫所说,您应该使用“prim_inet:async_accept(Listen_socket,-1)”。现在传入连接将被您的 handle_info 回调接受(假设您的接口也是 gen_server),因为您使用了异步接受调用。

接受连接后,您可以生成另一个 ger_server(我会推荐 gen_fsm),并通过调用“gen_tcp:controlling_process(CliSocket,spwned 进程的 Pid)”将其作为“控制进程”。

在此之后,来自套接字的所有数据都将由该进程而不是您的接口代码接收。就像那样,将为另一个连接产生一个新的控制过程。

于 2011-03-27T04:58:44.060 回答