【问题标题】:Getting a sibling process in Elixir在 Elixir 中获取兄弟进程
【发布时间】:2015-08-21 17:21:21
【问题描述】:
我有一个 Elixir/Erlang 进程树:
parent (Supervisor)
├── child1 (GenServer)
└── child2 (GenServer)
child1(一个 DB 客户端)拥有 child2 需要使用的信息。将 Supervisor 进程的引用传递给 child2 以使 child2 始终具有对 child1 的有效引用的好方法是什么?我是否只需要重组我的应用程序,让 child2 由 child1 监督?
【问题讨论】:
标签:
erlang
elixir
erlang-otp
【解决方案1】:
最简单的方法可能是使用本地别名注册child1 和child2。您可以在启动 GenServer 时通过传递 name 选项来执行此操作:
defmodule Child1 do
use GenServer
def start_link do
GenServer.start_link(__MODULE__, [], name: __MODULE__)
end
end
在这种情况下,由Child1 模块支持的进程将在本地以别名Child1 注册。然后,如果您想向它发送消息,您可以使用该别名而不是 PID。
defmodule Child1 do
# ...
def get_data do
GenServer.call(__MODULE__, :get_data)
end
def handle_call(:get_data, _from, state) do
{:reply, extract_data_from_state(state), state}
end
end
如果您想要一个更复杂的解决方案,例如可以注册许多相同类型的不同进程,请查看gproc library
【解决方案2】:
我不使用 Elixir,但我使用 Erlang,我认为我的答案在这两种情况下都是有效的。
如果您的 child1 类型的进程是永久的,并且数量固定,那么最简单的解决方案是注册它们(game_server,event_server,...)
但是如果他们有短暂的生命,他们的数量是不固定的,或者会存在许多相同类型的进程(例如游戏中的玩家进程)我建议使用另一个组织:
- 顶级主管启动 2 个进程,一个服务器和一个主管。
- 至少,服务器将维护所有活动“child1”进程的列表,这些进程具有允许访问它们的某些特征(玩家 ID ...)。通常它还会使用主管进程来启动、杀死……“child1”进程。
-
supervisor 是一个简单的工厂,它将使用 simple_one_for_one 策略创建和监督“child1”。
parent (Supervisor)
├── child2 (GenServer)
└── Client_supervisor(Supervisor)
├── Client_server(registered GenServer)
└── Client_factory(registered Supervisor)
├── Child1(GenServer)
├── Child1'(GenServer)
└── ...