erlang的gen_server call默认有超时, 若在指定的超时内没有收到返回. 则会exit(timeout).node
gen.erl:160async
do_call(Process, Label, Request, Timeout) when is_atom(Process) =:= false -> Mref = erlang:monitor(process, Process), %% OTP-21: %% Auto-connect is asynchronous. But we still use 'noconnect' to make sure %% we send on the monitored connection, and not trigger a new auto-connect. %% erlang:send(Process, {Label, {self(), Mref}, Request}, [noconnect]), receive {Mref, Reply} -> erlang:demonitor(Mref, [flush]), {ok, Reply}; {'DOWN', Mref, _, _, noconnection} -> Node = get_node(Process), exit({nodedown, Node}); {'DOWN', Mref, _, _, Reason} -> exit(Reason) after Timeout -> erlang:demonitor(Mref, [flush]), exit(timeout) end.
显然, 若是等待一段时间后, 没有收到消息, 有两种可能.atom
若是捕获了timeout异常, 对方又返回了消息, 该消息仍是会发送到调用者的pid信箱中.
如果一个gen_server, 须要在handle_info中处理(建议忽略)该消息. 避免由于没有在handle_info 中处理{Mref, Reply}消息而崩溃.设计
超时不意味着调用失败, 可能调用成功, 只是请求超时. 能够使用幂等接口设计应对超时失败.code
假设有以下调用链.
a_node -5000ms> b_node -5000ms> outer_services
若outer_services, 即不可控的外部服务超时, 会致使a_node, b_node的call所有超时. 建议在b_node上对外使用较小的超时时间. 避免外部超时让整条调用链都出现超时错误.server