RabbitMQ 生产者-消息丢失 之 场景分析

生产者-消息丢失 之 场景分析

  • 生产者消息丢失的场景
    • 消息无法到达RabbitMQ
      • 连接断开
      • 信道关闭
    • RabbitMQ无法将消息入队
      • 交换机不存在
      • 无匹配队列
    • 消息过期丢失
    • 消息丢失场景对比

生产者消息丢失的场景

       生产者发送消息的流程如下:首先生产者和RabbitMQ服务器建立连接,然后创建信道,通过信道发送消息给RabbitMQ服务器,RabbitMQ服务器接收到消息后交由交换机进行消息存储,交换机根据不同策略将消息路由到指定队列中。在此过程中,可能会存在以下消息丢失的场景:

  • 在发送消息的过程中生产者和RabbitMQ服务连接断开
  • 在发送消息的过程中信道关闭
  • RabbitMQ接收到消息后但是无法匹配到合适的交换机进行消息处理
  • 交换机接收到消息后无法将消息按照相关策略路由到指定队列中
  • 消息存放到队列中,但是一致没有消费者消费,并且消息存放时间超过了设置的过期时间,消息被过期丢失

       按照上述消息丢失场景可以划分为三种情况:消息无法到达RabbitMQ、RabbitMQ无法将消息存放的队列中、消息过期丢失

消息无法到达RabbitMQ

       上述已经分析了消息无法从生产者发送给你RabbitMQ的两种情况,分别是连接端口和信道关闭。

连接断开

测试方法:生产者重复发送消息,在消息发送的过程中将RabbitMQ服务停止。
测试结果:生产者提示异常

Exception in thread “main” com.rabbitmq.client.AlreadyClosedException: connection is already closed due to connection error;

       通过上述测试内容不难发现,如果连接断开则生产者将在消息发送的过程中提示异常,因此可以通过捕获异常的方式进行消息存储,避免消息丢失。

信道关闭

测试方法:生产者重复发送消息,开启一个线程,在一段时间后将信道关闭。
测试结果:生产者提示异常

Exception in thread “main” com.rabbitmq.client.AlreadyClosedException: channel is already closed due to clean channel shutdown; protocol method: #method(reply-code=200, reply-text=OK, class-id=0, method-id=0)

       通过上述测试内容发现信道关闭和连接断开类似,生产者都能接收到异常信息。本测试也可以侧面说明,信道是非线程安全的,不建议去在不同线程间使用相同信道。由于信道是逻辑连接,因此信道关闭后可以通过连接再次创建信道。

RabbitMQ无法将消息入队

       这种消息丢失的场景是指消息被RabbitMQ接收到了,因此针对生产者而言,消息已经成功发送了。单论消息发送的职责,生产者已经完成了;但是不可否认的情况话,RabbiMQ合法的接收到消息后已经可能存在消息丢失的情况,例如处理该消息的交换机不存在,消息无法按照规则路由到相关队列中。

交换机不存在

测试方法:消息发送的过程中写一个不存在的路由名称。
测试结果:生产者提示异常:

Exception in thread “main” com.rabbitmq.client.AlreadyClosedException: channel is already closed due to channel error; protocol method: #method(reply-code=404, reply-text=NOT_FOUND - no exchange ‘sample_exchangetest’ in vhost ‘/’, class-id=60, method-id=40)

       虽然生产者提示了该条异常,但是这是在第二次发送信息时提示的异常,也就是说在第一次给不存在的交换机发送消息时,生产者并未抛出异常,当第一条消息发送后,由于不存在相关交换机,则生产者将将该发送消息的信道关闭,进而在第二次通过该信道发送消息的时候提示信道关闭异常.

无匹配队列

测试方法:消息发送的过程中设置一个无法匹配到队列的路由键。
测试结果:生产者持续发送消息,未出现异常,但是队列中不存在生产者发送的消息。
       当消息按照设置规则发送给相关交换机,但是交换机无法根据消息携带的路由键匹配到队列中,此时消息无法存储到队列中,消费者无法消费这些消息。值得注意的是,无匹配队列这种情况发生时,并未向上述几种情况生产者出现异常提示。所以无论生产者无法通过异常监听的方式得知消息发送失败!为此RabbitMQ提供了mandatory属性配置实现当队列不可达时生产者接收到返回消息。mandatory详细讲解见后文。

消息过期丢失

测试方法:在发送消息的过程中设置过期时间。队列无消费者监听,等到消息过期。
测试结果:消息过期丢失,生产者无法获取消息丢失事件。
消息的过期时间设置见: RabbitMQ 过期时间(TTL)

消息丢失场景对比

场景 是否发生异常
连接断开
信道关闭
交换机不存在
无匹配队列
消息过期丢失

你可能感兴趣的:(rabbitmq)