MQ在分布式系统中的使用场景
异步处理
例如我们需要发送短信的服务,以前是点击发送短息,然后执行发送短信的逻辑,等到执行完成后返回信息,这中间假设发送短信需要500ms,那么从发起请求到执行完发送逻辑至少需要500ms的时间;但是如果我们将发送短信的请求写入到消息队列中,直接返回发送成功,别的服务直接从消息队列中获取消息并在后台发送短信,而写入消息到队列中的耗时是很少的,我们会立即获取到响应成功。
应用解耦
例如下订单减库存,如果下单完成后直接去调用减库存的接口,当其中一个系统进行升级而改动了传递的参数,那么另一个系统就必须得需要源代码;而引入消息队列,当下订单后,我们只需要将订单数据写入到消息队列中,库存系统去订阅消息队列获取里面的内容,然后分析执行减库存,这中间不需要去关心订单系统传递了什么参数,库存系统需要什么参数,即使其中某个系统升级,但是没有进行直接调用,则不必修改其他系统
流量控制
例如秒杀业务,瞬间流量非常大,我们可以将请求存到消息队列中,而不用去管请求的秒杀业务的具体执行,直接返回请求的响应结果,而其他服务订阅消息队列然后进行业务处理
消息中间件概述
大多数应用中,可以通过消息服务中间件来提升系统异步通信、扩展解耦能力;消息服务中有两个重要的概念:消息代理(message broker) 和 目的地(destination)
消息代理:就是安装了消息中间件的服务,不管是发消息还是接收消息都是通过它来获取的
目的地:消息发送的地方
所以,当消息发送者发送消息后,有消息代理接管,消息代理保证消息传递到指定的目的地,而在消息队列中有两种形式的目的地:队列(queue) 和 主题(topic)
队列(queue):点对点消息通信,消息发送者发送消息,消息代理将其放入一个队列中,消息接收者从队列中获取消息内容,消息读取后被移除队列,消息只有唯一一个发送者和接受者,但是可以有多个接收者
主题(topic):发布/订阅消息通信,发布者发送消息到主题,多个订阅者订阅这个主题,那么在消息到达时会同时收到消息
对于消息中间件,我们有非常多的规范和协议,例如JMS Java 消息服务,AMQP
JMS(Java Message Service) Java 消息服务:Sun公司指定的标准,是基于JVM消息代理的规范,例如ActiveMQ、HornetMQ就是基于JMS实现的
AMQP(Advanced Message Queuing Protocol):高级消息队列协议,它兼容JMS,例如RabbitMQ就是基于AMQP实现的
但是在分布式开发中应该选择JMS还是AMQP呢,先来看看他们两的区别
JMS(Java Message Service) | AMQP(Advanced Message Queuing Protocol) | |
---|---|---|
定义 | Java api | 网络线级协议 |
跨语言 | 否 | 是 |
跨平台 | 否 | 是 |
Model | 提供两种消息模型: (1) Peer-2-Peer (2) Pub/sub | 提供五种消息模型 (1)direct exchange (2)fanout exchange (3)topic exchange (4)headers exchange (5)system exchange 本质来讲,后四种和JMS的pub/sub模型没太大的区别,仅是在路由机制上做了更详细的划分 |
支持消息类型 | 多种消息类型 TextMessage MapMessage BytesMessage StreamMessage ObjectMessage Message(只有消息头和属性) | byte[] 当实际应用时,有复杂的消息,可以将消息序列化后发送 |
综合评价 | JMS定义了Java api 层面的标准,在Java体系中,多个client均可以通过JMS进行交互。不需要应用修改代码,但是其对跨平台的支持较差 | AMQP定义了wire-level层的标准协议,天然具有跨屏台、跨语言的特性 |
MQ技术选型