我可以从远程节点调用 GenServer 客户端函数吗?
Can I call GenServer client functions from a remote node?
我在远程节点上有一个 GenServer,模块中有实现和客户端功能。我能以某种方式远程使用 GenServer 客户端功能吗?
使用 GenServer.call({RemoteProcessName, :"app@remoteNode"}, :get)
可以达到我的预期,但是很麻烦。
如果我想清理它,我认为必须在调用(客户端)节点上编写客户端函数是否正确?
您可以使用 :rpc.call/{4,5}
函数。
:rpc.call(:"app@remoteNode", MyModule, :some_func, [arg1, arg2])
来电较多时,最好用gen_server:call/2-3
。
如果你想使用rpc:call/4-5
,你应该知道它只是在每个节点上一个名为rex
的进程来处理所有请求。所以如果是运行一个Mod:Func(Arg1, Arg2, Argn)
,此时不能响应其他请求!
TL;DR
是
讨论
有PID、消息、监视器和链接。仅此而已。那就是你的宇宙。 (除非您深入了解运行时实现的一些相当深奥的方面——但在 EVM 语言表示的抽象级别上,前面所述的元素(应该)构成了您的宇宙。)
在 Erlang 环境中(无论是本地还是分布在网格中)任何 PID 可以发送消息给任何其他 PID(不需要中间人),以及建立监控等等。
gen_server:cast
发送 gen_server 打包消息(因此它将以 handle_cast/2
将被调用的形式到达)。 gen_server:call/2
建立监视器和超时以接收标记的回复。简单地做 PID ! SomeMessage
与 gen_server:cast
(发送消息)本质上是一样的,没有任何背后的 gen_server 机制(更难抽象为接口)。
仅此而已。
考虑到这一点,当然您可以跨节点使用 gen_server:call/2
,只要它们通过 disterl 连接到 cluster/mesh。两个断开连接的节点将不得不以不同的方式(网络套接字)进行通信,并且不会知道彼此的 PID 内部映射,但只要使用 disterl,它们就会很容易地相互转换 PID。命名进程是事情变得有点棘手的地方,但这是 global
模块和实用程序(例如 gproc
的目的(尽管对此类设施的依赖超过某一点通常表明存在体系结构问题).
当然,仅仅因为来自任何节点的 PID 可以与来自另一个节点的 PID 通信并不总是意味着它们 应该 。当您开始发送高频或大型消息(很多 gen_server:call
s)时,网络的物理拓扑(带宽、延迟、抖动)开始发挥作用,并且您总是必须考虑分区容错性——但是为了减轻繁重的工作(很少见)或在一个非常大的系统中对子系统进行物理分区(更常见),直接发送消息是一种非常简单的方法,可以将为单个节点编码的程序分发到集群中。
(考虑到所有这些,很少看到使用 rpc 模块。)
我在远程节点上有一个 GenServer,模块中有实现和客户端功能。我能以某种方式远程使用 GenServer 客户端功能吗?
使用 GenServer.call({RemoteProcessName, :"app@remoteNode"}, :get)
可以达到我的预期,但是很麻烦。
如果我想清理它,我认为必须在调用(客户端)节点上编写客户端函数是否正确?
您可以使用 :rpc.call/{4,5}
函数。
:rpc.call(:"app@remoteNode", MyModule, :some_func, [arg1, arg2])
来电较多时,最好用gen_server:call/2-3
。
如果你想使用rpc:call/4-5
,你应该知道它只是在每个节点上一个名为rex
的进程来处理所有请求。所以如果是运行一个Mod:Func(Arg1, Arg2, Argn)
,此时不能响应其他请求!
TL;DR
是
讨论
有PID、消息、监视器和链接。仅此而已。那就是你的宇宙。 (除非您深入了解运行时实现的一些相当深奥的方面——但在 EVM 语言表示的抽象级别上,前面所述的元素(应该)构成了您的宇宙。)
在 Erlang 环境中(无论是本地还是分布在网格中)任何 PID 可以发送消息给任何其他 PID(不需要中间人),以及建立监控等等。
gen_server:cast
发送 gen_server 打包消息(因此它将以 handle_cast/2
将被调用的形式到达)。 gen_server:call/2
建立监视器和超时以接收标记的回复。简单地做 PID ! SomeMessage
与 gen_server:cast
(发送消息)本质上是一样的,没有任何背后的 gen_server 机制(更难抽象为接口)。
仅此而已。
考虑到这一点,当然您可以跨节点使用 gen_server:call/2
,只要它们通过 disterl 连接到 cluster/mesh。两个断开连接的节点将不得不以不同的方式(网络套接字)进行通信,并且不会知道彼此的 PID 内部映射,但只要使用 disterl,它们就会很容易地相互转换 PID。命名进程是事情变得有点棘手的地方,但这是 global
模块和实用程序(例如 gproc
的目的(尽管对此类设施的依赖超过某一点通常表明存在体系结构问题).
当然,仅仅因为来自任何节点的 PID 可以与来自另一个节点的 PID 通信并不总是意味着它们 应该 。当您开始发送高频或大型消息(很多 gen_server:call
s)时,网络的物理拓扑(带宽、延迟、抖动)开始发挥作用,并且您总是必须考虑分区容错性——但是为了减轻繁重的工作(很少见)或在一个非常大的系统中对子系统进行物理分区(更常见),直接发送消息是一种非常简单的方法,可以将为单个节点编码的程序分发到集群中。
(考虑到所有这些,很少看到使用 rpc 模块。)