JMS介绍
了解MQ之前先了解什么是JMS
Java Message Service (JMS) 简介
Java Message Service (JMS) 是由 Sun Microsystems(现为 Oracle 公司的一部分)提出的一项行业标准,用于定义一套 Java 平台上的消息传递应用程序接口(API),它允许开发人员在不同的分布式环境中进行松耦合、异步通信。JMS 提供了一种标准方法来创建、发送、接收和读取消息,从而使得应用程序可以独立于特定的消息中间件(MOM)产品进行开发。
JMS 消息模型
-
点对点(P2P, Point to Point): 在这种模型中,每个消息都有一个明确的目标接收者,即一个特定的消息队列。消息生产者将消息发送至队列,消息消费者从队列中取出并处理消息。只有唯一的一个消费者会收到每条消息,通常遵循先入先出(FIFO)的原则。
-
发布/订阅(pub/sub, Publish/Subscribe): 在发布/订阅模式下,消息生产者发布消息到主题(topic),多个消息消费者可以订阅这个主题以接收相关消息。不同于点对点,一条消息发布后,所有订阅了该主题的消费者都可以接收到消息。
JMS 的作用和应用场景
在不同应用之间进行通信或者从一个系统传输数据到另外一个系统。两个应用程序之间,或分布式系统中发送消息,进行异步通信。
这类问题有很多解决方案 ,比如DB、SOA、Socket通信、RMI,等,但我们需要根据项目的限制以及功能和性能的需要作出选择。
-
异步通信:JMS 支持异步消息处理,意味着发送方不必等待接收方响应即可继续执行其他任务,提高了系统的响应速度和吞吐量。
-
分布式系统集成:在复杂的分布式架构中,JMS 可以简化各个组件之间的交互,通过消息传递解耦系统组件,使它们能够在独立的时间和空间尺度上工作。
-
高可用性与可靠性:JMS 规范支持消息确认、持久化和事务处理等功能,有助于确保消息在传输过程中即使面临网络故障或其他系统问题也能得到可靠处理。
举例来说,在实际应用中,当两个应用程序间需要进行低耦合、高稳定性的通信时,如企业级应用间的流程协同、状态更新或事件通知等,JMS 可作为一个理想的选择。
同步通信对比
相比之下,同步通信要求调用方在收到响应前保持阻塞状态,而使用 JMS 进行异步通信则允许系统更灵活地处理负载变化,并且能够更好地适应大规模和复杂度较高的分布式系统环境,尤其是在处理不希望立即得到响应或无法确定接收端是否在线的情况时。
{{{width="auto" height="auto"}}}
JMS 模型详解
-
点对点模型 (Point-to-Point, P2P) (基于队列)
- 特点: 每个消息被设计为一对一的通信方式,即每条消息只有一个明确的接收者。
- 队列: 生产者将消息发送至一个队列,队列作为消息存储容器,确保消息在没有消费者消费的情况下暂存。
- 消费行为: 消费者从队列中获取消息,一旦消息被一个消费者成功消费,队列中该消息即被移除,不会被其他消费者再次获取。
- 同步阻塞: 如果队列中没有消息可供消费,消费者会处于阻塞等待状态,直到有新的消息到达。
-
发布/订阅模型 (Publish/Subscribe, Pub/Sub) (基于主题Topic)
- 特点: 每个消息可以被多个订阅该主题的消费者同时接收,实现一对多或多对多的通信方式。
- 主题(Topic): 生产者将消息发布到一个主题,所有订阅了该主题的消费者都能接收到消息。
- 订阅行为: 消费者在接收消息之前必须先订阅主题,仅能消费订阅后发布的消息。
- 持久化订阅者: 特殊类型的订阅者,即使在网络断开期间,仍然保留其订阅状态。当网络恢复时,消息服务器会重新投递在此期间发布的、符合订阅条件的消息给这些持久化订阅者,确保消息不会丢失。
总结起来,点对点模型强调的是单个消息的定向传递,适用于一次性、有序处理的任务;而发布/订阅模型则注重消息的广播和实时性,适合于多个接收者同时关注同一类信息的场景。
JMS消息发送模式
{{{width="auto" height="auto"}}}
Topic 发送模式
{{{width="auto" height="auto"}}}
JMS公共接口
JMS 公共 | 点对点域 | 发布/订阅域 |
---|---|---|
ConnectionFactory | QueueConnectionFactory | TopicConnectionFactory |
Connection | QueueConnection | TopicConnection |
Destination | Queue | Topic |
Session | QueueSession | TopicSession |
MessageProducer | QueueSender | TopicPublisher |
MessageConsumer | QueueReceiver | TopicSubscriber |
JMS的基本构建块
-
连接工厂 (ConnectionFactory)
- 功能:连接工厂是应用程序用于创建JMS连接的工厂对象,它代表了到JMS提供者的连接参数集合。例如,在使用ActiveMQ时,开发者会使用
ActiveMQConnectionFactory
来创建一个连接实例。
- 功能:连接工厂是应用程序用于创建JMS连接的工厂对象,它代表了到JMS提供者的连接参数集合。例如,在使用ActiveMQ时,开发者会使用
-
连接 (Connection)
- 定义:JMS Connection是一个对象,它封装了客户端与JMS Provider之间的逻辑连接,提供了与消息中间件建立和管理物理连接的方法。客户端通过连接工厂创建连接,从而得以与消息服务交互。
-
会话 (Session)
- 描述:JMS Session是生产和消费消息的单线程上下文环境,它是在连接的基础上创建的。在一个会话内,可以创建消息生产者和消费者,以及消息本身。会话支持事务处理,但需要注意的是,在同一个会话中,消息的生产和消费操作不能在同一个事务中混合进行。
-
生产者 (MessageProducer)
- 角色:MessageProducer是由会话对象创建的,专门用于向目标目的地发送消息的实体。生产者负责将消息有效地路由到指定的目的地,如队列或主题。
-
消费者 (MessageConsumer)
- 角色:MessageConsumer同样是由会话创建的,其目的是为了从指定的目的地接收和消费消息。消费者可以按照不同的消息筛选策略来监听和处理到达的目的地的消息。
-
消息 (Message)
- 结构:JMS消息是包含消息头、消息体和其他可选扩展属性的数据载体。JMS规范定义了几种不同类型的消息,包括:
- TextMessage:包含文本字符串的消息。
- MapMessage:包含一组名称/值对的映射消息。
- BytesMessage:包含原始字节流的消息。
- StreamMessage:包含一系列基本数据类型的值组成的流消息。
- ObjectMessage:包含可序列化的Java对象的消息。
- 结构:JMS消息是包含消息头、消息体和其他可选扩展属性的数据载体。JMS规范定义了几种不同类型的消息,包括:
-
目的地 (Destination)
- 概念:Destination是消息发送和接收的终结点,它是消息的源头或目标。有两种基本类型的目的地:
- 消息队列 (Queue):对应于点对点(P2P)模型,消息只能被一个消费者消费。
- 消息主题 (Topic):对应于发布/订阅(Publish/Subscribe)模型,消息可以被多个订阅该主题的消费者接收。
- 概念:Destination是消息发送和接收的终结点,它是消息的源头或目标。有两种基本类型的目的地:
JMS消息发送时序图
{{{width="auto" height="auto"}}}
JMS消息发送与接收开发流程
1. 生产者(Producer)开发流程(ProducerTool.java)
-
步骤1:创建Connection
- 使用给定的URL、用户名(user)和密码(password)初始化并创建一个JMS Connection对象,该对象表示与消息中间件的连接。
-
步骤2:创建Session
- 基于已创建的Connection对象,创建一个新的Session实例,并在此过程中指定是否启用事务支持以及确认模式(如AUTO_ACKNOWLEDGE、CLIENT_ACKNOWLEDGE等)。
-
步骤3:创建Destination对象
- 根据指定的主题(Subject)名称,创建Destination对象,这可能是Queue(点对点消息)或者是Topic(发布/订阅消息)。Producer和Consumer都将依据此Destination来定位消息的发送与接收目标。
-
步骤4:创建MessageProducer
- 使用上述Destination对象来创建一个MessageProducer实例,并可根据需求设置消息的持久化模式(持久或非持久)。
-
步骤5:发送消息到队列或主题
- 创建并填充TextMessage或其他类型的消息内容。
- 使用MessageProducer的send方法将消息发送至Destination,这样消息就被发布到了指定的队列或主题中。
2. 消费者(Consumer)开发流程(ConsumerTool.java)
-
步骤1:实现MessageListener接口
- 创建一个消费者类并实现MessageListener接口,其中包含核心方法
onMessage(Message message)
,该方法会在接收到消息时自动调用以处理传入的消息。
- 创建一个消费者类并实现MessageListener接口,其中包含核心方法
-
步骤2:创建Connection
- 同样基于URL、用户名和密码创建一个JMS Connection对象。若采用持久订阅模式,需为Connection设置一个唯一的ClientID。
-
步骤3:创建Session和Destination
- 创建与Producer相同的Session对象,并根据同样的主题名称创建Destination对象。
-
步骤4:创建ReplyProducer(可选)
- 若消费者需要回复消息,则创建一个MessageProducer对象,用于向消息的发送者发送响应消息。
-
步骤5:创建MessageConsumer
- 根据Destination创建MessageConsumer对象,并可能设置相关的消息监听器或订阅选项。
-
步骤6:消费消息
- 实现MessageListener接口的
onMessage()
方法,该方法将在消息到达时自动触发,从MessageConsumer接收并处理消息。在此过程中,消费者可以解析消息内容,并根据需要通过ReplyProducer向Producer发送反馈信息或其他响应消息。
JMS消息订阅者流程图
{{{width="auto" height="auto"}}}
- 实现MessageListener接口的
JMS消息的事务处理及消费方式
1. 事务创建与应答确认
-
创建事务Session:
使用createSession(boolean paramA, int paramB)
方法创建一个JMS会话。其中:-
paramA
:布尔值,决定是否开启事务支持。设置为true
表示启用事务(SESSION_TRANSACTED
),此时会话将参与到全局事务管理中,消息的发送和确认将与事务绑定。 -
paramB
:当paramA
为false
时,该参数用于设置应答模式(Acknowledgement Mode),可以选择以下三种模式之一:Session.AUTO_ACKNOWLEDGE
:自动确认模式。一旦消息被消费者成功接收(receive()
方法返回或MessageListener.onMessage()
方法执行完毕),会话将自动确认消息。Session.CLIENT_ACKNOWLEDGE
:客户端确认模式。在这种模式下,消息被接收后,客户端程序必须手动调用javax.jms.Message
对象的acknowledge()
方法来确认消息的接收,只有确认后,JMS服务器才会删除消息。Session.DUPS_OK_ACKNOWLEDGE
:允许重复确认模式。一旦消息被处理完,会话将自动确认消息,但如果在确认之前会话关闭,可能会导致消息重发。对于重复的消息,JMS提供商会将消息头中的JMSRedelivered
字段设为true
。
-
2. 消费者的消费方式
JMS消费者可以通过以下两种方式进行消息消费:
-
同步消费:
消费者通过调用receive()
方法从目的地(队列或主题)中显式提取消息。receive()
方法可以设定超时时间,如果没有消息到达则会阻塞等待直至消息到达或超时。 -
异步消费:
客户端可以为消费者注册一个消息监听器,通过实现MessageListener
接口并在onMessage(Message message)
方法中定义消息到达时的处理逻辑。当消息到达时,JMS提供商会自动调用监听器的onMessage()
方法来处理消息,这种方式无需主动调用receive()
方法,实现了消息的异步处理。
JMS的通信机制
{{{width="auto" height="auto"}}}
Topic | Queue | |
---|---|---|
概要 | Publish Subscribe messaging 发布订阅消息 | Point-to-Point 点对点 |
有无状态 | topic数据默认不落地,是无状态的。 | Queue数据默认会在mq服务器上以文件形式保存,比如Active MQ一般保存在$AMQ_HOME\data\kr-store\data下面。也可以配置成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里的消息采取删除或其他操作。 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!