其实在业界没有统一的标准,一般认为,消息中间件属于分布式系统中的一个子系统,关注数据的发送与接收,利用高效可靠的异步消息传递机制对分布式中的子系统进行整合。
假设一个电商交易场景,用户下单有调用库存系统减库存,然后调用物流系统进行发货,如果交易、库存、物流属于一个系统,那么就是接口调用,但是随着系统的发展,各个模块会越来越强大,业务逻辑也会越来越复杂,必然也是要做服务化及业务拆分的。这个时候就要考虑到系统如何进行交互,第一个反应就是就是RPC(Remote Procedure Call)。系统继续发展,一笔交易可能需要几十个接口来执行业务,比如短信系统、邮件系统等等。这时候就需要消息中间件了
消息中间件主要是解决分布式系统中消息的传递,同时为分布式系统其它子系统提供了伸缩性和扩展性,为系统带来了:低耦合,异步通信、缓冲的能力
低耦合:不管是程序中间还是模块之间,使用消息中间件进行间隔通讯
异步通讯:使得子系统中间得以充分的时间执行业务逻辑,无需等待
缓冲:消息中间件就像一个巨大的储水池一样,将高峰期存储的大量请求存储下来慢慢交给程序执行,这对秒杀系统来说尤 为重要
名词解释:
伸缩性:是指通过不断的向集群中添加服务器的手段来缓解程序高并发和不断增加的数据存储需求,就像弹簧上挂了个东西一样,用户多一点,伸一点。用户少一点,就缩一点。衡量架构高伸缩性的标准就是是否可用多台服务器构建集群,是否容易向集群中添加新的服务器,加入新的服务器之后是否可像原来系统一样提供相差无几的服务,集群可容纳服务器是否有限制。
扩展性:主要标准就是在网站增加新的产品时,是否可以对先产品无影响,不需要任何改动的情况下或者很少改动即有业务系统就可上线新产品。
RPC和消息中间件的很大差异就在 “依赖性” 和 “同步性”
比如短信服务并不是交易环境必须的,并不影响下单,不存在强依赖,所以交易系统不需要依赖短信服务。
消息中间件出现出现以后对于交易系统可能调用库存中心等强依赖系统执行业务,之后发布一条消息(这条消息存储在消息中间件中)。像消息通知服务、数据统计服务都是依赖于消息中间件去消费这条消息来完成业务逻辑的处理。
RPC的方式是典型的同步方式,让远程调用像本地调用。消息中间件事异步调用方式。消息队列是系统级的,模块级的的通信,RPC是是对象级,函数级的通信
他们有个共同点就是都是分布式下的通信方式
场景说明:用户注册后,需要发送注册邮件和注册短信。传统的方法有两个,1、是串行,2、并行
1)串行方式:将注册信息写入成功后发送注册邮件,然后再发送注册短信,三个任务完成后把结果返回客户端。
2)并行方式:将注册信息写入数据库成功后,发送邮件的同时,发送注册短信,以上三个任务完成后把结果返回客户端,与串行的方式不同是,这个可以大大的节省业务处理时间
引入消息队列业务处理方式:
引入消息队列,将不是必须的业务逻辑做异步处理。
按照以上约定,用户响应时间就相当于把注册信息写入数据库的时间,也就是50毫秒,注册邮件、发送短信写入消息队列后,直接返回,消息队列处理速度很快的,基本可以忽略,因此客户的响应时间是50ms,因此架构改变后,系统的吞吐量就达到了每秒20的QPS(每秒查询率),这种方式比串行提高的三倍的处理速度,比并行提高了两倍的处理速度。
场景说明:用户下单后,订单系统需要通知库存系统。传统的做法是订单系统直接调用库存系统接口。
传统模式的缺点:
1、如果订单系统无法访问,则订单减库存失败,则会造成订单失败
2、订单系统和库存系统耦合
引入消息队列后解决方案
订单系统:用户下单后,订单系统完成持久化处理,将消息写入队列中,返回用户订单下单成功。
库存系统:订阅下单消息,获取订单信息,库存系统根据订单信息进行相关的业务操作。
这样在下单的时候库存系统不能正常使用也不会影响到用户下单,因为下单之后订单系统把信息写入消息队列后就不管其他后续操作了,从而实现订单系统与库存系统的解耦。
流量削峰:
流量削峰是队列常用的使用场景,一般秒杀系统或者团购中广泛使用
应用场景:秒杀活动时会因为流量过大,用户流量暴增,导致应用崩溃。解决这个问题就是在中间加入消息队列,这样可以控制当前活动的人数;缓解短时间的涌入大量的流量压垮系统;
用户请求后,服务器接收后,先写入消息队列,假如消息队列长度超过的最大数量,则抛弃用户请求或者跳转到其他页面;秒杀信息根据消息队列中的请求信息再做后续处理。
日志处理是指将消息队列用在日志处理中,比如说kafka的应用,解决大量日志传输的问题,架构简化如下
日志采集客户端负责采集,定时写入kafka消息队列:kafka消息队列负责消息的接收、存储、转发;日志处理应用负责订阅及消费kafka消息队列中的日志数据。
消息通讯是指消息队列一般都内置了高效的内部通讯机制,因此也可以用在纯的消息通讯。比如实现点对点的消息队列,或者聊天是等。
点对点通讯:客户端A和客户端B使用同一队列,进行消息通讯。
聊天室通讯:客户端A,客户端B,客户端C订阅同一主题进行消息通讯,实现类似于聊天室的功能
ActiveMQ: 用户访问量在ActiveMQ的可承受范围内,而且确实主要是基于解耦和异步来用的,可以考虑ActiveMQ,也比较贴近Java工程师的使用习惯。
RabbitMQ:是使用erlang语言开发的,阻止了我们去深入研究和掌控,对公司而言,几乎处于不可控的状态,但是确实是开源的,有比较稳定的支持,活跃度也高。
RocketMQ :RocketMQ 是阿里的,有Dobbo的前车之鉴,对自己公司技术实力有绝对自信的,可以用RocketMQ ,所以中小型公司,技术实力较为一般,技术挑战不是特别高,用ActiveMQ、RabbitMQ是不错的选择;大型公司,基础架构研发实力较强,用RocketMQ是很好的选择
Kafka:如果是大数据领域的实时计算、日志采集等场景,用Kafka是业内标准的,绝对没问题,社区活跃度很高,几乎是全世界这个领域的事实性规范。