消息服务实践

本文探讨了消息服务在生产者和消费者端的最佳实践,包括维持连接、持久化、确认机制、错误处理和扩展性。生产者端强调了持久化、确认机制的使用和错误日志记录;消费者端关注连接的维护、顺序性、确认模式、prefetch值的设定以及幂等性设计。错误处理部分讨论了nack、reject和不做操作的区别,以及如何处理消息积压和过期失效问题。此外,提出了动态添加消息的挑战及解决方案。
摘要由CSDN通过智能技术生成

生产者端

同一服务下,维护生产者在一个vhost下的connection连接和channel,会断线重连

由于TCP的开启和关闭都是昂贵的开销,而且会存在慢启动的问题,不能一上来就传送大量的数据。假设每次发送消息都要重新建立一个connection,那如果同一时间发送消息的频率过于频繁,或者消息量过大,就可能出现异常(可用for循环连发消息1000次验证:1,每次都建立connection和channel,2,建立一次connection,每次发消息都建立channel,3,建立一次connection和channel,直接发送消息)。

因此,每个服务在启动时,即建立好所有vhost下的connection连接和channel。当需要发送消息的时候,直接用对应的channel去声明exchange和Publish即可。connection和channel在服务器运行的过程中不会主动close,当服务发生异常时会尝试主动close。

持久化和ack

从生产者发送消息到rabbitmq把消息发给队列,过程中的每个时刻都可能丢消息。

首先,为了确保rabbitmq不丢消息,需要持久化queue的元信息和队列中的消息。前者需要在assertExchange的时候讲durabel设为true,后者需要把publish方法里options里的persistent设为true(或者把deliveryMode设为2,但persistent的优先级高于deliveryMode)。这样,RabbitMQ就会将持久化消息写入磁盘上的持久化日志文件,如果rabbitmq挂了之后再次重启,也会恢复queue和这个queue里的数据。当然,写入磁盘有开销,持久化会降低rabbitmq的性能,但可以有效防止rabbitmq挂了之后丢消息。可以根据项目需求来灵活运用,只对内容重要、难以找回,不易再次触发的消息开启持久化。

其次,要处理生产者丢消息的情况。一般有两种做法,使用rabbitmq事务,或者引入confirm机制。事务是同步的,confirm机制是异步的。前者会大大降低性能,根据rabbitmq的官网,吞吐量会以250倍的因子减少。故而后者是通常推荐的做法。

引入confirm机制后,对于可路由消息,当所有队列都接受消息时,rabbitmq将发送basic.ack给生产者。对于路由到持久队列的持久性消息,这意味着持久化到磁盘。目前前端所有的消息都是routed的,即是知道要发送到哪个路由的。

开启持久化后会有延迟。如果没有空闲的队列,RabbitMQ消息会存储在一段时间(几百毫秒)之后批量传递消息到磁盘,以最小化同步的消息数。这意味着在恒定负载下,basic.ack的延迟可以达到几百毫秒。因此,需要异步发送消息,并尽量把发消息作为方法中的最后一环,从而不会block接下来的行为。

尽量对所有的生产者都开启confirm机制,因为它本身是异步的,对性能影响较小。

var open = require(
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值