鉴于号称“人见天堂”的杭州阿里系的互联网公司偏多,使得小编熟悉的RabbitMQ没有用武之地!RocketMQ和RabbitMQ的基础使用是不会有太大区别的,但底层原理、协议各有不同,接下来就在小编带大家一起探索吧~
首先,我们需要知道一些前置知识:
1. 什么是MQ?
MQ(Message Queue)消息队列,是基础数据结构中 “先进先出”的一种数据结构。指把要传输的消息放在队列中,用队列机制来实现消息传递。
即:
- 生产者产生消息并把消息放入队列,然后由消费者去处理;
- 消费者可以到指定队列拉取消息或者订阅相应队列,由MQ服务端给给其推送消息。
2. MQ解决了哪些问题?
因为项目比较大,使用了分布式系统架构,所有的远程服务调用都是同步执行经常出现问题,所以引入了MQ。消息队列中间件是分布式系统中重要的组件,主要实现了 流量削锋、应用解耦、异步处理功能,实现高性能,高可用,可伸缩和最终一致性架构。
-
削锋
可以通过消息队列长度控制请求量,可以缓解短时间内的高并发请求,减少高峰时期对服务器的压力。 -
解耦
一个业务需要多个模块共同实现,或者一条消息有多个系统需要对应处理,只需要主业务完成以后,发送一条MQ,其余模块消费MQ消息,即可实现业务,降低模块之间的耦合。- 比如说:A 系统发送数据到 BCD 三个系统,通过接口调用发送。如果 E 系统也要这个数据呢?那如果 C 系统现在不需要了呢?A 系统负责人几乎崩溃…A 系统跟其它各种乱七八糟的系统严重耦合,A 系统产生一条比较关键的数据,很多系统都需要 A 系统将这个数据发送过来。如果使用 MQ,A 系统产生一条数据,发送到 MQ 里面去,哪个系统需要数据自己去 MQ 里面消费。如果新系统需要数据,直接从 MQ 里消费即可;如果某个系统不需要这条数据了,就取消对 MQ 消息的消费即可。这样下来,A 系统压根儿不需要去考虑要给谁发送数据,不需要维护这个代码,也不需要考虑人家是否调用成功、失败超时等情况。
就是一个系统或者一个模块,调用了多个系统或者模块,互相之间的调用很复杂,维护起来很麻烦。但是其实这个调用是不需要直接同步调用接口的,如用 MQ 给它异步化解耦。
-
异步
主业务执行结束后从属业务通过MQ,异步执行,减低业务的响应时间,提高用户体验。
比如说:A 系统接收一个请求,需要在自己本地写库,还需要在 BCD 三个系统写库,自己本地写库要 3ms,BCD 三个系统分别写库要 300ms、450ms、200ms。最终请求总延时是 3 + 300 + 450 + 200 = 953ms,接近 1s,用户体验感就下降了,慢死了慢死了。用户通过浏览器发起请求,如果使用 MQ,那么 A 系统连续发送 3 条消息到 MQ 队列中,假如耗时 5ms,A 系统从接受一个请求到返回响应给用户,总时长是 3 + 5 = 8ms。
除了削峰、解耦、异步,使用MQ还有以下功能:
- 日志处理,解决了大量日志传输问题
- 消息通讯,消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯,比如实现点对点队列、聊天室等。
3. 使用MQ带来了哪些问题?
消息队列实际是一种非常复杂的架构,引入它有很多好处,但是也得针对它带来的坏处做各种额外的技术方案和架构来规避掉,做好之后,你会发现,系统复杂度提升了一个数量级,也许是复杂了 10 倍。但是关键时刻,用,还是得用的。
- 系统可用性降低,依赖服务越多,服务越容易挂掉,需要考虑MQ瘫痪的情况;
- 系统复杂性提高,加入了消息队列,需要考虑很多方面问题。比如说:如何保证消息不丢失呀?如何防止消息重复消费呢?以及消息传递的顺序性等等。
- 业务一致性,即数据的一致性。
- 比如:A 系统处理完了直接返回成功了,人都以为你这个请求就成功了;但是问题是,要是 BCD 三个系统那里,BD 两个系统写库成功了,结果 C 系统写库失败了,咋整?你这数据就不一致了。
- 小编是这样解决的,我们可以把消息塞进延迟队列,等到定长时间后成为死信队列,消费方去监听这个死信队列再做相关的数据一致性处理工作。
4. MQ中常见的协议有哪些?
- JMS,即 Java消息服务。是Java平台上有关 MOM(面向消息的中间件 PO/OO/AO)的技术规范,它便于消息系统中的Java应用程序进行消息交换,并且通过提供标准的产生、发送、接收消息的接口,简化企业应用的开发。ActiveMQ 是该协议的典型实现。
- STOMP,面向流文本的消息协议。是一种 MOM 设计的简单文本协议。STOMP 提供一个可互操作的连接格式,运行客户端与任意STOMP消息代理进行交互。ActiveMQ是该协议的典型实现,RabbitMQ 通过插件可以支持该协议。
- AMQP,高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。RabbitMQ就是一款开源的用Erlang编写的基于AMQP协议的消息中间件。
- MQTT,消息队列遥测传输,是 IBM 开发的一个即时通讯协议,是一种二进制协议,主要用于服务器和低功耗IOT(物联网)设备间的通信。该协议支持所有平 台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和致动器的通信协议。RabbitMQ通过插件可以支持该协议。
5. 常见的消息中间件
- ActiveMQ :Java开发、简单、稳定,性能不如其他三个。小型系统中使用还是ok的,但是不推荐。社区活跃度基本上变成了一条直线。
- RabbitMQ:一个开源的使用erlang语言开发的基于AMQP协议的消息队列,对消息堆积的支持并不好,当大量消息积压的时候,会导致RabbitMQ的性能急剧下降。每秒钟可以处理几万到几十万条消息;
- RocketMQ: 用Java开发,面向互联网集群化功能比较丰富,对在线业务的响应时延做了很多的优化,大多数情况下可以做到毫秒级的响应,每秒钟大概能处理几十万条消息;
- Kafka:Scala开发,面向日志功能丰富,性能最高。当你的业务场景中,每秒消息数量没有那么多的时候,Kafka的时延反而会比较高。所以,Kafka不太适合在线业务场景。