我有一个 Erlang 应用程序,它有点太消耗资源而无法留在一个节点上。我正在让 gen_servers 从一个进程移动到另一个进程——结果证明这相对容易。我遇到了最后一个障碍:让创建这些 gen_servers 的工厂进程在远程节点而不是本地节点上生成它们。start_link 的默认行为显然是仅在本地启动,但我看不到任何更改它的选项。
看来我将不得不对解决方案具有创造性,并想看看那里是否有人已经成功地实施了类似的东西。IOW,推荐的解决方案是什么?
编辑
我正在查看由调用触发的调用链:
gen_server:start_link(?Module, Args, [])
gen_server:start_link/3:
start_link(Mod, Args, Options) ->
gen:start(?MODULE, link, Mod, Args, Options).
创:开始/ 5:
start(GenMod, LinkP, Mod, Args, Options) ->
do_spawn(GenMod, LinkP, Mod, Args, Options).
gen:do_spawn/5:
do_spawn(GenMod, link, Mod, Args, Options) ->
Time = timeout(Options),
proc_lib:start_link(?MODULE, init_it,
[GenMod, self(), self(), Mod, Args, Options],
Time,
spawn_opts(Options));
proc_lib:start_link/5:
start_link(M,F,A,Timeout,SpawnOpts) when is_atom(M), is_atom(F), is_list(A) ->
Pid = ?MODULE:spawn_opt(M, F, A, ensure_link(SpawnOpts)),
sync_wait(Pid, Timeout).
这最终让我们来到了有趣的地方。有一个 spawn_opt/4 匹配:
spawn_opt(M, F, A, Opts) when is_atom(M), is_atom(F), is_list(A) ->
...
...
但是,有一个实际上对我有用:
spawn_opt(Node, M, F, A, Opts) when is_atom(M), is_atom(F), is_list(A) ->
...
...
令人难以置信的是,这没有暴露。我意识到粗心的程序员可能会尝试 gen_server:start_link 恰好在火星上运行的 erlang 节点上的进程,从而阻塞调用半小时,但可以肯定的是,这是程序员的注意。我真的坚持修改 OTP 或编写某种临时解决方案吗?