在 Elixir 中获取兄弟进程
Getting a sibling process in Elixir
我有一个 Elixir/Erlang 进程树:
parent (Supervisor)
├── child1 (GenServer)
└── child2 (GenServer)
child1(数据库客户端)有child2需要使用的信息。将 Supervisor 进程的引用传递给 child2 以便 child2 始终具有对 child1 的有效引用的好方法是什么?我是否只需要重组我的应用程序,让 child2 由 child1 监督?
最简单的方法可能是在本地别名下注册 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
我不使用 Elixir,但我使用 Erlang,我认为我的回答在这两种情况下都有效。
如果您的 child1 类型的进程是永久的,并且数量固定,那么最简单的解决方案是注册它们(game_server、event_server、...)
但是如果生命短暂,数量不固定,或者会存在很多同类进程(比如游戏中的玩家进程),我建议换个组织:
- 顶级主管启动 2 个进程,一台服务器和一个主管。
- 服务器至少会维护一个列表,其中包含所有活动的 "child1" 进程,这些进程具有允许访问它们的某些特征(玩家 ID ...)。一般它也会使用supervisor进程来启动,杀掉..."child1"个进程。
主管是一个简单的工厂,它将使用 simple_one_for_one 策略创建和监督 "child1"。
parent (Supervisor)
├── child2 (GenServer)
└── Client_supervisor(Supervisor)
├── Client_server(registered GenServer)
└── Client_factory(registered Supervisor)
├── Child1(GenServer)
├── Child1'(GenServer)
└── ...
我有一个 Elixir/Erlang 进程树:
parent (Supervisor)
├── child1 (GenServer)
└── child2 (GenServer)
child1(数据库客户端)有child2需要使用的信息。将 Supervisor 进程的引用传递给 child2 以便 child2 始终具有对 child1 的有效引用的好方法是什么?我是否只需要重组我的应用程序,让 child2 由 child1 监督?
最简单的方法可能是在本地别名下注册 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
我不使用 Elixir,但我使用 Erlang,我认为我的回答在这两种情况下都有效。
如果您的 child1 类型的进程是永久的,并且数量固定,那么最简单的解决方案是注册它们(game_server、event_server、...)
但是如果生命短暂,数量不固定,或者会存在很多同类进程(比如游戏中的玩家进程),我建议换个组织:
- 顶级主管启动 2 个进程,一台服务器和一个主管。
- 服务器至少会维护一个列表,其中包含所有活动的 "child1" 进程,这些进程具有允许访问它们的某些特征(玩家 ID ...)。一般它也会使用supervisor进程来启动,杀掉..."child1"个进程。
主管是一个简单的工厂,它将使用 simple_one_for_one 策略创建和监督 "child1"。
parent (Supervisor) ├── child2 (GenServer) └── Client_supervisor(Supervisor) ├── Client_server(registered GenServer) └── Client_factory(registered Supervisor) ├── Child1(GenServer) ├── Child1'(GenServer) └── ...