不要触发流控机制
关于内存报警
- 在默认配置情况下,rabbitmq的使用内存超过机器内存的40%,会触发内存报警,同时阻塞所有发布消息的连接,一旦内存报警清除(如:消息被写入硬盘或者被消费者消费),服务就会恢复正常。
- 默认内存阙值是机器内存的40%,但并不会阻止rabbitmq使用超过40%的内存,这仅仅是阻塞生产者。
- 内存阙值可以通过vm_memory_high_watermark, 字段进行调整
当消息发布速度大于消费速度时
- 一般的,当消息发布速度大于消费速度时,会引起大量的任务堆积,导致报警,触发流控。
- 这个时候,RabbitMQ服务端接收发布来的消息会变慢,使得进入队列的消息减少(可以观察rabbitmq web界面incoming 的速度变化)
- 消息的推送频率大幅下降,等待下一次推送的时间会越来越长。
- 需要做好设计。发送速率和接收速率保持平衡, 而不至于导致任务堆积
如何保证消息不被丢失
RabbitMQ 的消息默认存放在内存上面,如果不特别声明设置,消息不会持久化保存到硬盘上面的,如果节点重启或者意外crash掉,消息就会丢失。
保证消息持久化需要的必要条件,缺一不可:
1. Exchange 设置持久化:durable:true 2. Queue 设置持久化 3. message 持久化发送 。发送消息设置发送模式deliveryMode=2代表持久化消息。 即在消息的投递(publish), 传送(exchange),入队列(queue)的过程中都需要一致保持消息持久化。
消息ack 机制。默认情况下,消费者是自动确认消息投递成功的,需要设置为手动确认消息。自动确认意味着消息发送给消费者后立即确认,这样存在丢消息的可能,而且也不利于消息回推重试。
消息什么时候需要持久化
1. 消息本身在publish的时候就要求消息写入磁盘;
2. 内存紧张,需要将部分内存中的消息转移到磁盘;
消息什么时候会刷到磁盘?
- 写入文件前会有一个Buffer,大小为1M(1048576),数据在写入文件时,首先会写入到这个Buffer,如果Buffer已满,则会将Buffer写入到文件(未必刷到磁盘);
- 有个固定的刷盘时间:25ms,也就是不管Buffer满不满,每隔25ms,Buffer里的数据及未刷新到磁盘的文件内容必定会刷到磁盘;
- 每次消息写入后,如果没有后续写入请求,则会直接将已写入的消息刷到磁盘:使用Erlang的receive x after 0来实现,只要进程的信箱里没有消息,则产生一个timeout消息,而timeout会触发刷盘操作。