保证队列中有尽量少的消息堆积
当队列中堆积过多消息时会给内存带来极大的压力,为了释放内存Rabbit会将消息刷至磁盘,当有大量消息需要刷新至磁盘时,会造成队列的阻塞进而影响系统吞吐量。
当你的rabbit为集群部署时,重启的时候会重新建立索引,并且在集群中同步消息,消息量越多,这个时间也就越久。
所以尽量保证发送至队列的消息能够在一定时间内及时被消费掉。
启用懒惰队列功能
lazy queue会将生产者的消息持久化到磁盘中而不驻留在内存,只有当消息需要被消费时才会重新加载到内存,避免了消息堆积,会尽量避免内存过高导致的问题。
而对于持久化消息所造成的额外工作,这里引用一段朱小厮博客中的一段话:
惰性队列会将接收到的消息直接存入文件系统中,而不管是持久化的或者是非持久化的,这样可以减少了内存的消耗,但是会增加I/O的使用,如果消息是持久化的,那么这样的I/O操作不可避免,惰性队列和持久化消息可谓是“最佳拍档”。注意如果惰性队列中存储的是非持久化的消息,内存的使用率会一直很稳定,但是重启之后消息一样会丢失。
然而当你需要较高的性能--队列中消息较少,或者设置了队列最大长度时应该禁用队列的lazy属性。
设置max-length或者TTL
TTL为消息过期时间,max-length为队列最大长度。对于那些吞吐量优先,允许消息丢失的应用程序最好设置这两个属性避免消息堆积来保证内存正常。
队列数量
rabbit中的队列是单线程的,适当使用多个队列和消费者可以增加吞吐量。但不要设置太多的队列,如果底层节点上的队列与内核一样多,则可以实现最佳吞吐量。
自动删除不使用的队列
客户机连接可能会失败,并可能会留下未使用的资源(队列),而留下许多队列可能会影响性能。自动删除队列有三种方法。
1.可以在队列上设置TTL策略,例如,28天的TTL策略会删除28天未使用的队列。
2.设置了自动删除属性的队列在其最后一个消费者取消或连接关闭(或丢失与服务器的TCP连接)时被删除。
3.独占队列只能被声明他的连接所使用,当声明连接关闭或消失时(例如,由于底层TCP连接丢失),将删除独占队列。
设置优先级队列的优先级上限
rabbit由Erlang开发,每个优先级使用Erlang VM上的一个内部队列,该队列会占用一些资源。在大多数情况下,不超过5个优先级就足够了。
消息的大小与类型
一般来说我们发送给broker的消息都是对象序列化后的json字符串,大小为几百字节,并不需要担心,只是不要用rabbit来传输大文件即可。
消息确认机制
如果不需要确保消息不丢失,把消息确认机制关掉可以提高吞吐量。
如果开启了消息确认,接收到重要消息的消费应用程序在完成对这些消息的任何处理(工作程序崩溃、异常等)之前都不应该确认消息。
发布确认类似于消息确认机制,服务器在收到来自发布者的消息时进行ack。发布确认对性能也有影响。但是如果生产者需要确保消息到达broker,那么它是必需的。
所有未确认的消息必须驻留在服务器的内存中。如果有太多未确认的消息,就会耗尽内存。限制未确认消息的有效方法是设置客户端预取值,即prefetch_count的值(下面会有介绍)。
持久化消息与队列
如果你期望消息不丢失,那么需要将队列声明为durable的,并且发送的消息也要声明为persistent(二者必须同时设置)这样在broke发生故障重启后消息才不会丢失。
Prefetch预取值
prefetch属性用来定义一次可以给消费者发送多少条消息,设置合适的值会使消费者得到有效利用。默认情况下,预取值为无限大,意味着消费者尽可能的接收生产者的消息,预取值限制了消费者在确认消息之前可以接收多少消息。所有预获取的消息都将从队列中删除,并且对其他消费者不可见。举个栗子,假如prefetch_count值设为10且消费者开启acknowledge,获取10个消息后,rabbitmq不再将队列中的消息推送过来,当对消息处理完后(即对消息进行了ack,并且有能力处理更多的消息)再接收来自队列的消息。
预取值过小会降低rabbit的性能;预取值过大时当存在多个消费者,可能会导致某个消费者负载过高,而其他的消费者处于空闲状态。
关于预取值的建议:如果消费者数量不多并处理迅速,可以将预取值设的大一些,保证消费者充分使用。如果消费者数量较多,且处理时间较短,可以将值取的比上个情况下稍小一些。如果消费者较多且处理时间较长,建议将预取值设为1,以便各个消费者“负载均衡”。具体的数目可以在机器上进行测试,然后选取合适的值。总之,尽量不使用系统默认的预取策略。
最后最重要的一点是,预取值只有在手动确认模式下才生效。
HIPE
配置文件开启HIPE后会提高rabbit的吞吐量,但是会大幅度延长rabbit的启动时间,如果系统需要做高可用的话,建议不要开启。
参考:lovisa johanssan --RabbitMQ Best Practice