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

时间:2016-01-27 16:52:58

标签: elixir 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)的最后一行,还是可以最后执行<namespaces> <add namespace="System.Web.Mvc" /> <add namespace="System.Web.Mvc.Ajax" /> <add namespace="System.Web.Mvc.Html" /> <add namespace="System.Web.Routing" /> </namespaces>

有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

我过去使用的一种技术是将数据发送到另一个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