发送消息时确保 gen_fsm/gen_server 进程存在

Posted

技术标签:

【中文标题】发送消息时确保 gen_fsm/gen_server 进程存在【英文标题】:Ensure that gen_fsm/gen_server process exists while sending a message 【发布时间】:2013-07-22 20:06:41 【问题描述】:

在 Erlang 中最推荐的方法是在向它发送消息/事件之前确保某个进程存在?在我的场景中,我在第一次出现消息时开始处理,然后它保持活动状态。在继续传递更多消息的同时,我首先尝试使用相同的名称启动进程以确保它已启动,如下所示(使用 gen_fsmsimple-one-for-one 重启场景):

%% DeviceId - process name

heartbeat(ApplicationKey, DeviceId, Timeout) ->
    ensure_session_started(ApplicationKey, DeviceId, Timeout),
    gen_fsm:send_event(DeviceId, heartbeat, Timeout).

ensure_session_started(ApplicationKey, DeviceId, Timeout) ->
    case session_server_sup:start_child(ApplicationKey, DeviceId, Timeout) of
        ok, _Pid -> ok, running;
        error, already_started, _ -> ok, running;
        error, Error -> erlang:throw(error, failed_to_start_session, Error)
    end.

我相信这个解决方案并不完美,可能会有一些开销,但仍然相信它比使用erlang:is_process_alive 更不容易出现竞争情况。我对吗?任何想法如何改进它?

【问题讨论】:

【参考方案1】:

你是对的, erlang:is_process_alive/1 方法在这种情况下是无用的,因为竞争条件。

你的例子是可行的,我在野外看到过几次。请注意,它不保证会处理该消息。为确保这一点,您需要监控您的接收器并从中获得确认。这是在 gen_server:call/2 中完成的。

【讨论】:

【参考方案2】:

使用gen_fsm:sync_send_event/2,3,您可以将事件发送到您的 FSM 并等待响应。所以你可以告诉你的调用进程它的消息已经被接收到了。

【讨论】:

以上是关于发送消息时确保 gen_fsm/gen_server 进程存在的主要内容,如果未能解决你的问题,请参考以下文章

在数字签名安全模型中,如何确保公钥来自发送者?

如何确保消息正确地发送至RabbitMQ? 如何确保消息接收方消费了消息?

作业5散列函数

2016012093 马雪 散列函数的应用及其安全性

四种策略确保 RabbitMQ 消息发送可靠性!你用哪种?

Rabbit MQ 阻止调用以发送消息并确保它为超出消息限制或超出消息大小限制提供正确的回复代码