我有多个进程作为一个系统一起工作。其中一个过程充当主要过程。当系统关闭时,每个进程都需要向主进程发送通知(通过RabbitMQ)然后退出。该程序是用C ++编写的,我正在使用AMQPCPP library。
问题是有时通知未成功发布。我怀疑退出太快是问题的原因,因为AMQPCPP库在关闭连接之前没有机会发送消息。
AMQPCPP的文档说:
发布的消息通常不会被服务器确认,并且RabbitMQ不会发回报告以通知您消息是否已成功发布。因此,publish方法不会返回Deferred对象。
只要没有通过Channel :: onError()方法报告错误,您就可以安全地假设您的消息已经发送。
当您发布许多邮件时,这当然会成为一个问题。如果您在中途收到错误,则无法确定向代理发送了多少消息以及应该重新发布多少消息。如果这很重要,您可以将发布命令包装在事务中。在这种情况下,如果发生错误,RabbitMQ会自动回滚事务,并且实际上没有消息发布。
如果没有RabbitMQ服务器的确认,很难确定何时退出流程是安全的。此外,使用交易声音就像过度通知一样。
有人可以建议一个简单的解决方案,以便在不丢失最后通知的情况下正常关闭吗?
答案 0 :(得分:0)
事实证明,我可以在关闭频道时设置回调。因此,当所有通道成功关闭时,我可以安全地关闭连接。我不完全确定此过程是否确保所有传出消息都已发布。但是从测试结果来看,问题似乎已经解决了。
class MyClass
{
...
AMQP::TcpConnection m_tcpConnection;
AMQP::TcpChannel m_channelA;
AMQP::TcpChannel m_channelB;
...
};
void MyClass::stop(void)
{
sendTerminateNotification();
int remainChannel = 2;
auto closeConnection = [&]() {
--remainChannel;
if (remainChannel == 0) {
// close connection when all channels are closed.
m_tcpConnection.close();
ev::get_default_loop().break_loop();
}
};
auto closeChannel = [&](AMQP::TcpChannel & channel) {
channel.close()
.onSuccess([&](void) { closeConnection(); })
.onError([&](const char * msg)
{
std::cout << "cannot close channel: "
<< msg << std::endl;
// close the connection anyway
closeConnection();
}
);
closeChannel(m_channelA);
closeChannel(m_channelB);
}