我正在构建一个简单的 gen_server 模块,它监视多个远程节点的活动
当远程节点注册时,此模块使用 erlang:monitor_node(Node, true) 监视该节点。每个节点仅注册一次(通过日志确认)
在 gen_server 的 handle_info/2 回调中,它捕获 {nodedown, Node} 消息并使用 erlang:monitor_node(Node, false) 监视节点。我希望只收到一次此消息:当远程节点关闭时。
在测试模块时,我发现当一个远程节点宕机时,会向 gen_server 发送数百条 {nodedown, Node} 消息(数量从几百到几千不等)。
为什么monitor_node会发送多条消息?我怎样才能防止这种行为?
编辑:这是(一部分)源代码
register_node(#node_info{node = NodeName} = NodeInfo) ->
case mnesia:read(node_info, NodeName) of
[] ->
monitor_node(NodeName, true),
error_logger:info_msg("node ~p registered", [NodeName]);
[_OldInfo] ->
error_logger:trace_msg("info of node ~p updated", [NodeName])
end,
mnesia:write(NodeInfo).
handle_cast({register_node, #node_info{} = NodeStatus}, Timer) ->
case mnesia:transaction(fun register_node/1, [NodeStatus]) of
{aborted, Reason} ->
error_logger:warning_msg("transaction register_node failed: ~p", [Reason]);
_ ->
ok
end,
{noreply, Timer};
handle_cast({shutdown_node, #node_info{} = NodeStatus}, Timer) ->
case mnesia:dirty_delete_object(NodeStatus) of
{aborted, Reason} ->
error_logger:warning_msg("transaction shutdown_node failed: ~p", [Reason]);
_ ->
ok
end,
{noreply, Timer};
handle_cast(Message, Timer) ->
error_logger:warning_msg("~p: received unknown message ~p", [?MODULE, Message]),
{noreply, Timer}.
handle_info({nodedown, Node}, Timer) ->
monitor_node(Node, false),
error_logger:info_msg("~p: node ~p down", [?MODULE, Node]),
mnesia:transaction(fun mnesia:delete/3, [node_info, Node, write]),
{noreply, Timer};
handle_info(Message, Timer) ->
error_logger:warning_msg("~p: received unknown message ~p", [?MODULE, Message]),
{noreply, Timer}.