18 10 2021

前言

消息中间件是作为Java开发工程师必须掌握的技术栈之一,本系列文章由浅入深来学习消息中间件。

本节主要学习JMS规范(Java平台上的专业技术规范)。

JMS简介

JMS,全称:Java Message Service,中文名:Java 消息服务。

JMS 是 Java 的一套 API 标准,最初的目的是为了使应用程序能够访问现有的 MOM 系统。

MOM 是 Message Oriented Middleware 的英文缩写,即为消息中间件,指的是利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成。

常见 MOM 系统包括 Apache 的 ActiveMQ、 阿里巴巴的 RocketMQ、IBM 的 MQSeries、Microsoft 的 MSMQ、BEA 的 RabbitMQ 等。

但是并非全部的 MOM 系统都遵循 JMS 规范(如RocketMQ)。基于 JMS 实现的 MOM,又被称为 JMSProvider。

常用术语介绍

在提到JMS时,我们通常会说到一些术语,解释如下:

1、消息中间件(JMS Provider)

指提供了对JMS协议的第三方组件,比如ActiveMQ就是一个消息中间件,另外比较知名的还有KAFKA, Rabbit MQ等。

2、消息模式

分为点对点(Point to Point,即P2P)和发布/订阅(Pub/Sub),对应的数据结构分别是队列(Queue)和主题(Topic)。

3、消息(Message)

通信内容的载体,其结构主要分为消息头,属性和消息体,并且根据存储结构的不同分为好几种,后面会详细提到。

4、消息生产者

产生消息的一方,在P2P模式下,指消息发送者(Sender),在P/S模式下指消息发布者(Publisher)。

5、消息消费者

接收消息的一方,对应于两种模式分别是消息接收者(Receiver)和消息订阅者(Subscriber) 。

JMS体系架构

JMS由以下元素组成:

1、JMS提供者
连接面向消息中间件的,JMS接口的一个实现。提供者可以是Java平台的JMS实现,也可以是非Java平台的面向消息中间件的适配器。

2、JMS客户
生产或消费消息的基于Java的应用程序或对象。

3、JMS生产者
创建并发送消息的JMS客户。

4、JMS消费者
接收消息的JMS客户。

5、JMS消息
包括可以在JMS客户之间传递的数据的对象

6、JMS队列
一个容纳那些被发送的等待阅读的消息的区域。队列暗示,这些消息将按照顺序发送。一旦一个消息被阅读,该消息将被从队列中移走。

7、JMS主题
一种支持发送消息给多个订阅者的机制。

JMS对象模型

JMS对象模型

JMS对象模型包含如下几个要素:

1、连接工厂。连接工厂(ConnectionFactory)是由管理员创建,并绑定到JNDI树中。客户端使用JNDI查找连接工厂,然后利用连接工厂创建一个JMS连接。

2、JMS连接。JMS连接(Connection)表示JMS客户端和服务器端之间的一个活动的连接,是由客户端通过调用连接工厂的方法建立的。

3、JMS会话。JMS会话(Session)表示JMS客户与JMS服务器之间的会话状态。JMS会话建立在JMS连接上,表示客户与服务器之间的一个会话线程。

4、JMS目的。JMS目的(Destination),又称为消息队列,是实际的消息源。

5、JMS生产者和消费者。生产者(Message Producer)和消费者(Message Consumer)对象由Session对象创建,用于发送和接收消息。

JMS消息模型

1、点对点消息模型(Point-to-Point(P2P))

JMS点对点消息模型

消息生产者生产消息发送到 queue 中,然后消息消费者从 queue 中取出并且消费消息。 消息被消费以后,queue 中不再有存储,所以消息消费者不可能消费到已经被消费的消息。

queue 支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费、其它的则不能消费此消息了。 当消费者不存在时,消息会一直保存,直到有消费消费。

2、发布/订阅模式(Pub/Sub)

JMS发布订阅消息模式

消息生产者(发布)将消息发布到 topic 中,同时有多个消息消费者(订阅)消费该消息。

和点对点方式不同,发布到 topic 的消息会被所有订阅者消费。 当生产者发布消息,不管是否有消费者。都不会保存消息 一定要先有消息的消费者,后有消息的生产者。

3、P2P 和 PUB/SUB 对比

Topic Queue
Publish Subscribe messaging 发布订阅消息 Point-to-Point 点对点
有无状态 topic 数据默认不落地,是无状态的。 Queue 数据默认会在 mq 服 务器上以文件形式保存,比如 Active MQ 一 般保存在 $AMQ_HOME\data\kahadb 下面。也可以配置成 DB 存储。
完整性保障 并不保证 publisher 发布的每条数据,Subscriber 都能接受到。 Queue 保证每条数据都能被 receiver 接收。消息不超时。
消息是否会丢失 一般来说 publisher 发布消息到某一个 topic 时,只有正在监听该 topic 地址的 sub 能够接收到消息;如果没有 sub 在监听,该 topic 就丢失了。 Sender 发送消息到目标 Queue, receiver 可以异步接收这个Queue 上的消息。Queue 上的消息如果暂时没有 receiver 来取,也不会丢失。前提是消息不超时。
消息发布接 收策略 一对多的消息发布接收策略,监听同一个 topic 地址的多个 sub 都能收到 publisher 发送的消息。Sub 接收完通知 mq 服务器 一对一的消息发布接收策略,一个 sender 发送的消息,只能有一个 receiver 接收。 receiver 接收完后,通知 mq 服务器已接收,mq 服务器对 queue 里的消息采取删除或其他操作。

JMS应用程序接口

1、ConnectionFactory 接口(连接工厂)

创建Connection对象的工厂,根据消息类型的不同,用户将使用队列连接工厂,或者主题连接工厂。

分别有QueueConnectionFactory和TopicConnectionFactory两种。

2、Destination 接口(目标)

Destination是一个包装了消息目标标识符的被管对象,消息目标是指消息发布和接收的地点,或者是队列,或者是主题。

Destination实际上就是两种类型的对象:Queue、Topic。

3、Connection 接口(连接)

Connection表示在客户端和JMS系统之间建立的链接(对TCP/IP socket的包装)

Connection可以产生一个或多个Session。跟ConnectionFactory一样,Connection也有两种类型:QueueConnection和TopicConnection。

4、Session 接口(会话)

Session是我们操作消息的接口。表示一个单线程的上下文,用于发送和接收消息。由于会话是单线程的,所以消息是连续的,就是说消息是按照发送的顺序一个一个接收的。

可以通过session创建生产者、消费者、消息等。Session提供了事务的功能。当我们需要使用session发送/接收多个消息时,可以将这些发送/接收动作放到一个事务中。同样,也分QueueSession和TopicSession。

5、MessageProducer 接口(消息的生产者)

消息生产者由Session创建,并用于将消息发送到Destination。消费者可以同步地(阻塞模式),或异步(非阻塞)接收队列和主题类型的消息。

同样,消息生产者分两种类型:QueueSender和TopicPublisher。可以调用消息生产者的方法(send或publish方法)发送消息。

6、MessageConsumer 接口(消息消费者)

消息消费者由Session创建,用于接收被发送到Destination的消息。两种类型:QueueReceiver和TopicSubscriber。

可分别通过session的createReceiver(Queue)或createSubscriber(Topic)来创建。当然,也可以session的creatDurableSubscriber方法来创建持久化的订阅者。

7、Message 接口(消息)

Message是在消费者和生产者之间传送的对象,也就是说从一个应用程序创送到另一个应用程序。一个消息有三个主要部分:

1、消息头(必须):包含用于识别和为消息寻找路由的操作设置。

2、一组消息属性(可选):包含额外的属性,支持其他提供者和用户的兼容。可以创建定制的字段和过滤器(消息选择器)。

3、一个消息体(可选):允许用户创建五种类型的消息(文本消息,映射消息,字节消息,流消息和对象消息)。消息接口非常灵活,并提供了许多方式来定制消息的内容。

8、MessageListener

消息监听器。如果注册了消息监听器,一旦消息到达,将自动调用监听器的onMessage方法。

EJB中的MDB(Message-Driven Bean)就是一种MessageListener。

JMS的消息格式

JMS消息由以下三部分组成的:

  • 消息头。

    每个消息头字段都有相应的getter和setter方法。

  • 消息属性。

    如果需要除消息头字段以外的值,那么可以使用消息属性。

  • 消息体。

    JMS定义的消息类型有TextMessage(文本消息)、MapMessage(k/v)、BytesMessage(字节流)、StreamMessage(java原始的数据流)和ObjectMessage(序列化的java对象)。

总结

本节主要学习了JMS,是Java平台上有关面向消息中间件(MOM)的技术规范,它便于消息系统中的Java应用程序进行消息交换,并且通过提供标准的产生、发送、接收消息的接口简化企业应用的开发。

延伸阅读
  1. 消息中间件(引1):JMS规范
发表评论