我正在测试这样的节点间函数调用(rpc):
defmodule RpcTest do
def run do
Task.Supervisor.async( {DBServer.DistSupervisor, :'dbserver@hostname'}, fn -> "test" end)
|> Task.await
|> IO.inspect
end
end
然后我运行dbserver
node,调用接收rcp,在另一个node执行上面的Task.Supervisor.start_link(name: DBServer.DistSupervisor)
代码dbserver
dbclient
它可以正确运行 rpc,如下所示。
dbserver
$ iex --sname dbserver --cookie a -S mix
Erlang/OTP 18 [erts-7.3] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Compiling 1 file (.ex)
Interactive Elixir (1.3.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(dbserver@hostname)1> Task.Supervisor.start_link(name: DBServer.DistSupervisor)
{:ok, #PID<0.101.0>}
iex(dbserver@hostname)2>
dbclient
$ elixir --sname dbclient --cookie a -S mix run -e RpcTest.run
"test"
但是,将代码从“更改"test"
为"test test
”后,dbclient 节点不起作用。
这是错误消息
dbserver
iex(dbserver@hostname)2>
12:54:57.430 [error] Task #PID<0.110.0> started from {:"dbclient@hostname", #PID<13423.52.0>} terminating
** (BadFunctionError) expected a function, got: #Function<0.113878361/0 in RpcTest>
:erlang.apply/2
(elixir) lib/task/supervised.ex:94: Task.Supervised.do_apply/2
(elixir) lib/task/supervised.ex:45: Task.Supervised.reply/5
(stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Function: #Function<0.113878361/0 in RpcTest>
Args: []
dbclient
$ elixir --sname dbclient --cookie a -S mix run -e RpcTest.run
Compiling 1 file (.ex)
** (EXIT from #PID<0.52.0>) an exception was raised:
** (BadFunctionError) expected a function, got: #Function<0.113878361/0 in RpcTest.run/0>
:erlang.apply/2
(elixir) lib/task/supervised.ex:94: Task.Supervised.do_apply/2
(elixir) lib/task/supervised.ex:45: Task.Supervised.reply/5
(stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
此外,它在手动重新启动后确实有效。dbserver
有趣的是,它适用于iex
任何代码。
$ iex --sname dbclient --cookie a -S mix
Erlang/OTP 18 [erts-7.3] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Compiling 1 file (.ex)
Interactive Elixir (1.3.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(dbclient@hostname)1> Task.Supervisor.async( {DBServer.DistSupervisor, :'dbserver@hostname'}, fn -> "test" end) |>
...(dbclient@hostname)1> Task.await |>
...(dbclient@hostname)1> IO.inspect
"test"
"test"
iex(dbclient@hostname)2> Task.Supervisor.async( {DBServer.DistSupervisor, :'dbserver@hostname'}, fn -> "test test" end) |>
...(dbclient@hostname)2> Task.await |>
...(dbclient@hostname)2> IO.inspect
"test test"
"test test"
我的问题是,
- 从另一个节点调用节点中的函数是错误的方法吗?
- 使用节点间函数调用时,每次更改客户端代码时是否必须重新执行被调用节点?
iex
为什么和之间的行为不同elixir script
?
代码和整个项目上传到这里:https ://github.com/ayamamori/rpc_test/blob/master/lib/rpc_test.ex
提前致谢!