消息队列-基础篇

本文介绍了消息队列在分布式系统中的重要作用,包括应用解耦、异步处理和流量削锋。讲解了JMS规范及其包含的点对点和发布/订阅两种模型,以及AMQP协议的基础概念。文中还提到了常见消息队列如RocketMQ、RabbitMQ和Kafka,并指出选择MQ时需考虑的特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前文我们讲到了分布式事务可以通过MQ(消息队列)的半消息来实现,除此之外在分布式系统中我们大量的场景会用到MQ,比如微信朋友圈里你点赞一条信息,你的共同点赞的好友就会收到一个消息通知等。那么MQ都有哪些使用场景呢?

MQ 的作用

1.应用解耦

消息队列-基础篇

如图所示,第一种 B和C 都直接依赖 A 服务,那么如果 A 中的接口修改,B和C 都要跟着做修改,耦合度高。 第二种,通过 MQ 来作为中间件收发消息,B和C只依赖收到的消息而不是具体的接口,这样即使 A 服务修改或者增加其他服务,都只要订阅MQ就行。这样一来,应用是不是更解耦了?

2.异步处理

消息队列-基础篇

如图可见,我在 A 服务用户注册完成后,就直接返回了,这个时候 MQ 用来发送异步处理消息,B和C 服务分别处理。A 不用等待 B、C 的返回结果 ,这样用户体验就是只有 50ms 等待时间。而在邮件、短信这个阶段,因为网络延迟原因,用户可以接受一定时间的等待。这样通过异步处理的方式,就提高了系统的吞吐量。

3.流量削锋

消息队列-基础篇

将上游处理的较快的任务,加入到MQ中,下游逐一消费MQ,直到所有MQ消息消费完成。 假如秒杀服务处理请求数:1000/s,下游订单服务处理请求数量:10/s,为了不给下游订单服务造成压力,秒杀后的信息发送到队列,订单服务就可以从容淡定的每秒处理十个,而不是直接塞 1000 个请求也不管人家愿意不愿意,这样是不是保护了订单服务不至于宕机?

怎么样,到这里是不是感觉到了MQ是不是很有用?那如何实现一个MQ呢?早就有前人为我们抽象出了一些模型,我们只需要照着葫芦画瓢。

MQ的规范

1. JMS规范

通常而言提到JMS(Java Message Service)实际上是指JMS API。JMS是由Sun公司早期提出的消息标准,旨在为java应用提供统一的消息操作,包括create、send、receive等。JMS已经成为Java Enterprise Edition的一部分。用于在两个应用程序之间,或分布式系统中发送消息(发送消息的时候,接收者不需要在线),进行异步通信。

JMS通常包含如下一些角色:

名称

描述

JMS provider

实现了JMS接口的消息中间件,如ActiveMQ

JMS client

生产或者消费消息的应用

JMS producer/publisher

JMS消息生产者

JMS consumer/subscriber

JMS消息消费者

JMS message

消息,在各个JMS client传输的对象;

JMS queue

Provider存放等待被消费的消息的地方

JMS topic

一种提供多个订阅者消费消息的一种机制;在MQ中常常被提到,topic模式。

看到这些角色的名称我们很熟悉,没错!常见的消息队列,大部分都实现了JMS API,可以担任JMS provider的角色,如ActiveMQ,Redis以及RabbitMQ等。

2. JMS常用模型:

1.P2P(Point to Point)点对点模式

P2P模式包含三个角色:消息队列(Queue)发送者(Sender)接收者(Receiver)

每个消息都被发送到一个特定的队列,接收者从队列中获取消息。队列保留着消息,直到他们被消费或超时。

消息队列-基础篇

P2P的特点:

  • 每个消息只有一个消费者(Consumer)(即一旦被消费,消息就不再在消息队列中)
  • 发送者和接收者之间在时间上没有依赖性,也就是说当发送者发送了消息之后,不管接收者有没有正在运行,它不会影响到消息被发送到队列
  • 接收者在成功接收消息之后需向队列应答成功

2.Publish/Subscribe(Pub/Sub) 发布订阅模式

Pub/Sub模式包含三个角色:主题(Topic)发布者(Publisher)订阅者(Subscriber)

多个发布者将消息发送到Topic,系统将这些消息传递给多个订阅者。

消息队列-基础篇

Pub/Sub的特点:

  • 每个消息可以有多个消费者
  • 发布者和订阅者之间有时间上的依赖性。针对某个主题(Topic)的订阅者,它必须创建一个订阅之后,才能消费发布者的消息
  • 为了消费消息,订阅者必须保持运行的状态

AMQP协议

同样的,涉及到消息中间件也需要对AMQP协议有一定的了解,什么是AMQP协议?

高级消息队列协议 AMQP(advanced message queuing protocol)是一个提供统一消息服务的应用层标准协议,基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同开发语言条件的限制。

AMQP中的常见角色:

名称

描述

Broker

接收和分发消息的应用,RabbitMQ Server就是Message Broker

Virtual host

AMQP的基本组件划分到一个虚拟的分组中

Connection

publisher/consumer和broker之间的TCP连接

Channel

Channel作为轻量级的Connection极大减少了操作系统建立TCP connection的开销

Exchange

message到达broker的交换机,根据分发规则,匹配查询表中的routing key,分发消息到queue中去

Queue

消息最终被送到这里等待consumer取走。

Binding

exchange和queue之间的虚拟连接,binding中可以包含routing key。

AMQP模型的工作流程如下:

1、消息(Message) 被发布者 (publisher) 发送给交换机(exchange),交换机常常被比喻成邮局或者邮箱,

2、然后交换机将收到的消息根据路由规则分发给绑定的队列(queue),

3、最后AMQP代理会将消息投递给订阅此队列的消费者,或者消费者按照需求从队列中拉取消息。

如下图所示:

消息队列-基础篇

从图上可以看出AMQP协议有一个很核心的思想:

生产者和消息者隔离,生产者从不直接将消息发送给队列。生产者通常不知道是否一个消息会被发送到队列中,只是将消息发送到一个交换机。先由 Exchange 来接收,然后 Exchange 按照特定的路由规则转发到 Queue 进行存储。

那么为什么不直接发送到Queue呢?

架构设计的核心就是——分层,通过Exchange层的代理,可以实现非常灵活的Queue的分配。

AMQP提供四种不同类型的Exchange

  • Direct:当消息的routing key 与 binding 的 routing key 直接匹配,消息路由到该队列
  • Topic: 当消息routing key 与 binding 的 routing key 符合通配符匹配,消息路由到该队列
  • Fanout: 任何消息直接匹配到所有队列上
  • Headers: 当消息参数表中的头信息和值都与 binding参数表中匹配的话,消息路由到该队列

关于AMQP的其他组件的详细介绍,我们之后在RabbitMQ中详细描述。

总结一下

JMS

AMQP

定义

Java api

Wire-protocol

跨语言

跨平台

模型

Peer-2-Peer、Pub/sub

direct exchange、fanout exchange、topic change、headers exchange

支持消息类型

多种消息类型:
TextMessage、MapMessage、BytesMessage、StreamMessage、ObjectMessage、Message (只有消息头和属性)

byte[]
当实际应用时,有复杂的消息,可以将消息序列化后发送。

综合评价

JMS 定义了JAVA API层面的标准;在java体系中,多个client均可以通过JMS进行交互,不需要应用修改代码,但是其对跨平台的支持较差;

AMQP定义了wire-level层的协议标准;天然具有跨平台、跨语言特性。

常见MQ对比

那我们常用的MQ有哪些呢?目前使用最多的有RocketMQ、RabbitMQ和Kafka。我们如何去选择使用哪个MQ呢?我们就需要了解MQ之间的区别。如下图所示:

消息队列-基础篇

上图取自网络,部分描述可能有误,仅供参考!后文我们会逐步深入分析常用MQ的原理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值