在线上生产环境中,RabbitMQ可能会产生消息丢失或者是投递失败的一个场景,RabbitMQ为了避免这种场景的发生,提供了两种方式来控制消息传递的可靠性。
我们可以利用RabbitMQ的两种可靠性投递模式分析产生失败的原因,从业务逻辑上解决问题。
ConSumer ACK是指消费方接收到消息数据后的确认方式,消费者从MQ中读取到消息数据后,需要返回一个确认接收的动作。
确认有三种方式:
消费者限流这个特性是非常有必要的,在前面我们提到过削峰填谷的概念,削峰填谷就是消费者限流的概念。
当系统高并发时,生产者一直在发消息数据,MQ全部存储在队列中,如果消费方没有进行限流的操作,那么大了的消费数据读取可能就会使消费者挂掉,因此就需要对消费方读取消息数据的频次进行限流,例如每秒5千个请求,我们允许消费者每秒从MQ中读取一千个请求,至少不会使消费者由于压力巨大而崩溃。
另外当消费方挂掉后,MQ中堆积了大量请求,如果没有限流,一下都让消费者读取,消费者还会挂掉。
RabbitMQ中可以对消息数据设置TTL过期时间,当消息达到过期时间后,还没有被消费者读取,MQ就会自动将消息进行清除。
RabbitMQ可以对消息设置过期时间,也可以对整个队列设置过期时间。
一个典型的应用场景:订单系统为生产者,用户下单后发送一条消息到MQ消息队列,MQ对这条消息的过期时间为30分钟,如果用户在30分内没有下单,就会被取消订单。
死信队列在任何MQ消息队列中间件中都有这个概念,在RabbitMQ中私信队列简称为DLX(Dead Letter Exchange)死信交换机,RabbitMQ与其他的MQ中间件不同,RabbitMQ有Exchange交换机的概念,因此死信队列在RabbitMQ中也被成为死信交换机。
在没有Exchange交换机概念的MQ消息队列中,通常就被成为死信队列Dead Letter Queue。
什么是死信队列?当有消息数据成为死信消息时,消息所在的队列会将消息传递到DLX死信交换机上,由死信交换机再将消息数据存放在死信交换机,等待消费者读取数据。
消息成为死信的情况:
死信队列的典型应用场景:当消息设置了TTL过期时间,超过过期时间后消息数据没有被消费,此时消息成为了死信消息,消息所在的队列会将消息传递给DLX死信交换机,再由死信交换机将数据写入到死信队列中,等待消费者读取数据。
队列如何绑定死信交换机:
需要给队列设置绑定参数,才可以绑定死信交换机,设置x-dead-letter-exchange(死信交换机名称)和 x-dead-letter-routeing-key(死信交换机的routeingkey)
当有消息成为死信消息后,队列会根据死信交换机的名称以及消息中指定的死信交换机routeingkey,将死信消息传递给死信交换机,死信交换在通过死信队列的routeingkey,将消息数据写入到死信队列。
**延迟队列:**消息进入队列后不会立即被消费,当到达指定时间后,才可以被消费。
延迟队列的典型应用场景:
以上两种常见的场景都是要求消费者一段时间后再对数据进行处理,实现该需求的方式有以下两种。
虽然延迟队列的功能很好用,但是RabbitMQ并没有延迟队列的功能,不过我们可以通过TTL+死信队列的方式实现延迟队列的功能。
TTL+死信队列实现延迟队列
用户在订单系统下单后,会发送一条消息数据到RabbitMQ的Exchange交换机,Exchange交换机将数据写入到队列中,这个队列设置TTL过期时间为30分钟,并且不允许消费者读取数据,30分钟后消息成为死信消息,此时队列将死信消息发送到DLX死信交换机,死信交换机再将消息数据传递给死信队列,然后由消费者从死信队列中读取数据并进行处理。
RabbitMQ的日志存放在/var/log/rabbitmq/[email protected]中,xxx表示主机名。
日志中包含了RabbitMQ的版本号、Erlang版本号、RabbitMQ服务节点名称、Cookie的hash值、RabbitMQ配置文件地址、内存限制、磁盘限制、默认账户guest的创建已经权限配置。
在Web控制台中有很多RabbitMQ的监控信息。
RabbitMQ常用命令
rabbitmqctl list_queues //查看队列
rabbitmqctl environment //查看环境变量
rabbitmqctl list_exchanges //查看exchange
rabbitmqctl list_queues aa messages_unacknowledged //查看未被确认的队列
rabbitmqctl list_users //查看用户
rabbitmqctl list_queues name memory //查看单个队列的内存使用
rabbitmqctl list_connections //查看链接
rabbitmqctl list_queues name messages_ready //查看准备就绪的队列
rabbitmqctl list_consumers //查看消费者信息
在使用任何消息中间件的过程中,难免会出现某条消息异常丢失的情况。对于RabbitMQ而言,可能是因为生产者或消费者与RabbitMQ断开了连接,而它们与RabbitMQ丈采用了不同的确认机制;也有可能是因为交换器与队列之间不同的转发策略;甚至是交换器并没有与任何队列进行绑定,生产者又不感知或者没有采取相应的措施;另外RabbitMQ本身的集群策略也可能导致消息的丢失。这个时候就需要有一个较好的机制跟踪记录消息的投递过程,以此协助开发和运维人员进行问题的定位。
在RabbitMQ中可以使用Firehose和rabbitmq_tracing插件功能来实现消息追踪。
trace交换机默认自带,需要开启才可以使用:rabbitmqctl trace_on