本文介绍了每秒具有1个HTTP请求的GenServer的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我做了这个genserver

I have made this genserver

defmodule Recorder do
  use GenServer

  def start_link(args) do
    id = Map.get(args, :id)
    GenServer.start_link(__MODULE__, args, name: id)
  end

  def init(state) do
    schedule_fetch_call()
    {:ok, state}
  end

  def handle_info(:jpeg_fetch, state) do
    spawn(fn ->
      IO.inspect("I am being called")
      IO.inspect(DateTime.utc_now())
      Fincher.request(:get, state.url) |> IO.inspect()
    end)
    schedule_fetch_call()
    {:noreply, Map.put(state, :run, true)}
  end

  defp schedule_fetch_call do
    Process.send_after(self(), :jpeg_fetch, 1000)
  end
end

在这样的状态下,我每秒运行1个请求.

I am running it 1 request per second with such a state.

  defp get_children do
    Enum.map([
      %{
        id: :hdipc,
        url: "http://77.66.206.55/jpgmulreq/1/image.jpg?key=1516975535684&lq=1&COUNTER"
      }
    ], fn(camera) ->
      Supervisor.child_spec({Recorder, camera}, id: camera.id)
    end)
  end

application.ex 中.

我在这里使用spawn,但我不想使用spawn,这是解决此问题的最合乎逻辑和最理想的方法.

I am using spawn here but I don't want to use spawn, what is the most logical and ideal way to solve this problem.

  1. GenServer将在其中每秒发出一个请求.

  1. where GenServer will make a request each second.

也不要等待请求完成,因为请求可能需要一秒钟以上的时间.

Also don't wait for the request to complete, as the request can take more than a second.

在HTTP请求响应的情况下,我还需要执行其他一些操作.

There are a few other certain operations I want to do in case of HTTP request-response.

我不想让genserver精疲力尽并崩溃.但要处理每秒将要发生的请求的背压(由于需求不确定,因此不会进入阶段).

I don't want to make genserver exhausted and crash. but to handle the back pressure of requests, which will be going each second (Not genstage as demand is not certain).

是否可以以这样的方式使用 GenServer 来使其不产生和处理请求就可以运行?任何指导或帮助都会很棒.

Is it possible to use GenServer in such a way that it can run without spawn and handle requests? any guidance or help would be wonderful.

推荐答案

对于 DynamicSupervisor .

将工作程序定义为 GenServer 以执行工作.

Define the worker as a GenServer to perform a work.

defmodule Recorder.Worker do
  use GenServer

  def start_link(opts) do
    {id, opts} = Map.pop!(opts, :id)
    GenServer.start_link(__MODULE__, opts, name: id)
  end

  def init(state) do
    schedule_fetch_call()
    {:ok, state}
  end

  def handle_info(:jpeg_fetch, state) do
    result = Fincher.request(:get, state.url)
    schedule_fetch_call()
    {:noreply, Map.put(state, :run, {DateTime.utc_now(), result})}
  end

  defp schedule_fetch_call,
    do: Process.send_after(self(), :jpeg_fetch, 1000)
end

然后将 DynamicSupervisor 定义为

defmodule Recorder.Supervisor do
  use DynamicSupervisor

  def start_link(opts),
    do: DynamicSupervisor.start_link(__MODULE__, opts, name: __MODULE__)

  def start_child(opts),
    do: DynamicSupervisor.start_child(__MODULE__, {Recorder.Worker, opts})

  @impl DynamicSupervisor
  def init(opts),
    do: DynamicSupervisor.init(strategy: :one_for_one, extra_arguments: [opts])
end

现在可以根据需要启动尽可能多的 DynamicSupervisor ,也可以对其进行监督.

Now start as many DynamicSupervisors, also supervised, as you need.

我相信我已经推荐了我的 Tarearbol 库,该库(除其他所有功能外)使用动态工人管理有点像

I believe I have already recommended my Tarearbol library that (besides everything else,) simplifies the above with Dynamic Workers Management to somewhat like

defmodule Recorder.Worker do
  use Tarearbol.DynamicManager

  def children_specs do
    Enum.into([%{id: :hdipc, url: "..."}], %{}, &{&1.id, &1})
  end

  def perform(_id, state) do
    result = Fincher.request(:get, state.url)
    {:noreply, Map.put(state, :run, {DateTime.utc_now(), result})}
  end
end

使用它, perform/2 将在 timeout 选项(默认为1秒)之后执行,并且还可以使用 handle_timeout/1 .

With it, perform/2 will be executed after timeout option (defaulted to 1 second,) and one might also handle response timeouts with handle_timeout/1.

示例来自测试可能是寻求灵感.

这篇关于每秒具有1个HTTP请求的GenServer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-22 06:06