RabbitMQ真实生产故障问题还原与分析(二)


风晓
风晓 2023-12-31 09:22:12 51986 赞同 0 反对 0
分类: 资源
接上一篇RabbitMQ真实生产故障问题还原与分析(一)

3、    第三个问题原因分析

还是查看抓包信息

 

Basic.Reject: 客户端发送Basic.Reject方法请求,表示无法处理消息,拒绝消息,此时的requeue参数为true,将消息返回原来的队列;

Basic.Deliver: 服务端调用Basic.Deliver方法,和第一次Basic.Deliver方法不同的是,此时的redeliver参数为true,表示重新投递消息到监听队列的消费者,然后这两步会一直重复下去。

RabbitMQ消息监听程序异常时,consumer会向rabbitmq server发送Basic.Reject,表示消息拒绝接受,由于Spring默认requeue-rejected配置为true,消息会重新入队,然后rabbitmq server重新投递。就相当于死循环了,所以容易导致消费端资源占用过高,特别是TCP连接数、线程数、IO飙升,如果个别程序带事务或数据库操作等连接资源得不到释放也会占满,导致应用假死状态(出现问题的时候,查看问题应用出现大量的connection timeout错误报错日志)。

因此针对性的,有些业务场景(不强调数据强一致性的场景,比如日志收集)可以设置default-requeue-rejected: false即可。

factory.setDefaultRequeueRejected(false);

  会根据异常类型选择直接丢弃或加入dead-letter-exchange中。

 

消费者端正确的使用手动确认示例结构代码,很重要!

 

复制代码
try {
    // 业务逻辑。
}catch (Exception e){
    // 输出错误日志。
}finally {
    // 消息签收。
}
复制代码

 

  

4、    验证队列设置最大长度限制

 

设置queueLengthLimit队列最大长度限制 x-max-length=5

 

 

 

生产者原本想要生产10条消息

 

 

 

 

由于受到队列最大长度限制,实际上只有5条入队列里面。

 

消费者拿出来的消息,仅有5条,从NO.6~NO.10

 

 

 

 

改变消费者程序,让生产者一直产生消息,消费者消费速度明显赶不上生产者的生产速度

 

 

 

从消费端来看消息是随机性入队的,队列里面一直最多5条消息,发再多也进不了,消息者和生产者也不会发生什么异常,只是消息会随机性丢失(并没有全部入队)。

 

 

运行情况良好,除了消息没有全部入队列 ,没有出现异常情况

 

 

消费比较慢,本机器CPU和内存各项指标正常,没有异常。

 

搞一个异常情况出现unack,最大队列长度限制,是不算unack数量的,如下图所示

 

 

 

异常之后,此观察MQ监控管理后台

 

生产者不停一直在生产消息,运行30分钟,观察生产者应用也是正常的的,就是消息入不了队列。

 

 

 

 

5、  检查实际的业务端代码

 

再看我们业务系统消费端代码,消费端各种不规范写法都有,以下例举几个典型

1、手动签收有ACK,但是没有try-catch-finally结构,消费端业务代码如下:

 

 

2、有try-catch-finally结构,但是deliverTag是一个固定值0,一样的会出问题。

 

 

3、自动签收确认的,大量消息的时候,容易搞死消费端应用。

 

 

 

 

6、    总结

  • 生产环境不建议使用自动ack模式,这样会使QOS无法生效。
  • 在使用手动ack的时候,需要非常注意消息签收,业务代码使用try-catch-finally处理结构,防止业务代码异常时无法签收。
  • 规范约束mq客户端代码,正确的使用Rabbitmq配置。
  • 不同业务项目设置不同的vhost可以隔离一些影响,提升rabbitmq资源使用。
  • 考虑设置dead-letter-exchange,当设置了 requeue=false时,可以放入dead-letter-exchange,可以快速排查定位问题。
  • Exchange和队列的最大长度限制可以是限制消息的数量(参数:x-max-length),或者是消息的总字节数(总字节数表示的是所有的消息体的字节数,忽略消息的属性和任何头部信息),又或者两者都进行了限制,两者取小值生效,只有处于ready状态的消息被计数未被确认的消息不会被计数受到limit的限制。最大队列设置可以限制生产端,但会造成消息丢失风险,最大消息数量限制,不能完全解决队列阻塞问题。
  • 尽量使用Direct-exchange,Direct 类型的 Exchange 投递消息是最快的。
    • Direct:处理路由键,需要将一个队列绑定到交换机上,要求该消息与一个特定的路由键完全匹配。这是一个完整的匹配。如果一个队列绑定到该交换机上要求路由键为“A”,则只有路由键为“A”的消息才被转发,不会转发路由键为"B",只会转发路由键为“A”;
    • Topic:将路由键和某模式进行匹配。此时队列需要绑定要一个模式上。符号“#”匹配一个或多个词,符号“*”只能匹配一个词;
    • Fanout:不处理路由键。只需要简单的将队列绑定到交换机上。一个发送到该类型交换机的消息都会被广播到与该交换机绑定的所有队列上;
    • Headers:不处理路由键,而是根据发送的消息内容中的 headers 属性进行匹配。在绑定 Queue 与 Exchange 时指定一组键值对;当消息发送到 RabbitMQ 时会取到该消息的 headers 与 Exchange 绑定时指定的键值对进行匹配;如果完全匹配则消息会路由到该队列,否则不会路由到该队列。

如果您发现该资源为电子书等存在侵权的资源或对该资源描述不正确等,可点击“私信”按钮向作者进行反馈;如作者无回复可进行平台仲裁,我们会在第一时间进行处理!

评价 0 条
风晓L1
粉丝 1 资源 2038 + 关注 私信
最近热门资源
统信桌面专业版【全盘安装UOS系统】介绍  28
银河麒麟桌面操作系统备份用户数据  22
银河麒麟桌面操作系统安装佳能打印机驱动方法  17
银河麒麟桌面操作系统 V10-SP1用户密码修改  16
最近下载排行榜
统信桌面专业版【全盘安装UOS系统】介绍 0
银河麒麟桌面操作系统备份用户数据 0
银河麒麟桌面操作系统安装佳能打印机驱动方法 0
银河麒麟桌面操作系统 V10-SP1用户密码修改 0
作者收入月榜
1

prtyaa 收益393.62元

2

zlj141319 收益217.55元

3

1843880570 收益214.2元

4

IT-feng 收益208.98元

5

风晓 收益208.24元

6

777 收益172.71元

7

Fhawking 收益106.6元

8

信创来了 收益105.84元

9

克里斯蒂亚诺诺 收益91.08元

10

技术-小陈 收益79.5元

请使用微信扫码

加入交流群

请使用微信扫一扫!