MQ可靠消息传递背景知识
消息队列是大多数分布式系统的核心,给服务/微服务的异步处理提供支持。
当异步执行任务时,可以将任务写入队列,其他组件(线程、进程)读取到该任务后运行。消息送达处理任务队列时,我们希望它能够被快速读取,异步处理。在提高可靠消息传递前提下(我们希望确保消息发送完成后,即使节点或系统崩溃,该消息也将永久排队并最终将被传递)测试如下几种常见MQ系统:
Mongo DBRabbitMqActiveMQKafka系统通过以下方式确保消息高可靠性:
将消息持久保存到磁盘通过网络复制消息MQ满足条件
- 作为发送方,我们希望一旦消息发送成功,消息就会得到处理。当然,不可能达到100%成功,将消息丢失可能性降到最低:消息在服务器重启不丢失,消息应保留在持久性硬盘中;服务器故障消息不丢失,消息应复制到其他服务器后才发送。
- 作为接收方,接收一条消息,确认该消息已成功处理。消息接收不应立刻将消息从队列中删除,因为接收方可能随时崩溃(包括接收后,处理之前)。可能导致消息被处理两次(例如,接收方在处理之后 ,确认之前崩溃)。
- 确认一条消息成功处理。对于同一次消息传递,消息处理应该是幂等的,即两次处理消息应该不会造成任何问题(业务保证重新发送了某个消息,不会造成任何损害)。
测试及结果
测试维度:
- 消息吞吐量/秒:队列平均速度,即每秒可以发送多少条消息,每秒可以接收和确认多少条消息
- 处理延迟95th percentile (1分钟窗口内):消息发送和消息接收之间经过的时间(以毫秒为单位)。也就是说,代理将消息从发送方传递到接收方的速度有多快
- 发送延迟95th percentile (1分钟窗口内):完成一条消息发送需要多长时间,才确保消息安全地保留在群集中。类似响应客户的http请求“已收到邮件”。(95th percentile=X,表示95%的数值都比X低或高)
测试过程:
测试队列部署在3个相同集群节点上,集群自动处理故障。测试使用了1到8个客户端节点(客户端和接收方节点的数量始终相同),每个节点运行1到25个线程,每个线程尝试以每一批为1到10条(消息大小随机)成批发送定量消息(每一批最多100或1000条消息)。接收节点接收消息后,确认消息(队列删除该消息)。当一分钟内未收到任何消息时,测试结束。
- sender 应该是同步的,也就是说,send完成时,我们要确保消息发送成功。
- receiver应该从队列中接收消息,如果receive节点崩溃,则应将消息返回到队列并重新发送。
- ACK确认消息的传递和处理。ACK可以是异步的,不必确保ACK成功。
测试硬件:
测试服务器才有AWS m4.2xlarge EC2 实例;每个这样的实例8个虚拟CPU,32GiB的RAM和SSD存储。所有实例均在同一可用区(eu-west-1)中启动。