【发布时间】:2016-12-06 00:47:36
【问题描述】:
我通常使用这种模式与单个 TCP 资源进行交互,在active-mode:
def connect(ip, port) do
t = System.system_time(1000)
case :gen_tcp.connect(ip, port, [:binary, active: :once, keepalive: true, nodelay: true]) do
{:ok, socket} ->
log "Connected to #{ip}:#{port} in #{System.system_time(1000) - t}ms"
socket
{:error, err} ->
log "Connect Error - #{ip}: #{port} [#{inspect err}]"
Process.send_after(self(), :retry_connect, 3000)
nil
end
end
def handle_info({:tcp, _, data}, s) do
s = proc_raw(s.extra <> data, %{s | extra: ""})
:inet.setopts(s.socket, active: :once)
{:noreply, s}
end
如何扩展它以处理同一GenServer 中的多个 TCP 连接?
到目前为止,这对于active-mode 中的单个 TCP 套接字非常有效
更新
每个 GenServer 都由主管管理。另外,每个 GenServer 代表一个客户端,每个客户端可能有 3-5 个 TCP 连接到一些外部资源。
TCP 连接会不时发生故障/重置,每次失败都会尝试重新连接,但主机 GenServer 不需要重新启动
【问题讨论】:
-
为什么不希望每个连接一个进程?隔离连接是有意义的,因为单个连接可能会关闭,并且不应影响其他连接。
-
每个 GenServer 用于单个客户端实例。每个客户端实例最多管理 5 个到相同 TCP 资源的 tcp 连接
-
@MartinSvalin 关闭或失败的 TCP 连接将被管理并重新启动,它不应使进程崩溃,因为这是预期的行为
-
我还是会使用监督树。我不是每个客户端一个 GenServer,而是每个客户端一个主管,每个 tcp 连接一个 GenServer。我认为以这种方式进行故障处理会更容易推理。
-
@MartinSvalin 嗯,我会考虑的