什么是消息队列(Message queue)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/codejas/article/details/79930909

最近接触到消息中间件,想通过本篇博文总结一些关于消息队列的知识,以及 Java 语言中面向消息中间件(MOM)的API(JMS),希望能够帮助大家更好的理解消息中间件。

一、消息队列概述

消息队列(英语:Message queue)是一种进程间通信或同一进程的不同线程间的通信方式,软件的贮列用来处理一系列的输入,通常是来自用户。

消息队列提供了异步的通信协议,每一个贮列中的纪录包含详细说明的数据,包含发生的时间,输入设备的种类,以及特定的输入参数,也就是说:消息的发送者和接收者不需要同时与消息队列交互。消息会保存在队列中,直到接收者取回它。

上面的介绍来自维基百科,解释用语比较官方,但是我们应该知道的是消息队列可以实现异步之间的通信。下面通过一个简单的架构模型来解释:

  • Producer:消息生产者,负责产生和发送消息到 Broker。

  • Broker:消息处理中心。负责消息存储、确认、重试等,一般其中会包含多个 queue。

  • Consumer:消息消费者,负责从 Broker 中获取消息,并进行相应处理。

二、消息队列的特点

异步

消息队列本身是异步的,它允许接收者在消息发送很长时间后再取回消息,这和大多数通信协议是不同的。很多情况下我们需要异步的通信协议。比如,一个进程通知另一个进程发生了一个事件,但不需要等待回应。

但消息队列的异步特点,也造成了一个缺点,就是接收者必须轮询消息队列,才能收到最近的消息。

解耦

消息队列减少了服务之间的耦合性,不同的服务可以通过消息队列进行通信,而不用关心彼此的实现细节,只要定义好消息的格式就行。

比如订单系统,订单最终支付成功之后可能需要给用户发送短信积分什么的,但其实这已经不是核心流程了。如果外部系统速度偏慢(比如短信网关速度不好),那么主流程的时间会加长很多,用户肯定不希望点击支付过好几分钟才看到结果。那么我们只需要通知短信系统“我们支付成功了”,不一定非要等待它处理完成。

广播

消息队列的基本功能之一是进行广播。如果没有消息队列,每当一个新的业务方接入,我们都要联调一次新接口。有了消息队列,我们只需要关心消息是否送达了队列,至于谁希望订阅,是下游的事情,无疑极大地减少了开发和联调的工作量。

流量削峰与流控

当上下游系统处理能力存在差距的时候,利用消息队列做一个通用的”载体”。在下游有能力处理的时候,再进行分发与处理。

比如在电商系统中常见的秒杀活动,每秒可能会有成千上万个请求,但是数据库的处理能力是有限的,在这种并发量下后台服务很可能会挂掉。这时就可以通过消息队列将请求压入队列中,后台服务仍然按照之前的数据处理能力处理这些请求。虽然速度会慢一些但是能保证服务正常执行。

三、JMS

JMS 概述

Java 消息服务(Java Message Service,JMS)应用程序接口是一个 Java 平台中关于面向消息中间件(MOM)的 API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。

Java消息服务是一个与具体平台无关的 API,绝大多数 MOM 提供商都对 JMS 提供支持。

JMS 模型

Java 消息服务应用程序结构支持两种模型:点对点或队列模型与发布/订阅模型。

在点对点或队列模型下,一个生产者向一个特定的队列发布消息,一个消费者从该队列中读取消息。

  • 只有一个消费者将获得消息。

  • 生产者不需要在接收者消费该消息期间处于运行状态,接收者也同样不需要在消息发送时处于运行状态。

  • 每一个成功处理的消息都由接收者签收。

发布者/订阅者模型支持向一个特定的消息主题发布消息。

  • 多个消费者可以获得消息。

  • 在发布者和订阅者之间存在时间依赖性。发布者需要建立一个订阅(subscription),以便客户能够购订阅。订阅者必须保持持续的活动状态以接收消息,除非订阅者建立了持久的订阅。在那种情况下,在订阅者未连接时发布的消息将在订阅者重新连接时重新发布。

JMS 提供者实现

要使用 Java 消息服务,需要有一个 JMS 提供者,来管理会话和队列。现在有很多的开源 JMS 提供者,比如:Kafka、Apache ActiveMQ、RabbitMQ 等。

参考资料:
https://tech.meituan.com/mq-design.html
https://github.com/jasonGeng88/blog/blob/master/201705/MQ.md

阅读更多

没有更多推荐了,返回首页