公司的网站如何建设方案,WordPress读写分离,二楼平台设计,更换wordpress界面上篇写了掌握Rabbitmq几个重要概念#xff0c;从一条消息说起#xff0c;这篇来总结关于消息丢失让人头痛的事情。网络故障、服务器重启、硬盘损坏等都会导致消息的丢失。消息从生产到消费主要结果以下几个阶段如下图。①生产阶段#xff0c;生产者创建消息#xff0c;经过… 上篇写了掌握Rabbitmq几个重要概念从一条消息说起这篇来总结关于消息丢失让人头痛的事情。网络故障、服务器重启、硬盘损坏等都会导致消息的丢失。消息从生产到消费主要结果以下几个阶段如下图。①生产阶段生产者创建消息经过网络发送到rabbit服务器②消息存储阶段首先被发送到交换器然后经过路由算法到达队列等待被拉取消费③消费阶段消费者经过网络从rabbit服务器拉取消息进行消费 这三个阶段都有可能消息丢失下面一一分析。消息存储阶段正常情况下我们使用BasicPublish方法发送消息到交换器上然后路由到队列上面消费者还没进行消费此时服务器重启了队列、交换器使用默认的创建方式会发生什么答案是消息丢失。原因很简单消息在内存中没有刷盘并且他们默认是非持久化的服务重启之后它们需要重新创建消息自然就丢失还好Rabbit提供持久化的机制队列、交换器创建的时候durable属性设置为true同时消息投递模式delivery mode设置为2,则消息标记成持久化。这样可以避免服务器重启消息丢失的情况。发送阶段由于发布操作不返回任何信息给生产者那你怎么知道服务器是否已经持久化了持久消息到硬盘呢服务器可能在把消息写入磁盘前就宕机了消息因此而丢失 有。Rabbit提供两中解决方案事务但是性能会大打折扣而且会使生产者应用程序产生同步。生产环境一般不会采用另外一种方案是确认模式。也很简单消息路由给所有匹配的订阅队列中之后会异步的告之生产者。使用channel.ConfirmSelect()方法使信道开启确认模式。然后注入两个回调函数ack和nack事件。channel.BasicAcks (sender, ev) {Console.WriteLine(消息已经确认收到 ev.DeliveryTag);};channel.BasicNacks (sender, ev) {Console.WriteLine(消息未确认 ev.DeliveryTag);};
消费阶段你可能会问消费端消息怎么会丢失呢Rabbitmq提供自动和手动确认消息然后消息从队列中移除。如果autoAck为true自动确认模式服务器就会在消息发给消费端后自动将其出队。如果因为某些原因连接中断了或者你的消费端应用发生了故障那么消息就会丢失通过把AutoAck设置为false手工确认告知服务器消息已经处理了可以进行消息出队删除。 channel.BasicConsume(queue: queueName,autoAck: false,consumer: consumer);consumer.Received (model, ea) {//dosometingchannel.BasicAck(ea.DeliveryTag, false);//确认};
小结如果做了以上的处理那么消息就不会跟你躲猫猫了。这里有性能的问题消息持久化是要刷到磁盘上的会影响投递速度并且消息确认也会影响到消息投递速度。不基本上能够满足需求了。如果不能满足性能需求可以使用其他方法比如 在每次发送消息的时候都包含应答队列的名称这样消费者就可以回发应答以确认接受到了。如果消息应答未在合理时间范围内到达生产者就重新发送消息。