文章目录
- 一、消息中间件简介
- 1.1 概述
- 1.2 消息中间件的好处
- 1.2.1 应用解耦
- 1.2.2 异步处理
- 1.2.3 流量削峰
- 1.3 消息中间件带来的问题
- 1.3.1 消息一致性
- 1.3.2 消息重复消费(消息幂等性)
- 1.3.3 成本问题
- 1.3 常见MQ性能对比
- 1.4 AMQP和JMS
一、消息中间件简介
1.1 概述
MQ全称为Message Queue,消息队列是消息在传递过程中的容器,消息队列常用于分布式系统之间的通信
消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题实现高性能,高可用,可伸缩和最终一致性架构;使用较多的消息队列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ以下介绍消息队列在实际应用中常用的使用场景:异步处理,应用解耦,流量削锋和消息通讯四个场景
1.2 消息中间件的好处
在项目中,可将一些无需即时返回且耗时的操作提取出来,进行异步处理,而这种异步处理的方式大大的节省了服务器的请求响应时间,从而提高了系统的吞吐量。
1.2.1 应用解耦
在我们的应用中,下订单同时需要调用库存系统、支付系统等业务;
随着业务升级,需要更改业务需求,在下订单的同时需要对接积分系统进行加积分操作,因此结果变为如下:
从上图的演变我们可以知道,随着业务的不断升级,业务的不多增加,我们可能需要频繁的修改订单系统的代码,现在我们的订单系统严重和其他系统耦合在一起了,可维护差;不仅如此,当订单系统调用库存系统时,如果库存系统不能够及时响应,那么必定会造成订单系统的延迟,或者库存系统出现错误,那么也很有可能导致订单系统出现故障,系统的容错性非常低;
为了解决上述问题,我们引入了消息中间件(MQ):
当订单系统需要对接其他系统时,只需要发消息给MQ,由MQ来通知其他系统进行业务操作,订单系统只与MQ进行对接,从而解决我们上面的几个问题;
- 1、业务耦合
- 2、系统延迟
- 3、容错性低
1.2.2 异步处理
在我们没有引入MQ之前的老系统中,调用订单系统,等待订单系统处理完业务逻辑之后响应客户端大概需要时间:200ms+200ms+200ms=600ms
引入了MQ队列之后只需要5ms!
这里说明一点:我们之前讲MQ概述时已经讲过,MQ适用于一些无需即时返回且耗时的操作,假设在上述架构中,订单系统需要库存系统返回某值后才能进行下一步操作则不适用于MQ;
1.2.3 流量削峰
流量削峰指的是在应用服务器面对大流量访问时,MQ可以帮助我们进行流量的限流操作,削弱流量,保证服务器的正常运行;
假设现在某电商网站搞促销活动,导致流量迅速激增,已经远远超过应用服务器的压力承受范围,此时如果不进行流量(QPS)的控制,那么应用服务器很有可能会出现故障:
为了防止过度的流量同时进入我们的应用服务器,导致应用服务器最终宕机,我们可以进行限流手段,即每秒从MQ中拉取1000个请求进行处理:
由于高并发的访问,消息会被挤压在MQ中,在高峰期过后,仍有一段时间内消息消费的速度维护在1000/s,直到积压的消息全部被消费完毕;
1.3 消息中间件带来的问题
1.3.1 消息一致性
如上图,如果订单系统给其他系统发送完毕消息后,某个系统处理失败,该如何保证数据的一致性?
1.3.2 消息重复消费(消息幂等性)
当我们一个接口多次消费一个消息时,我们需要保证这个操作无论被操作多少次其结果是一样的,这个时候我们就需要保证接口的幂等性;
幂等:一个操作任意执行多次与执行一次的结果是相同的
在上述系统中,如果执行库存系统出现问题,那么订单系统会重发消息,但是支付和积分系统是没有任何问题的,但由于消息的重发,导致支付和积分系统再次消费一次消息;
1.3.3 成本问题
- 系统可用性降低
系统引入的外部依赖越多,系统稳定性越差。一旦 MQ 宕机,就会对业务造成影响。如何保证MQ的高可用?
- 系统复杂度提高
MQ 的加入大大增加了系统的复杂度,以前系统间是同步的远程调用,现在是通过 MQ 进行异步调用。需要保证MQ带来的一系列问题
1.3 常见MQ性能对比
RabbitMQ | ActiveMQ | RocketMQ | Kafka | |
公司/社区 | Rabbit | Apache | 阿里 | Apache |
开发语言 | Erlang | Java | Java | Scala&Java |
协议支持 | AMQP,XMPP,SMTP,STOMP | OpenWire,STOMP,REST,XMPP,AMQP | 自定义 | 自定义协议,社区封装了http协议支持 |
客户端支持语言 | 官方支持Erlang,Java,Ruby等,社区产出多种API,几乎支持所有语言 | Java,C,C++,Python,PHP,Perl,.net等 | Java,C++(不成熟) | 官方支持Java,社区产出多种API,如PHP,Python等 |
单机吞吐量 | 万级(其次) | 万级(最差) | 十万级(最好) | 十万级(次之) |
消息延迟 | 微秒级 | 毫秒级 | 毫秒级 | 毫秒以内 |
功能特性 | 并发能力强,性能极其好,延时低,社区活跃,管理界面丰富 | 老牌产品,成熟度高,文档较多 | MQ功能比较完备,扩展性佳 | 只支持主要的MQ功能,毕竟是为大数据领域准备的。 |
1.4 AMQP和JMS
- AMQP:即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,进程间传递异步消息的网络协议。为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端中间件不同产品的限制,不同的开发语言等条件的限制。Erlang中的实现有RabbitMQ等。
- JMS:JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。Java消息服务是一个与具体平台无关的API,绝大多数消息中间件提供商都对JMS提供支持。
AMQP是基于消息传输的一个应用层协议,JMS准确的来说是Java操作MQ的一套API,类似于JDBC,第三方厂商(MySQL厂商、MQ厂商)进行功能的实现,Java则使用JMS对厂商进行规范;