他们真的很不一样,
pmap 将执行类似于:list.map 的映射(更多此处为http://erlang.org/doc/man/lists.html),但优点是只要节点可用连接并且列表上有要执行的值,此调用将在节点之间发生地图。
multicall 以其他方式将始终执行相同的调用,在多个节点中使用相同的参数。 multicall/4 在所有连接的节点中执行相同的函数调用。 multicall/5 在开头有一个额外的参数,即将执行 rpc 的节点列表。
当我们有一个由 3 个 shell 组成的集群时更好地举例说明
iex --sname node1
iex --sname node2
iex --sname node3
我们在node1执行时相互连接
Node.connect :"node2@mymachine"
# => false
Node.connect :"node3@mymachine"
# => false
我们可以定义一个函数,将 2 个值相加并返回执行此操作的节点的值,如下所示:
iex(node1@mymachine)> defmodule Operation do
...(node1@mymachine)> def sum(a, b), do: {Node.self(), a + b}
...(node1@mymachine)> end
有必要在每个 shell 中定义这个函数。所以现在可以用多个值调用我们的 pmap 看看会发生什么。在我从 node1 调用的计算机中发生了这种情况。
iex(node1@mymachine)> :rpc.pmap {Operation, :sum}, [1], [1,2,3]
[node3@mymachine: 2, node2@mymachine: 3, node1@mymachine: 4]
对于每个节点,sum/2 函数在最后一个位置上使用不同的参数调用,从而产生不同的输出。如果我的:rpc.map/3 的最后一个参数是一个元素较少的列表,那么节点可用,则没有必要调用所有节点。但那些是完成操作所必需的。如果我传递了很多参数,它将以更平衡的方式返回调用。可以尝试在每个节点上执行:rpc.pmap {Operation, :sum}, [1], Enum.to_list 1..20,自己看看结果。
另一方面,当我们使用:rpc.multicall/5 时,您不会传递要并行执行的参数列表,而是要在多个节点中同时执行相同的参数。例如
iex(node1@mymachine)> :rpc.multicall(Operation, :sum, [2, 2], :infinity)
# => {[node1@mymachine: 4, node2@mymachine: 4, node3@mymachine: 4], []}
最后一个参数是每个节点执行的超时时间,如果满足这个超时时间,这个节点的结果将不会显示在元组的第一个列表中。
使用:rpc.multicall/5 可以传递将执行此调用的节点列表作为第一个参数。例如,如果我只想在任何节点内的 node2 和 node3 中执行,我只需执行
iex(node1@mymachine)> :rpc.multicall([:"node2@mymachine", :"node3@mymachine"] Operation, :sum, [2, 2], :infinity)
# => {[node2@mymachine: 4, node3@mymachine: 4], []}
需要注意的一点是,:rpc.multicall/4 和 :rpc.pmap/3 都可以在没有节点的情况下工作,这是因为对于 erlangvm,每当你触发 iex 或 erl 时,你已经在一个单节点集群上.