【发布时间】:2018-02-09 08:48:32
【问题描述】:
我的 rabbitmq 客户端遇到了赛车状况问题。我的服务有多个实例侦听单个队列,将接收到的消息存储到数据库中。
当它们同时重新启动时,我有时会看到消息被重新传递并存储在数据库中两次。这通常在客户端通过检查相关 ID 是否已存储在数据库中来处理。这在 99.9% 的时间里都有效(我每天处理 5 条消息,每天发生一到两次)。
正如我所说,我怀疑是赛车状况造成的。我想我的第一条消息仍在处理中时再次收到消息。所以当我检查时我没有看到它存储在数据库中,最后存储了两次。
我不应该认为这不是问题,而是一直困扰着我,因为我无法真正解释发生了什么。
我怀疑它在我重新启动服务时发生。我想我与队列断开连接,而我仍在处理消息,触发 rabbitmq 再次重新传递到另一个尚未关闭的实例。
我想要做的是当我停止服务时
- 告诉rabbitmq我不想再收到消息了
- 等待所有当前正在处理的消息完成
- 发送ack / nacks
- 关机
现在我首先注销收到的事件
_consumerServer.Received -= MessageReceived;
然后我正在处理频道和服务器
if (_channel != null)
{
_channel.Close();
_channel.Dispose();
}
if (_connectionServer != null)
{
_connectionServer.Close();
_connectionServer.Dispose();
}
【问题讨论】:
-
使用像 ZooKeeper 这样的分布式锁系统怎么样?
-
我对ZooKeeper不熟悉,但我会看看
-
我认为你必须手动实现,通过使用一些线程同步结构(如
Monitor.Wait\Pulse)来确保MessageReceived中的所有处理在关闭之前完成。或者只是不允许向数据库插入重复项(通过唯一索引或通过仔细的 sql 查询)。
标签: c# rabbitmq windows-services