我在远程节点上有一个GenServer,在模块中同时具有实现和客户端功能。我可以通过某种方式远程使用GenServer客户端功能吗?
使用GenServer.call({RemoteProcessName, :"app@remoteNode"}, :get)
可以正常工作,但是很麻烦。
如果我想清理这个问题,是在考虑是否必须在调用(客户端)节点上编写客户端功能吗?
答案 0 :(得分:2)
您可以使用:rpc.call/{4,5}
函数。
:rpc.call(:"app@remoteNode", MyModule, :some_func, [arg1, arg2])
答案 1 :(得分:2)
对于大量呼叫,最好是用户gen_server:call/2-3
。
如果要使用rpc:call/4-5
,则应该知道它只是每个节点上名为rex
的一个进程,用于处理所有请求。因此,如果它正在运行一个Mod:Func(Arg1, Arg2, Argn)
,则此时它无法响应其他请求!
答案 2 :(得分:0)
TL; DR
是
讨论
有PID,消息,监视器和链接。仅此而已。那就是你的宇宙。 (除非您进入了运行时实现的一些颇为深奥的方面,但是在以EVM语言表示的抽象级别上,(应该)先前说明的元素构成了您的Universe。)
在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
,只要它们通过disdisl连接到集群/网格中即可。两个断开连接的节点将必须以不同的方式进行通信(网络套接字),并且彼此之间对PID的内部映射一无所知,但是只要使用Disterl,它们就可以很容易地在它们之间转换PID。命名过程会让事情变得有些棘手,但这就是global
模块和诸如gproc
之类的实用程序的目的(尽管对特定功能的依赖超出一定程度通常表明存在体系结构问题)。
当然,仅仅因为来自任何节点的PID可以与来自另一个节点的PID进行通信,并不总是意味着它们应该。当您开始发送高频或大型消息(很多gen_server:call
s)时,网络的物理拓扑(带宽,延迟,抖动)就开始起作用了,您始终必须考虑分区容限-但对于卸载繁重的工作(稀有)或在非常大的系统中对子系统进行物理分区(更常见),直接发送消息是采用为单个节点编码的程序并将其分布在整个群集中的一种非常简单的方法。
(考虑到所有这些,很少看到所使用的rpc模块。)