我在远程节点上有一个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;博士
是的
讨论
有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 连接到集群/网格中即可。两个断开连接的节点必须以不同的方式(网络套接字(进行通信,并且不知道彼此的PID内部映射,但只要使用disterl,它们都很容易在它们之间转换PID。命名进程是事情变得有点棘手的地方,但这就是global
模块和实用程序(如gproc
(的目的(尽管对此类设施的依赖超过一定点通常表明存在架构问题(。
当然,仅仅因为来自任何节点的 PID 可以与来自另一个节点的 PID 通信并不总是意味着它们应该这样做。当您开始发送高频或大型消息(大量gen_server:call
(时,网络的物理拓扑(带宽,延迟,抖动(就会发挥作用,并且您始终必须考虑分区容错 - 但是对于卸载繁重的工作(很少(或在非常大的系统中对子系统进行物理分区(更常见(,直接发送消息是一种非常简单的方法,可以将为单个节点编码的程序分发到各个节点一个集群。
(考虑到所有这些,很少看到使用的 rpc 模块。