检查实际的业务端代码
再看我们业务系统消费端代码,消费端各种不规范写法都有,以下例举几个典型
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 绑定时指定的键值对进行匹配;如果完全匹配则消息会路由到该队列,否则不会路由到该队列。
