使用 GenServer 处理负载下的数据 (gen_server)

Processing data under load with GenServer (gen_server)

我正在 GenServer 中测试以下模式:

  def handle_info({:tcp, _, data}, s) do
    # IO.puts "\nrx: \n#{Base.encode16(data)}\n"

    extra = _proc_data(<<s.extra::binary, data::binary>>)

    :inet.setopts(s.socket, active: :once)

    {:noreply, %{s | extra: extra}}
  end

数据来得快时出现问题,无法在:inet.setopts(s.socket, active: :once)发布新数据前更新状态

必须 {:noreply, %{s | extra: extra}}handle_info 的最后一行,或者我可以最后执行 :inet.setopts(s.socket, active: :once) 吗?

有更好的方法吗?

我过去使用的一种技术是将数据发送到另一个 GenServer 进行处理。这将允许当前进程更快地调用 :inet.setopts(s.socket, active: :once)

def handle_info({:tcp, _, data}, s) do
    # IO.puts "\nrx: \n#{Base.encode16(data)}\n"

    GenServer.cast(s.processor, {:data, data})

    :inet.setopts(s.socket, active: :once)

    {:noreply, s}
end

处理器:

defmodule DataProcessor do
  use GenServer

  def start_link(opts), do: GenServer.start_link(__MODULE__, [], opts)

  def init(_), do: {:ok, %{}}

  def handle_cast({:data, data}, state) do
    extra = _proc_data(s.extra <> data)    
    {:noreply, %{state| extra: extra}}
  end

  defp _proc_data(data) do
    ...
  end
end