定义
目录
消息中间件是基于队列与消息传递技术,在网络环境中为应用系统提供同步或异步、可靠的消息传输的支撑性软件系统。简单来说,消息中间件关注于数据的发送与接收,利用高效、可靠的信息传递机制,对分布式系统中各个子系统进行集成,如图所示:
为什么使用消息中间件
假设有一个电商系统,用户下单支付成功后,需要调用库存系统减库存,调用物流系统发货等。传统的方式是通过接口相互调用,但是随着系统的发展,需要调用的接口就会越来越多,例如发送短信、添加积分等等。如果使用接口调用的方式那么增加了系统的复杂性和耦合性。系统业务修改时,需要改动大量代码。
这时,就可以用到消息中间件了,用户下单支付成功后,系统向消息中间件发送一条消息,其他的系统从消息中间件中取数据,取到后执行相应的业务。这样就做到了服务的解耦,没有了大量的接口调用。
使用消息中间件,还可以提高系统的执行效率。
消息中间件还有流量消峰的作用,消息中间件可以作为一个蓄水池,将消息缓存起来,供消费者使用。
消息中间件使用场景
系统解耦
如图所示,订单服务将消息发送至消息中间件,不与其他服务做接口调用,此时如果需要增加一个积分服务,那么只需添加积分服务,作为消费者读取消息中间件的信息即可,无需改动订单服务的代码。
如果短信服务因故宕机,也不影响订单服务继续下单。
异步调用
对于串行调用接口方式如图:
由于各个接口是同步调用,那么耗时就是各个接口的总时长 就是各个接口耗时的总和。此时可以使用中间件那么耗时就是订单服务耗时加写入中间件的耗时,这样就提高了系统的执行效率。
流量削峰
在电商秒杀时,由于请求暴增,会导致服务异常,这种场景可以使用消息中间件,将用户请求放入放入消息中间件,当请求数量超过中间价队列最大限制时,直接返回错误页面。对于中间件队列的请求,由消费者做后续处理。这样就避免了由于请求过多导致的服务异常。
常见的消息中间件
常见的消息中间件有ActiveMQ,RabbitMQ,RocketMQ和kafka。简单比较入下:
ActiveMQ | RabbitMQ | RocketMQ | kafka | |
语言 | java | erlang | java | scala |
单机吞吐 | 万 | 万 | 十万 | 十万 |
时效性 | ms | us | ms | ms |
优点 | 可用性高,MQ领域的功能及其完备 | MQ性能较好,高并发;健壮、稳定、跨平台、支持多语言、文档齐全 | 可用性非常高;经过参数优化配置,消息可做到0丢失;支持10亿级别消息堆积不影响性能 | 性能卓越,可用性非常高;在大数据领域的实时计算以及日志采集被大规模使用 |
缺点 | 官方社区维护越来越少,较少在大规模吞吐的场景中使用 | 源码难懂,不利于二次开发和维护 | 支持语言不多,目前支持java、c++,其中c++不成熟;没有在 mq 核心中去实现JMS等接口,有些系统要迁移需要修改大量代码 | 单机超过64个队列/分区,Load会发生明显的飙高现象,队列越多,load越高,发送消息响应时间变长;消费失败不支持重试;支持消息顺序,但是一台代理宕机后,就会产生消息乱序 |
那么这几个如何选择呢?一般来说:
用户访问量在ActiveMQ的可承受范围内,而且确实主要是基于解耦和异步来用的,可以考虑ActiveMQ,也比较贴近Java工程师的使用习惯。
RabbitMQ,结合erlang语言本身的并发优势,性能较好,社区活跃度也比较高,但是不利于做二次开发和维护。不过,RabbitMQ的社区十分活跃,可以解决开发过程中遇到的bug。
RockeMQ,天生为金融互联网领域而生,对于可靠性要求很高的场景,尤其是电商里面的订单扣款,以及业务削峰,在大量交易涌入时,后端可能无法及时处理的情况。RoketMQ在稳定性上可能更值得信赖,这些业务场景在阿里双11已经经历了多次考验,如果你的业务有上述并发场景,建议可以选择RocketMQ。
kafka,要特点是基于Pull的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输,适合产生大量数据的互联网服务的数据收集业务。大型公司建议可以选用,如果有日志采集功能,肯定是首选kafka了。