- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在自动启动监督树时遇到了死锁问题。一个 GenServer 的初始状态是树中另一个主管的子进程。代码如下:
主管和 worker :
defmodule Parallel.Worker.Supervisor do
import Supervisor.Spec
def start_link do
# Start up a worker for each core
schedulers = :erlang.system_info(:schedulers)
children = Enum.map(1..schedulers,
&(worker(Parallel.Worker.Server, [], id: "Parallel.Worker#{&1}")))
opts = [strategy: :one_for_one, name: Parallel.Worker.Supervisor]
Supervisor.start_link(children, opts)
end
def workers do
Process.whereis(Parallel.Supervisor)
|> Supervisor.which_children
|> Enum.reduce [], fn
{_name, pid, :worker, _module}, acc -> [{make_ref, pid} | acc]
_, acc -> acc
end
end
end
GenServer 以及这些工作进程 pid 的状态:
defmodule Parallel.Process.Server do
use GenServer
def start_link do
GenServer.start_link(__MODULE__, workers: [Parallel.Worker.Supervisor.workers])
end
end
正如您在最后一行所看到的,我正在调用“Parallel.Worker.Supervisor.workers”,它似乎会阻止等待树上的初始化,直到该方法返回时才会完成。如何将受监督的 PID 作为初始 GenServer 状态?
更新:
我不想使用 poolboy(尽管查看源代码是一个很好的建议)来帮助我了解更多信息。我并不想做任何特别的事情,我的工作人员只是处理传递的函数及其参数。这是工作 GenServer:
defmodule Parallel.Worker do
use GenServer
require Logger
def start_link(state) do
GenServer.start_link(__MODULE__, state, [])
end
def init(state) do
{:ok, state}
end
# Using cast to be async as the job could take longer than the default 5 seconds,
# Don't want client blocked on waiting for job to complete
def handle_cast({:execute, fun, args, return_pid, job_ref}, state) do
Logger.debug fn()-> "#{inspect self}: Recevied job with args: #{inspect args} for job #{inspect job_ref} to return to #{inspect return_pid}" end
send(return_pid, {job_ref, apply(fun, args), self})
{:noreply, state}
end
end
最佳答案
我假设您想在这里创建某种池?正如评论中提到的,你应该看看 poolboy。如果出于练习的目的,您想自己实现这一点,那么仍然值得研究 poolboy 代码以获取灵感。
本质上,poolboy 池由“池管理器”管理 - 一个维护已知工作人员集合的 gen_server。此池管理器进程在内部启动一个 simple_one_for_one
主管,然后用于启动和监督工作人员。
池管理器进程 during initialization first starts the supervisor 。然后,它调用 prepopulate/1
来 start supervised worker processes 。该函数将动态创建N个worker via supervisor:start_child/2 ,并且池管理器可以在内部保留工作进程 pid 列表。
这可以确保池管理器进程在初始化期间不需要与父主管通信(这就是导致死锁的原因)。相反,管理者自己创建 child 。依靠内部监督者仍然可以确保 worker 驻留在监督树中。
还需要一些其他精美的细节来确保一切正常工作。 Poolboy 进程(池管理器)将捕获退出,链接到监视器,并在 worker check out 时对其进行监视。这确保了正确检测工作人员崩溃。我建议阅读代码以进行进一步分析。
我的观点是,这可能是一个有趣的练习,可以更好地理解 OTP。但是,如果您是为了生产而执行此操作,那么直接使用 poolboy 可能会更好。
关于Elixir - GenServer 具有其他几个 GenServer pid 的初始状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27031222/
我在自动启动监督树时遇到了死锁问题。一个 GenServer 的初始状态是树中另一个主管的子进程。代码如下: 主管和 worker : defmodule Parallel.Worker.Superv
考虑这样简单的 GenServer 模块: defmodule Crap do use GenServer ... #All the needed crap def handle_info
背景 我有一组测试需要先启动 GenServer。根据经验,我知道在每次测试后进行清理是一种很好的做法,因此我也想在每次测试后停止 GenServer。 问题 这里的问题是我不知道如何在测试完成后停止
在elixir GenServer中,有sync和async方法,handle_cast和handle_call。在异步情况下,如果该方法失败,我如何获得通知? 方法失败意味着在handle_call
我对一些 OTP 概念不熟悉。我有 GenServer,它将向 RabbitMQ 发布事件。此 GenServer 具有状态:amqp Chanel,它在 init() 期间启动一次,并在 cast
我缩小了问题的大小,因为它太大了。这是代码: defmodule MayRaiseGenServer do use GenServer def start_link do IO.put
我正在练习这个例子。 https://github.com/kwmiebach/how-to-elixir-supervisor 我按照说明进行操作并了解它是如何工作的,但我无法理解 Supervis
我的一项服务与速率受限的外部 API 进行通信,因此我想确保每 10 秒发送的调用不超过 1 个。 我的天真的方法是拥有一个长期运行的 API 服务,并在每次调用后超时: def handle_cas
我最近遇到了一点麻烦:GenServer 进程使用的内存非常高,可能是因为大量的二进制泄漏。 问题来自于这里:我们通过 GenServer 接收大型二进制文件,并将它们传递给消费者,然后消费者与该数据
我知道我可以像这样调用 GenServer GenServer.call(pid, request) # using a pid 或者像这样 GenServer.call(registered_nam
我的一项服务与速率受限的外部 API 进行通信,因此我想确保每 10 秒发送的调用不超过 1 个。 我的天真的方法是拥有一个长期运行的 API 服务,并在每次调用后超时: def handle_cas
假设我有 GenServer 实例: defmodule MyModule do use GenServer def init(_) do {:ok, %{}} end #... e
我有一个为单个项目实现功能的 GenServer,例如: def handle_call({:sync, id}, _from, state) do ## update data {:
给定一个简单的 GenServer过程。 defmodule KVServer do use GenServer def start do GenServer.start(__MODU
我正在编写一个模块来查询在线天气 API。我决定将它作为一个应用程序来实现,并带有一个受监督的 GenServer . 这是代码: defmodule Weather do use GenServ
场景: 我有一个简单的GenServer来管理某些状态。 目前,我正在使用 map 来管理我的状态。但它正在增长我正在向该状态添加更多数据。 问题: 那么,为了获得一些编译时保证,我的 GenServ
我正在阅读this关于如何从现有的phoenix应用程序中提取微服务的文章。作者重构了 phoenix 应用程序 Controller 之一,并将其方法之一移至 Genserver,之后将该 Ge
我有一个模拟应用程序范围的 Repo 的测试。大多数时候,测试都是绿色的。当我在循环中运行测试时,使用相同的种子,可能有 10% 的运行成功,但带有 GenServer 终止消息: 15:39:34.
我有一个 GenServer,它负责联系外部资源。调用外部资源的结果并不重要,偶尔失败是可以接受的,所以使用 handle_cast 似乎适用于代码的其他部分。我确实有一个用于该外部资源的类似接口(i
在这两种方法中,我都坚持如何通过给定的一组 id 或组映射进程,然后将存储的结构映射到过滤数据。%{group => [users]}执行。 我意识到组将与用户相反,因此我创建了一个使用组名称作为键的
我是一名优秀的程序员,十分优秀!