查看源码 erpc (内核 v10.2)

增强型远程过程调用

此模块提供类似于远程过程调用的服务。远程过程调用是一种在远程节点上调用函数并收集答案的方法。它用于收集远程节点上的信息,或者在远程节点上运行具有某些特定副作用的函数。

这是 rpc 模块提供的操作的增强子集。增强是指它可以区分返回值、引发的异常和其他错误。erpc 也比原始 rpc 实现具有更好的性能和可伸缩性。但是,当前的 rpc 模块将利用 erpc 来尽可能地提供这些属性。

为了使 erpc 操作成功,远程节点也需要支持 erpc。通常,只有 OTP 23 或更高版本的普通 Erlang 节点才具有 erpc 支持。

请注意,用户有责任确保通过 erpc 执行的正确代码在相关节点上可用。

注意

有关分布式信号的一些重要信息,请参阅 Erlang 参考手册进程章节中的通过分布的阻塞信号部分。阻塞信号可能会导致 erpc 中的超时显著延迟。

总结

类型

一个不透明的请求标识符。有关更多信息,请参阅 send_request/4

一个不透明的请求标识符集合 (request_id/0),其中每个请求标识符都可以与用户选择的标签关联。有关更多信息,请参阅 reqids_new/0

erpc 函数使用的超时时间。

函数

在节点 Node 上评估 apply(Module, Function, Args) 并返回相应的值 ResultTimeout 设置 call 操作完成的最长时间限制。

在节点 Node 上评估 apply(Module, Function, Args)。不向调用进程传递响应。cast() 在发送 cast 请求后立即返回。除了错误的参数外,任何失败都将被静默忽略。

检查消息是否是对调用进程先前使用 send_request/4 发出的 call 请求的响应。

检查消息是否是对 RequestIdCollection 中保存的请求标识符对应的 call 请求的响应。RequestIdCollection 的所有请求标识符必须对应于使用 send_request/4send_request/6 发出的请求,并且所有请求都必须由调用此函数的进程发出。

在多个节点上并行执行多个 call 操作。

在节点 Nodes 上评估 apply(Module, Function, Args)。不向调用进程传递响应。multicast() 在发送 cast 请求后立即返回。除了错误的参数外,任何失败都将被静默忽略。

接收对调用进程先前使用 send_request/4 发出的 call 请求的响应。

接收对 RequestIdCollection 中保存的请求标识符对应的 call 请求的响应。RequestIdCollection 的所有请求标识符必须对应于使用 send_request/4send_request/6 发出的请求,并且所有请求都必须由调用此函数的进程发出。

保存 RequestId 并通过将此信息添加到 RequestIdCollection 并返回生成的请求标识符集合,将 Label 与请求标识符关联。

返回一个新的空请求标识符集合。可以使用请求标识符集合来处理多个未完成的请求。

返回 RequestIdCollection 中保存的请求标识符的数量。

返回一个 {RequestId, Label} 元组的列表,该列表对应于 RequestIdCollection 集合中存在的所有请求标识符及其关联的标签。

向节点 Node 发送异步 call 请求。

向节点 Node 发送异步 call 请求。Label 将与操作的请求标识符关联,并添加到返回的请求标识符集合 NewRequestIdCollection。稍后可以通过将该集合作为参数传递给 receive_response/3wait_response/3check_response/3 来获取集合中与请求对应的响应。

等效于 erpc:wait_response(RequestId, 0)。也就是说,轮询先前由调用进程发出的 call 请求的响应消息。

等待或轮询先前由调用进程使用 send_request/4 发出的 call 请求的响应消息。

等待或轮询与 RequestIdCollection 中保存的请求标识符对应的 call 请求的响应。RequestIdCollection 的所有请求标识符必须对应于使用 send_request/4send_request/6 发出的请求,并且所有请求都必须由调用此函数的进程发出。

类型

链接到此类型

caught_call_exception()

查看源码 (未导出) (自 OTP 23.0 起)
-type caught_call_exception() ::
          {throw, Throw :: term()} |
          {exit, {exception, Reason :: term()}} |
          {error, {exception, Reason :: term(), StackTrace :: [stack_item()]}} |
          {exit, {signal, Reason :: term()}} |
          {error, {erpc, Reason :: term()}}.
链接到此不透明

request_id()

查看源码 (自 OTP 23.0 起)
-opaque request_id()

一个不透明的请求标识符。有关更多信息,请参阅 send_request/4

链接到此不透明

request_id_collection()

查看源码 (自 OTP 23.0 起)
-opaque request_id_collection()

一个不透明的请求标识符集合 (request_id/0),其中每个请求标识符都可以与用户选择的标签关联。有关更多信息,请参阅 reqids_new/0

链接到此类型

stack_item()

查看源码 (未导出) (自 OTP 23.0 起)
-type stack_item() ::
          {Module :: atom(),
           Function :: atom(),
           Arity :: arity() | (Args :: [term()]),
           Location :: [{file, Filename :: string()} | {line, Line :: pos_integer()}]}.
链接到此类型

timeout_time()

查看源码 (自 OTP 23.0 起)
-type timeout_time() :: 0..4294967295 | infinity | {abs, integer()}.

erpc 函数使用的超时时间。

该值可以是

  • 0..4294967295 - 相对于当前时间的毫秒超时。

  • infinity - 无限超时。也就是说,操作永远不会超时。

  • {abs, Timeout} - 绝对 Erlang 单调时间超时,以毫秒为单位。也就是说,当 erlang:monotonic_time(millisecond) 返回的值大于或等于 Timeout 时,操作将超时。不允许 Timeout 识别超过 4294967295 毫秒的未来时间。当响应与完整的请求集合 (request_id_collection/0) 相对应时,使用绝对超时值标识超时尤其方便,因为您不必一遍又一遍地重新计算截止时间之前的相对时间。

函数

链接到此函数

call(Node, Fun)

查看源码 (自 OTP 23.0 起)
-spec call(Node, Fun) -> Result when Node :: node(), Fun :: function(), Result :: term().

等效于 call(Node, Fun, infinity)

链接到此函数

call(Node, Fun, Timeout)

查看源代码 (自 OTP 23.0 起)
-spec call(Node, Fun, Timeout) -> Result
              when Node :: node(), Fun :: function(), Timeout :: timeout_time(), Result :: term().

等效于 erpc:call(Node, erlang, apply, [Fun,[]], Timeout)

可能会引发与 call/5 相同的异常,此外,如果 Fun 不是零元函数,则会引发 {erpc, badarg} error 异常。

链接到此函数

call(Node, Module, Function, Args)

查看源代码 (自 OTP 23.0 起)
-spec call(Node, Module, Function, Args) -> Result
              when
                  Node :: node(),
                  Module :: atom(),
                  Function :: atom(),
                  Args :: [term()],
                  Result :: term().

等效于 call(Node, Module, Function, Args, infinity)

链接到此函数

call(Node, Module, Function, Args, Timeout)

查看源代码 (自 OTP 23.0 起)
-spec call(Node, Module, Function, Args, Timeout) -> Result
              when
                  Node :: node(),
                  Module :: atom(),
                  Function :: atom(),
                  Args :: [term()],
                  Timeout :: timeout_time(),
                  Result :: term().

在节点 Node 上评估 apply(Module, Function, Args) 并返回相应的值 ResultTimeout 设置 call 操作完成的最长时间限制。

只有当所应用的函数成功返回且没有引发任何未捕获的异常、操作没有超时且没有发生任何故障时,call() 函数才会返回。在所有其他情况下,都会引发异常。以下异常(按异常类列出)目前可以由 call() 引发。

  • throw - 所应用的函数调用了 throw(Value) 并且没有捕获此异常。异常原因 Value 等于传递给 throw/1 的参数。

  • exit - 异常原因

    • {exception, ExitReason} - 所应用的函数调用了 exit(ExitReason) 并且没有捕获此异常。退出原因 ExitReason 等于传递给 exit/1 的参数。

    • {signal, ExitReason} - 应用该函数的进程接收到退出信号并因该信号而终止。该进程以退出原因 ExitReason 终止。

  • error - 异常原因

    • {exception, ErrorReason, StackTrace} - 在应用函数时发生运行时错误,从而引发错误异常,并且所应用的函数没有捕获该异常。错误原因 ErrorReason 指示发生的错误类型。StackTrace 的格式与在 try/catch 结构中捕获时相同。StackTrace 仅限于所应用的函数及其调用的函数。

    • {erpc, ERpcErrorReason} - erpc 操作失败。以下 ERpcErrorReason 是最常见的错误原因:

      • badarg - 如果以下任何一项为真:

        • Node 不是原子。
        • Module 不是原子。
        • Function 不是原子。
        • Args 不是列表。请注意,该列表在客户端未验证为正确列表。
        • Timeout 无效。
      • noconnection - 与 Node 的连接丢失或无法建立。该函数可能被应用,也可能不被应用。

      • system_limit - 由于达到某些系统限制,erpc 操作失败。这通常是由于无法在远程节点 Node 上创建进程,但也可能是其他原因。

      • timeout - erpc 操作超时。该函数可能被应用,也可能不被应用。

      • notsup - 远程节点 Node 不支持此 erpc 操作。

如果 erpc 操作失败,但不知道该函数是否/将要被应用(即超时或连接丢失),则调用方将不会收到有关所应用函数何时完成的任何进一步信息。如果所应用的函数明确地与调用进程通信,则此类通信当然可以到达调用进程。

注意

您不能对将执行 apply() 的进程做出任何假设。它可能是调用进程本身、服务器或新生成的进程。

链接到此函数

cast(Node, Fun)

查看源代码 (自 OTP 23.0 起)
-spec cast(Node, Fun) -> ok when Node :: node(), Fun :: function().

等效于 erpc:cast(Node,erlang,apply,[Fun,[]])

如果出现以下情况,cast/2 会因 {erpc, badarg} error 异常而失败:

  • Node 不是原子。
  • Fun 不是零元函数。
链接到此函数

cast(Node, Module, Function, Args)

查看源代码 (自 OTP 23.0 起)
-spec cast(Node, Module, Function, Args) -> ok
              when Node :: node(), Module :: atom(), Function :: atom(), Args :: [term()].

在节点 Node 上评估 apply(Module, Function, Args)。不向调用进程传递响应。cast() 在发送 cast 请求后立即返回。除了错误的参数外,任何失败都将被静默忽略。

如果出现以下情况,cast/4 会因 {erpc, badarg} error 异常而失败:

  • Node 不是原子。
  • Module 不是原子。
  • Function 不是原子。
  • Args 不是列表。请注意,该列表在客户端未验证为正确列表。

注意

您不能对将执行 apply() 的进程做出任何假设。它可能是服务器,也可能是新生成的进程。

链接到此函数

check_response(Message, RequestId)

查看源代码 (自 OTP 23.0 起)
-spec check_response(Message, RequestId) -> {response, Result} | no_response
                        when Message :: term(), RequestId :: request_id(), Result :: term().

检查消息是否是对调用进程先前使用 send_request/4 发出的 call 请求的响应。

RequestId 应该是先前 send_request/4 调用返回的值,并且相应的响应不应已由 check_response/2receive_response/2wait_response/2 接收并处理完毕。Message 是要检查的消息。

如果 Message 与响应不对应,则返回原子 no_response。如果 Message 与响应对应,则 call 操作完成,并且返回值将以 {response, Result} 的形式返回,其中 Result 对应于所应用函数返回的值,否则会引发异常。可以引发的异常与 call/4 可以引发的异常相同。也就是说,不会引发 {erpc, timeout} error 异常。如果/当检测到无效的 RequestId 时,check_response() 将会因 {erpc, badarg} 异常而失败。

如果 erpc 操作失败,但不知道该函数是否/将要被应用(即连接丢失),则调用方将不会收到有关所应用函数何时完成的任何进一步信息。如果所应用的函数明确地与调用进程通信,则此类通信当然可以到达调用进程。

链接到此函数

check_response(Message, RequestIdCollection, Delete)

查看源代码 (自 OTP 25.0 起)
-spec check_response(Message, RequestIdCollection, Delete) ->
                        {{response, Result}, Label, NewRequestIdCollection} | no_response | no_request
                        when
                            Message :: term(),
                            RequestIdCollection :: request_id_collection(),
                            Delete :: boolean(),
                            Result :: term(),
                            Label :: term(),
                            NewRequestIdCollection :: request_id_collection().

检查消息是否是对 RequestIdCollection 中保存的请求标识符对应的 call 请求的响应。RequestIdCollection 的所有请求标识符必须对应于使用 send_request/4send_request/6 发出的请求,并且所有请求都必须由调用此函数的进程发出。

Label 是与响应对应的请求标识符关联的标签。当在 请求标识符集合添加请求标识符 或使用 send_request/6 发送请求时,请求标识符会与标签关联。

check_response/2 相比,与特定请求标识符关联的返回结果或与特定请求标识符关联的异常将包装在 3 元组中。此元组的第一个元素等于 check_response/2 将会生成的值,第二个元素等于与特定请求标识符关联的 Label,第三个元素 NewRequestIdCollection 是可能已修改的请求标识符集合。error 异常 {erpc, badarg} 与任何特定请求标识符无关,因此不会被包装。

如果 RequestIdCollection 为空,则返回原子 no_request。如果 MessageRequestIdCollection 中的任何请求标识符都不对应,则返回原子 no_response

如果 Delete 等于 true,则与 Label 的关联将已从结果 NewRequestIdCollection 中的 RequestIdCollection 中删除。如果 Delete 等于 false,则 NewRequestIdCollection 将等于 RequestIdCollection。请注意,删除关联并非没有代价,并且包含已处理请求的集合仍然可以被后续的 check_response/3receive_response/3wait_response/3 调用使用。但是,如果不删除已处理的关联,则以上调用将无法检测到何时没有更多未完成的请求需要处理,因此您必须以其他方式(而不是依赖 no_request 返回值)来跟踪此情况。请注意,如果您传递一个仅包含已处理或放弃的请求的关联的集合给 check_response/3,它将始终返回 no_response

请注意,响应可能在发生 {erpc, badarg} 异常时被使用,如果是这样,则将永远丢失。

链接到此函数

multicall(Nodes, Fun)

查看源代码 (自 OTP 23.0 起)
-spec multicall(Nodes, Fun) -> Result when Nodes :: [atom()], Fun :: function(), Result :: term().

等效于 multicall(Nodes, Fun, infinity)

链接到此函数

multicall(Nodes, Fun, Timeout)

查看源代码 (自 OTP 23.0 起)
-spec multicall(Nodes, Fun, Timeout) -> Result
                   when
                       Nodes :: [atom()], Fun :: function(), Timeout :: timeout_time(), Result :: term().

等效于 erpc:multicall(Nodes, erlang, apply, [Fun,[]], Timeout)

可能会引发与 multicall/5 相同的异常,此外,如果 Fun 不是零元函数,则会引发 {erpc, badarg} error 异常。

链接到此函数

multicall(Nodes, Module, Function, Args)

查看源代码 (自 OTP 23.0 起)
-spec multicall(Nodes, Module, Function, Args) -> Result
                   when
                       Nodes :: [atom()],
                       Module :: atom(),
                       Function :: atom(),
                       Args :: [term()],
                       Result :: [{ok, ReturnValue :: term()} | caught_call_exception()].

等效于 multicall(Nodes, Module, Function, Args, infinity)

链接到此函数

multicall(Nodes, Module, Function, Args, Timeout)

查看源代码 (自 OTP 23.0 起)
-spec multicall(Nodes, Module, Function, Args, Timeout) -> Result
                   when
                       Nodes :: [atom()],
                       Module :: atom(),
                       Function :: atom(),
                       Args :: [term()],
                       Timeout :: timeout_time(),
                       Result :: [{ok, ReturnValue :: term()} | caught_call_exception()].

在多个节点上并行执行多个 call 操作。

也就是说,在节点 Nodes 上并行计算 apply(Module, Function, Args)Timeout 设置所有 call 操作完成的上限时间。结果以列表形式返回,其中每个节点的结果与其在 Nodes 中节点名称的位置相同。结果列表中的每个项的格式为:

  • {ok, Result} - 此特定节点的 call 操作返回 Result

  • {Class, ExceptionReason} - 此特定节点的 call 操作引发了类 Class 的异常,异常原因为 ExceptionReason。这些异常对应于 call/5 可以引发的异常。

如果出现以下情况,multicall/5 会因 {erpc, badarg} error 异常而失败:

  • Nodes 不是原子的正确列表。请注意,当发生故障时,某些请求可能已经发送。也就是说,该函数可能在某些节点上被应用,也可能不被应用。
  • Module 不是原子。
  • Function 不是原子。
  • Args 不是列表。请注意,该列表在客户端未验证为正确列表。

调用 erpc:multicall(Nodes, Module, Function, Args) 等同于调用 erpc:multicall(Nodes, Module, Function, Args, infinity)。如果忽略性能和失败行为,这些调用也等同于调用下面的 my_multicall(Nodes, Module, Function, Args)multicall() 可以利用选择性接收优化,从而无需从头开始扫描消息队列以查找匹配的消息。然而,send_request()/receive_response() 组合无法利用此优化。

my_multicall(Nodes, Module, Function, Args) ->
  ReqIds = lists:map(fun (Node) ->
                       erpc:send_request(Node, Module, Function, Args)
                     end,
                     Nodes),
  lists:map(fun (ReqId) ->
              try
                {ok, erpc:receive_response(ReqId, infinity)}
              catch
                Class:Reason ->
                  {Class, Reason}
              end
            end,
            ReqIds).

如果 erpc 操作失败,但不知道该函数是否已应用/将要应用(即超时、连接丢失或错误的 Nodes 列表),则调用者将不会收到关于已应用函数完成时的进一步结果信息。当然,如果已应用函数与调用进程通信,则此类通信可能会到达调用进程。

注意

您不能对将执行 apply() 的进程做出任何假设。它可能是调用进程本身、服务器或新生成的进程。

链接到此函数

multicast(Nodes, Fun)

查看源码 (自 OTP 23.0 起)
-spec multicast(Nodes, Fun) -> ok when Nodes :: [node()], Fun :: function().

等效于 erpc:multicast(Nodes,erlang,apply,[Fun,[]])

如果出现以下情况,multicast/2 将失败并抛出 {erpc, badarg} error 异常:

  • Nodes 不是原子类型的正确列表。
  • Fun 不是零元函数。
链接到此函数

multicast(Nodes, Module, Function, Args)

查看源码 (自 OTP 23.0 起)
-spec multicast(Nodes, Module, Function, Args) -> ok
                   when Nodes :: [node()], Module :: atom(), Function :: atom(), Args :: [term()].

在节点 Nodes 上评估 apply(Module, Function, Args)。不向调用进程传递响应。multicast() 在发送 cast 请求后立即返回。除了错误的参数外,任何失败都将被静默忽略。

如果出现以下情况,multicast/4 将失败并抛出 {erpc, badarg} error 异常:

  • Nodes 不是原子的正确列表。请注意,当发生故障时,某些请求可能已经发送。也就是说,该函数可能在某些节点上被应用,也可能不被应用。
  • Module 不是原子。
  • Function 不是原子。
  • Args 不是列表。请注意,该列表在客户端未验证为正确列表。

注意

您不能对将执行 apply() 的进程做出任何假设。它可能是服务器,也可能是新生成的进程。

链接到此函数

receive_response(RequestId)

查看源码 (自 OTP 23.0 起)
-spec receive_response(RequestId) -> Result when RequestId :: request_id(), Result :: term().

等效于 receive_response(RequestId, infinity)

链接到此函数

receive_response(RequestId, Timeout)

查看源码 (自 OTP 23.0 起)
-spec receive_response(RequestId, Timeout) -> Result
                          when RequestId :: request_id(), Timeout :: timeout_time(), Result :: term().

接收对调用进程先前使用 send_request/4 发出的 call 请求的响应。

RequestId 应该是先前进行的 send_request/4 调用返回的值,并且相应的响应不应已被 receive_response()check_response/4wait_response/4 接收和处理完毕。

Timeout 设置等待响应的最长时间限制。如果操作超时,则由 RequestId 标识的请求将被放弃,然后将引发 {erpc, timeout} error 异常。也就是说,超时后将不会收到与该请求对应的任何响应。如果收到响应,则 call 操作完成,并返回结果或引发异常。可以引发的异常与 call/5 可以引发的异常相同。如果检测到无效的 RequestId 或传递了无效的 Timeout,则 receive_response/2 将失败并抛出 {erpc, badarg} 异常。

如果忽略性能,则调用下面的函数 my_call(Node, Module, Function, Args, Timeout) 等同于调用 erpc:call(Node, Module, Function, Args, Timeout)call() 可以利用选择性接收优化,从而无需从头开始扫描消息队列以查找匹配的消息。然而,send_request()/receive_response() 组合无法利用此优化。

my_call(Node, Module, Function, Args, Timeout) ->
  RequestId = erpc:send_request(Node, Module, Function, Args),
  erpc:receive_response(RequestId, Timeout).

如果 erpc 操作失败,但不知道该函数是否已应用/将要应用(即超时或连接丢失),则调用者将不会收到关于已应用函数完成时的进一步结果信息。当然,如果已应用函数明确与调用进程通信,则此类通信可能会到达调用进程。

链接到此函数

receive_response(RequestIdCollection, Timeout, Delete)

查看源码 (自 OTP 25.0 起)
-spec receive_response(RequestIdCollection, Timeout, Delete) ->
                          {Result, Label, NewRequestIdCollection} | no_request
                          when
                              RequestIdCollection :: request_id_collection(),
                              Timeout :: timeout_time(),
                              Delete :: boolean(),
                              Result :: term(),
                              Label :: term(),
                              NewRequestIdCollection :: request_id_collection().

接收对 RequestIdCollection 中保存的请求标识符对应的 call 请求的响应。RequestIdCollection 的所有请求标识符必须对应于使用 send_request/4send_request/6 发出的请求,并且所有请求都必须由调用此函数的进程发出。

Label 是与响应对应的请求标识符关联的标签。当在 请求标识符集合添加请求标识符 或使用 send_request/6 发送请求时,请求标识符会与标签关联。

receive_response/2 相比,与特定请求标识符关联的返回结果或与特定请求标识符关联的异常将包装在三元组中。此元组的第一个元素等于 receive_response/2 将会产生的值,第二个元素等于与特定请求标识符关联的 Label,第三个元素 NewRequestIdCollection 是可能被修改的请求标识符集合。 error 异常 {erpc, badarg}{erpc, timeout} 不与任何特定的请求标识符关联,因此不会被包装。

如果 RequestIdCollection 为空,则将返回原子 no_request

如果操作超时,则由 RequestIdCollection 标识的所有请求将被放弃,然后将引发 {erpc, timeout} error 异常。也就是说,超时后将不会收到与 RequestIdCollection 中的任何请求标识符对应的任何响应。receive_response/3wait_response/3 之间的区别在于,receive_response/3 会在超时时放弃请求,以便忽略任何潜在的未来响应,而 wait_response/3 则不会。

如果 Delete 等于 true,则与 Label 的关联将已从结果 NewRequestIdCollection 中的 RequestIdCollection 中删除。如果 Delete 等于 false,则 NewRequestIdCollection 将等于 RequestIdCollection。请注意,删除关联并非没有代价,并且包含已处理请求的集合仍然可以被后续调用 receive_response/3check_response/3wait_response/3 使用。但是,如果不删除已处理的关联,则上述调用将无法检测到何时没有更多待处理请求,因此您必须通过其他方式跟踪此信息,而不是依赖 no_request 返回值。请注意,如果将仅包含已处理或已放弃请求的关联的集合传递给 receive_response/3,则它将始终阻塞直到触发由 Timeout 确定的超时。

请注意,响应可能在发生 {erpc, badarg} 异常时被使用,如果是这样,则将永远丢失。

链接到此函数

reqids_add(RequestId, Label, RequestIdCollection)

查看源码 (自 OTP 25.0 起)
-spec reqids_add(RequestId :: request_id(),
                 Label :: term(),
                 RequestIdCollection :: request_id_collection()) ->
                    NewRequestIdCollection :: request_id_collection().

保存 RequestId 并通过将此信息添加到 RequestIdCollection 并返回生成的请求标识符集合,将 Label 与请求标识符关联。

链接到此函数

reqids_new()

查看源码 (自 OTP 25.0 起)
-spec reqids_new() -> NewRequestIdCollection :: request_id_collection().

返回一个新的空请求标识符集合。可以使用请求标识符集合来处理多个未完成的请求。

使用 reqids_add/3 可以将 send_request/4 发出的请求的请求标识符保存在请求标识符集合中。稍后可以通过将该集合作为参数传递给 check_response/3receive_response/3wait_response/3,从而获取该集合中与请求对应的响应。

可以使用 reqids_size/1 确定请求标识符集合中的请求标识符数量。

链接到此函数

reqids_size(RequestIdCollection)

查看源码 (自 OTP 25.0 起)
-spec reqids_size(RequestIdCollection :: request_id_collection()) -> non_neg_integer().

返回 RequestIdCollection 中保存的请求标识符的数量。

链接到此函数

reqids_to_list(RequestIdCollection)

查看源码 (自 OTP 25.0 起)
-spec reqids_to_list(RequestIdCollection :: request_id_collection()) ->
                        [{RequestId :: request_id(), Label :: term()}].

返回一个 {RequestId, Label} 元组的列表,该列表对应于 RequestIdCollection 集合中存在的所有请求标识符及其关联的标签。

链接到此函数

send_request(Node, Fun)

查看源码 (自 OTP 23.0 起)
-spec send_request(Node, Fun) -> RequestId
                      when Node :: node(), Fun :: function(), RequestId :: request_id().

等效于 erpc:send_request(Node, erlang, apply, [Fun, []])

如果出现以下情况,将失败并抛出 {erpc, badarg} error 异常:

  • Node 不是原子。
  • Fun 不是零元函数。

注意

您不能对将执行 apply() 的进程做出任何假设。它可能是服务器,也可能是新生成的进程。

链接到此函数

send_request/4

查看源码 (自 OTP 23.0 起)
-spec send_request(Node, Module, Function, Args) -> RequestId
                      when
                          Node :: node(),
                          Module :: atom(),
                          Function :: atom(),
                          Args :: [term()],
                          RequestId :: request_id();
                  (Node, Fun, Label, RequestIdCollection) -> NewRequestIdCollection
                      when
                          Node :: node(),
                          Fun :: function(),
                          Label :: term(),
                          RequestIdCollection :: request_id_collection(),
                          NewRequestIdCollection :: request_id_collection().

向节点 Node 发送异步 call 请求。

send_request/4 返回请求标识符,该标识符稍后将传递给 receive_response/2wait_response/2check_response/2,以获取调用请求的响应。除了将请求标识符直接传递给这些函数之外,还可以使用 reqids_add/3 将其添加到请求标识符集合中。稍后可以通过将该集合作为参数传递给 receive_response/3wait_response/3check_response/3,从而获取该集合中与请求对应的响应。如果您要将请求标识符保存在请求标识符集合中,则不妨考虑使用 send_request/6

如果忽略性能,则调用下面的函数 my_call(Node, Module, Function, Args, Timeout) 等同于调用 erpc:call(Node, Module, Function, Args, Timeout)call() 可以利用选择性接收优化,从而无需从头开始扫描消息队列以查找匹配的消息。然而,send_request()/receive_response() 组合无法利用此优化。

my_call(Node, Module, Function, Args, Timeout) ->
  RequestId = erpc:send_request(Node, Module, Function, Args),
  erpc:receive_response(RequestId, Timeout).

如果出现以下情况,将失败并抛出 {erpc, badarg} error 异常:

  • Node 不是原子。
  • Module 不是原子。
  • Function 不是原子。
  • Args 不是列表。请注意,该列表在客户端未验证为正确列表。

注意

您不能对将执行 apply() 的进程做出任何假设。它可能是服务器,也可能是新生成的进程。

等同于 erpc:send_request(Node, erlang, apply, [Fun,[]]), Label, RequestIdCollection)

如果出现以下情况,将失败并抛出 {erpc, badarg} error 异常:

  • Node 不是原子。
  • Fun 不是零元函数。
  • 检测到 RequestIdCollection 不是请求标识符集合。

注意

您不能对将执行 apply() 的进程做出任何假设。它可能是服务器,也可能是新生成的进程。

链接到此函数

send_request(Node, Module, Function, Args, Label, RequestIdCollection)

查看源码 (自 OTP 25.0 起)
-spec send_request(Node, Module, Function, Args, Label, RequestIdCollection) -> NewRequestIdCollection
                      when
                          Node :: node(),
                          Module :: atom(),
                          Function :: atom(),
                          Args :: [term()],
                          Label :: term(),
                          RequestIdCollection :: request_id_collection(),
                          NewRequestIdCollection :: request_id_collection().

向节点 Node 发送异步 call 请求。Label 将与操作的请求标识符关联,并添加到返回的请求标识符集合 NewRequestIdCollection。稍后可以通过将该集合作为参数传递给 receive_response/3wait_response/3check_response/3 来获取集合中与请求对应的响应。

等同于 erpc:reqids_add(erpc:send_request(Node, Module, Function, Args), Label, RequestIdCollection),但调用 send_request/6 效率稍高。

如果出现以下情况,将失败并抛出 {erpc, badarg} error 异常:

  • Node 不是原子。
  • Module 不是原子。
  • Function 不是原子。
  • Args 不是列表。请注意,该列表在客户端未验证为正确列表。
  • 检测到 RequestIdCollection 不是请求标识符集合。

注意

您不能对将执行 apply() 的进程做出任何假设。它可能是服务器,也可能是新生成的进程。

链接到此函数

wait_response(RequestId)

查看源码 (自 OTP 23.0 起)
-spec wait_response(RequestId) -> {response, Result} | no_response
                       when RequestId :: request_id(), Result :: term().

等效于 erpc:wait_response(RequestId, 0)。也就是说,轮询先前由调用进程发出的 call 请求的响应消息。

链接到此函数

wait_response(RequestId, WaitTime)

查看源码 (自 OTP 23.0 起)
-spec wait_response(RequestId, WaitTime) -> {response, Result} | no_response
                       when RequestId :: request_id(), WaitTime :: timeout_time(), Result :: term().

等待或轮询先前由调用进程使用 send_request/4 发出的 call 请求的响应消息。

RequestId 应该是先前进行的 send_request() 调用返回的值,并且相应的响应不应已被 check_response/2receive_response/2wait_response() 接收和处理完毕。

WaitTime 设置等待响应的最长时间上限。如果在 WaitTime 超时触发之前没有收到响应,则返回原子 no_response。可以根据需要多次继续等待响应,直到通过 check_response()receive_response()wait_response() 接收并完成响应。如果收到响应,则 call 操作完成,并且要么将结果作为 {response, Result} 返回,其中 Result 对应于应用函数返回的值,要么引发异常。可以引发的异常与 call/4 可以引发的异常相同。也就是说,不会引发 {erpc, timeout} error 异常。wait_response/2 在检测到无效的 RequestId 或传递了无效的 WaitTime 时,将失败并抛出 {erpc, badarg} 异常。

如果 erpc 操作失败,但不知道函数是否已应用/将要应用(即,等待时间值过大或连接丢失),则调用者不会收到有关应用函数完成时的任何进一步结果信息。如果应用函数显式地与调用进程通信,则此类通信当然可能会到达调用进程。

链接到此函数

wait_response(RequestIdCollection, WaitTime, Delete)

查看源代码 (自 OTP 25.0 起)
-spec wait_response(RequestIdCollection, WaitTime, Delete) ->
                       {{response, Result}, Label, NewRequestIdCollection} | no_response | no_request
                       when
                           RequestIdCollection :: request_id_collection(),
                           WaitTime :: timeout_time(),
                           Delete :: boolean(),
                           Label :: term(),
                           NewRequestIdCollection :: request_id_collection(),
                           Result :: term().

等待或轮询与 RequestIdCollection 中保存的请求标识符对应的 call 请求的响应。RequestIdCollection 的所有请求标识符必须对应于使用 send_request/4send_request/6 发出的请求,并且所有请求都必须由调用此函数的进程发出。

Label 是与响应对应的请求标识符关联的标签。当在 请求标识符集合添加请求标识符 或使用 send_request/6 发送请求时,请求标识符会与标签关联。

wait_response/2 相比,与特定请求标识符关联的返回结果或与特定请求标识符关联的异常将包装在一个 3 元组中。此元组的第一个元素等于 wait_response/2 将产生的值,第二个元素等于与特定请求标识符关联的 Label,第三个元素 NewRequestIdCollection 是一个可能已修改的请求标识符集合。error 异常 {erpc, badarg} 不与任何特定请求标识符关联,因此不会被包装。

如果 RequestIdCollection 为空,则返回 no_request。如果在 WaitTime 超时触发之前没有收到响应,则返回原子 no_response。可以根据需要多次继续等待响应,直到通过 check_response()receive_response()wait_response() 接收并完成响应。receive_response/3wait_response/3 之间的区别在于,receive_response/3 会在超时时放弃请求,以便忽略任何潜在的未来响应,而 wait_response/3 则不会。

如果 Delete 等于 true,则 Label 的关联将从结果 NewRequestIdCollection 中的 RequestIdCollection 中删除。如果 Delete 等于 false,则 NewRequestIdCollection 将等于 RequestIdCollection。请注意,删除关联并非没有代价,并且包含已处理请求的集合仍可用于后续调用 wait_response/3check_response/3receive_response/3。但是,如果不删除已处理的关联,则上述调用将无法检测何时没有更多待处理的请求需要处理,因此您必须以其他方式跟踪此信息,而不是依赖 no_request 返回值。请注意,如果传递仅包含已处理或已放弃请求的关联的集合给 wait_response/3,它将始终阻塞,直到触发由 WaitTime 确定的超时,然后返回 no_response

请注意,响应可能在发生 {erpc, badarg} 异常时被使用,如果是这样,则将永远丢失。