Alice和Bob是两个完全独立的系统,现在Alice有一条消息需要发送给Bob,Bob接收到消息后需要进行一系列的处理,然后得到一个最终结果。从Alice发出消息,到Bob对消息进行有效处理,期间可能出现各种各样的状况,导致Alice所发出的消息没有被Bob有效处理。Alice静静的想了一下,从她发送消息开始,可能出现的状况有:
- 网络不好,Bob始终接收不到消息;
- Bob不在;
- Bob收到消息了,但是抽风死掉了;
不管是什么状况,Alice还是希望Bob可以有效的处理她发送的消息,所以她重发,重发,再重发,最后Alice累死在重发的路上。。。
Duang一下,上帝出现了,救活了Alice,并给了她一个消息队列,然后Alice和Bob有可以一起愉快的玩耍了。
故事讲完了,最近在项目中用到了消息队列,对在使用过程中考虑的因素总结如下:
1. 并发性
虽说消息队列主要是做消息的转发,不涉及逻辑处理,所以对单条消息的处理消耗并不大,但不管怎样始终还是有上线的。所以在选择消息队列时也需要关注接收消息的并发数,以及能够同时承载的生产者、消费者总数量。
2. 可靠性
消息队列并不产生消息,而是接收生产者产生的消息,并转发给对应的消费者,在消息的接收、转发过程中就存在以下可靠性问题:
消息接收的可靠性(这也和消息接收的并发性相关)
消息队列应该快速、可靠的接收来自生产者产生的消息,如果生产者往消息队列发送消息时延太大,或者还需要不断的重试,那消息队列存在的价值就不大了(因为它会成为整个系统中新的瓶颈)。
消息存储的可靠性
消息队列接收到消息后,对应消费者并不一定能够及时对消息进行消费,此时就需要消息队列对消息进行暂存。而且消息队列本身也存在宕机的可能性,无论是消费者的问题,还是消息队列本身的问题,只要是消息队列确认接收到的消息就不应该丢失,而且必须保证消息最终被消费者处理完成。
消息传递的可靠性
消息队列接收到来自生产者的消息后,在送达消费者前,可能还需要经过一系列的路由中转等;以及将消息转发给对应消费者,都应该有一定的机制来保证消息在传输过程中不丢,同时应该由消费者来最终确认消息处理完成。这里也就涉及消息队列支持的消息接收确认方式,一般包括自动确认方式、客户端确认方式、事物方式等。其中客户端确认方式和事物方式,消费者可以在合适的时机向消息队列确认已经接收到消息(可以在处理完成后才向消息队列确认),从而确保生产者发出的消息被有效处理。
PS:由于消费者自身的问题,可能存在消息处理完成,但向消息队列确认接收到消息失败的情况。这次消息队列会重发消息,因此消费者应该保证多次接收到相同的消息,最终处理结果应该一致的。
3. 重发机制
对于消息队列的重发机制,需要考虑的问题主要有:
- 消费者接收、处理消息失败后,消息队列什么时候重发消息?
- 重发消息是否阻塞后续新到达的消息?
- 重发消息是否支持延迟、以及延迟的方式(比如重发的延迟时间不断增加)?
- 是否可以无限重发?
- 当达到重发上限后,对应的消息会怎么处理?
4. 定时/延迟发送机制
在某些特定的场景下,可能希望消息队列接收到消息后,并不是立即转发给对应消费者,而是延迟一定的时间、或者在指定的时间再转发给对应消费者。如果能够按指定的规则重复发送消息那就更好了,这样就可以利用消息队列实现定时任务的功能了。