目录
一、认识消息中间件
官方说法(维基百科)就是:面向消息的系统(消息中间件-Message oriented middleware,简称MOM)是在分布式系统中完成消息的发送和接收的基础软件。
消息中间件也可以称消息队列,是指用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信进行分布式系统的集成。通过提供消息传递和消息队列模型,可以在分布式环境下扩展进程的通信。
emmm~从上面我们大概知道了消息中间件的定义,下面我用张图来展示这玩意在真实的项目中所处的地位,或者说位置是啥~
》》》假设上面是一个正儿八经的微服务架构的商城系统(随便画的,里面一些细节经不起推敲不用在意)。假如现在有一个需求,用户在商城下订单支付成功之后,需要发起物流服务、更新用户的积分等,那么正常代码就是如下:
//伪代码
//1、下单(可以不在当前步骤接口中,为了流程写出来)
orderService.makeOrder();
//2、支付
boolean success=payService.pay();
if(success){
//3、物流
transportService.tran();
//4、积分
jfService.up();
}else{
}
//最后返回给用户支付成功的
return success;
从上面的流程,就可以看出,在这个小小的接口中,就需要涉及至少3个服务的调用,并且在代码中可以看出是顺序调用,那么就会出现如下的一些问题:
- 由于是服务间调用,虽然微服务调用基本会采用Feign/OpenFeign这样的组件,但是无法避免存在一些服务器异常或者网络波动的问题,出现问题就会导致接口慢甚至超时的问题,这样对用户的体验度就很不好。
- 假如用户已经支付完成,并且已经扣款,由于后面不重要的服务,譬如:积分服务的报错,而导致整个流程回滚,就会得不偿失。
》》》因此,我们需要解决的问题就是:服务之间的解耦、以及将影响降到最低,那么此时我们就考虑是不是可以进行异步的处理方式,同时进行一些特殊处理,譬如使用公共的任务池。
//伪代码-plus
//1、下单(可以不在当前步骤接口中,为了流程写出来)
orderService.makeOrder();
//2、支付
boolean success=payService.pay();
if(success){
//创建一个任务池
TaskPools pools = new TaskPools();
//3、物流任务异步处理
pools.start(transportTask.class);
//4、积分任务异步处理
pools.start(jfTask.class);
}else{
}
//最后返回给用户支付成功的
return success;
从上面优化后的代码可以看出,我们将不重要的服务,通过异步任务的方式放在任务池中进行处理,这样就可以避免小流程影响主流程的问题。但是这样同样会存在一些问题:
- 我们将异步任务放在池中,失败怎么处理?怎么回调给主流程?怎么进行重试?
- 重试后,最终执行的结果怎么保证一致?
- 我们发去池中的任务一定会存在吗?池子满了怎么办?有持久化的策略吗?
- ......
是不是越想越头大~~~其实还有很多需要解决的问题要去考虑的呀,例如:网络通信、协议、回调、持久化、丢弃策略、分配策略等等。那么此时,我们的消息中间件就隆重登场了!!!
消息中间件本身就具备以下特性:
- 系统解耦
- 异步通信
- 流量削峰填谷
- 天生分布式
二、消息中间件的比较
我们自己也可以自制一个简单的单机版的消息中间件,来大概知道他的基本理念。可以通过Java的BlockingDeque来自制,不过也就图一乐,代码就不贴了。
说说市面上的消息中间件吧:
- ActiveMQ:早期的消息中间件~emmm,没啥好说的,现在基本上都被淘汰的。啥?你们公司还在用?什么古老项目,跑路跑路!!!
- RabbitMQ:目前中小型公司使用的多,得益于他的轻量、快捷以及完备的社区,目前还是有一定的市场占用率。
- KAFKA:这玩意以前一段时间平平无奇,后面由于完美兼容大数据相关的各类组件,成为大数据方向的宠儿,同时他的一些新特性,也成为目前炙手可热的产品。
- RocketMQ:阿里的开源组件,得益于阿里在国内Java的影响地位,同时也因为很多中小型公司都使用阿里云服务,RocketMQ这个产品也就渐渐火了起来,不过更多的原因还是RocketMQ本身产品特性够硬,抗住了各种大促,还是很强大的。
下面用图的方式来展示后面三款的一些比较吧~ActiveMQ就不谈了,不给他面子~
从上面的图就可以看出,为啥中小型公司喜欢用RabbitMQ了吧,首先就是轻量,其次就是本身公司的量级不大,使用KAFKA或者RocketMQ就有点大材小用了~~~其实就算大厂,也不一定没个部门都有像淘宝、像京东这样的体量吧,其实大厂的一些部门也是有很多做内部系统或者轻量级项目的!!!
因此,项目体量不大就RabbitMQ,超过十万就看喜好~
三、RabbitMQ介绍
说了这么多,回到最初的主题,咱们的小兔子:RabbitMQ~~
引用《RabbitMQ实战》的话:RabbitMQ是一款轻量级的、功能强大的工具,可以用来构建简单的或异常复杂的分布式软件架构。他具备以下特性:
- 开源——emmm,怎么说呢,这玩意是用erlang语言写的,erlang的爱立信公司早期用来做电力开发的,所以开源对我们没去深入erlang语言的来说,没啥用,只是对该产品的发展有很大的作用。
- 平台与供应商无关性——因为RabbitMQ采用的是通用的协议AMQP协议,所以RabbitMQ基本上可以为所有语言提供客户端工具并运行在主流计算机上。
- 轻量——这玩意很小就是了。
- 良好语言支持——支持大部分主流的语言
- 支持插件——貌似没怎么用过,emmm
- 消息中间件的公用特性——异步通信、解耦、分布式等
四、AMQP协议
简单聊聊AMQP协议吧~
AMQP全称高级消息队列协议(Advanced Message Queuing Protocol),是一种标准,类似于JMS,兼容JMS协议。目前RabbitMQ主流支持AMQP 0-9-1,3.8.4版本支持AMQP 1.0。
其实AMQP协议中的一些概念,就是RabbitMQ中的一些概念:
- Publisher:消息发送者,将消息发送到Exchange并指定RoutingKey,以便queue可以接收到指定的消息。
- Consumer:消息消费者,从queue获取消息,一个Consumer可以订阅多个queue以从多个
queue中接收消息。 - Server:一个具体的MQ服务实例,也称为Broker。
- Virtual host:虚拟主机,一个Server下可以有多个虚拟主机,用于隔离不同项目,一个Virtual
host通常包含多个Exchange、Message Queue。 - Exchange:交换器,接收Producer发送来的消息,把消息转发到对应的Message Queue中。
- Routing key:路由键,用于指定消息路由规则(Exchange将消息路由到具体的queue中),通常需要和具体的Exchange类型、Binding的Routing key结合起来使用。
- Bindings:指定了Exchange和Queue之间的绑定关系。Exchange根据消息的Routing key和
Binding配置(绑定关系、Binding、Routing key等)来决定把消息分派到哪些具体的queue中。这依赖于Exchange类型。 - Message Queue:实际存储消息的容器,并把消息传递给最终的Consumer。
具体的协议内容,后面看看是否单独拿一章来说~~
本章就到此结束~后面会慢慢介绍Rabbit安装、高级特性以及高级应用,同时还有实战~~~Bye!