Day10_01_消息队列之JMS

JMS

一. JMS 概述

The Java Message Service (JMS) API is a messaging standard that allows application components based on the Java Platform Enterprise Edition (Java EE) to create, send, receive, and read messages. It enables distributed communication that is loosely coupled, reliable, and asynchronous.

JMS(JAVA Message Service,Java消息服务)API是一个消息服务的标准或者说是规范,允许应用程序组件基于JavaEE平台创建、发送、接收和读取消息.它使分布式通信耦合度更低,消息服务更加可靠以及异步性.

二. JMS 简介

JMS是Java的消息服务,JMS的客户端之间可以通过JMS服务进行异步的消息传输.

1. JMS消息模型

1️⃣.Point-to-Point(P2P);

2️⃣.Publish/Subscribe(Pub/Sub)
即点对点和发布订阅模型.

三. P2P--点对点模式

P2P模式图

1. P2P模式涉及到的概念

  • 消息队列(Queue);

  • 发送者(Sender);

  • 接收者(Receiver);

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

    扫描二维码关注公众号,回复: 6481830 查看本文章

2. P2P的特点

1️⃣.每个消息只有一个消费者(Consumer)(即一旦被消费,消息就不再在消息队列中);

2️⃣.发送者和接收者之间在时间上没有依赖性,也就是说当发送者发送了消息之后,不管接收者有没有正在运行,它不会影响到消息被发送到队列;

3️⃣.接收者在成功接收消息之后需向队列应答成功.

如果你希望发送的每个消息都应该被成功处理的话,那么你需要P2P模式.

四. Pub/Sub--发布/订阅模式

Pub/Sub模式图

1. P/S模式涉及到的概念

  • 主题(Topic);

  • 发布者(Publisher);

  • 订阅者(Subscriber);

  • 客户端将消息发送到主题,多个发布者将消息发送到Topic,系统将这些消息传递给多个订阅者.

2. Pub/Sub的特点

1️⃣.每个消息可以有多个消费者;

2️⃣.发布者和订阅者之间有时间上的依赖性.针对某个主题(Topic)的订阅者,它必须创建一个订阅者之后,才能消费发布者的消息,而且为了消费消息,订阅者必须保持运 行的状态;

3️⃣.为了缓和这样严格的时间相关性,JMS允许订阅者创建一个可持久化的订阅.这样,即使订阅者没有被激活(运行),它也能接收到发布者的消息.

如果你希望发送的消息可以不被做任何处理,或者被一个消息者处理,或者可以被多个消费者处理的话,那么可以采用Pub/Sub模型.

五. 消息的消费方式

在JMS中,消息的产生和消费是异步的.对于消费来说,JMS的消息者可以通过两种方式来消费消息.

1. 同步

订阅者或接收者调用receive()方法来接收消息,receive()方法在能够接收到消息之前(或超时之前)将一直阻塞; 

2. 异步

订阅者或接收者可以注册为一个消息监听器.当消息到达之后,系统自动调用监听器的onMessage()方法.

六. JMS消息系统的优点

我们先来看看下图,应用程序A将Message发送到服务器上,然后应用程序B从服务器中接收A发来的消息,通过这个图我们一起来分析一下JMS的好处:

1️⃣.提供消息灵活性;
2️⃣.松散耦合;
3️⃣.异步性.

七. JMS编程模型API

1. ConnectionFactory

创建Connection对象的工厂,针对两种不同的JMS消息模型,分别有QueueConnectionFactory和TopicConnectionFactory两种.可以通过JNDI来查找ConnectionFactory对象.

2. Destination

Destination的意思是消息生产者的消息发送目标或者说消息消费者的消息来源.对于消息生产者来说,它的Destination是某个队列(Queue)或某个主题(Topic);对于消息消费者来说,它的Destination也是某个队列或主题(即消息来源).

所以,Destination实际上就是两种类型的对象:Queue、Topic可以通过JNDI来查找Destination.

3. Connection

Connection表示在客户端和JMS系统之间建立的链接(对TCP/IP socket的包装),Connection可以产生一个或多个Session.跟ConnectionFactory一样,Connection也有两种类型:QueueConnection和TopicConnection.

4. Session

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

5. 消息的生产者

消息生产者由Session创建,并用于将消息发送到Destination.同样,消息生产者分两种类型:QueueSender和TopicPublisher.可以调用消息生产者的方法(send或publish方法)发送消息.

6. 消息消费者

消息消费者由Session创建,用于接收被发送到Destination的消息.两种类型:QueueReceiver和TopicSubscriber.可分别通过Session的createReceiver(Queue)或createSubscriber(Topic)来创建.当然,也可以由Session的creatDurableSubscriber方法来创建持久化的订阅者.

7. MessageListener

消息监听器.如果注册了消息监听器,一旦消息到达,将自动调用监听器的onMessage方法.EJB中的MDB(Message-Driven Bean)就是一种MessageListener.

八. 消息队列的流派

1. 什么是 MQ

Message Queue(MQ),消息队列中间件.很多人都说:MQ 通过将消息的发送和接收分离来实现应用程序的异步和解偶,这个给人的直觉是——MQ 是异步的,用来解耦的,但是这个只是 MQ 的效果而不是目的.MQ 真正的目的是为了通讯,屏蔽底层复杂的通讯协议,定义了一套应用层的、更加简单的通讯协议.一个分布式系统中两个模块之间通讯要么是 HTTP,要么是自己开发的 TCP,但是这两种协议其实都是原始的协议.HTTP 协议很难实现两端通讯——模块 A 可以调用 B,B 也可以主动调用 A,如果要做到这个两端都要背上 WebServer,而且还不支持长连接(HTTP 2.0 的库根本找不到).TCP 就更加原始了,粘包、心跳、私有的协议,想一想头皮就发麻.MQ 所要做的就是在这些协议之上构建一个简单的“协议”——生产者/消费者模型.MQ 带给我的“协议”不是具体的通讯协议,而是更高层次通讯模型.它定义了两个对象——发送数据的叫生产者;接收数据的叫消费者,提供一个 SDK 让我们可以定义自己的生产者和消费者实现消息通讯而无视底层通讯协议.

2. 有 Broker(服务器) 的 MQ

这个流派通常有一台服务器作为 Broker,所有的消息都通过它中转.生产者把消息发送给它就结束自己的任务了,Broker 则把消息主动推送给消费者(或者消费者主动轮询).

2.1 重 Topic

kafka、JMS(ActiveMQ)就属于这个流派,生产者会发送 key 和数据到 Broker,由 Broker 比较 key 之后决定给哪个消费者.这种模式是我们最常见的模式,是我们对 MQ 最多的印象.在这种模式下一个 topic 往往是一个比较大的概念,甚至一个系统中就可能只有一个 topic,topic 某种意义上就是 queue,生产者发送 key 相当于说:“hi,把数据放到 key 的队列中”.

虽然架构一样,但是 kafka 的性能要比 jms 的性能高很多倍,所以基本这种类型的 MQ 只有 kafka 一种备选方案.如果你需要一条暴力的数据流(在乎性能而非灵活性)那么 kafka 是最好的选择.

2.2 轻 Topic

这种的代表是 RabbitMQ(AMQP).生产者发送 key 和数据,消费者定义订阅的队列,Broker 收到数据之后会通过一定的逻辑计算出 key 对应的队列,然后把数据交给队列.

这种模式下解耦了 key 和 queue,在这种架构中 queue 是非常轻量级的(在 RabbitMQ 中它的上限取决于你的内存),消费者关心的只是自己的 queue;生产者不必关心数据最终给谁只要指定 key 就行了,中间的那层映射在 AMQP 中叫 exchange(交换机).

AMQP 中有四种 exchange:

  • 1️⃣.Direct exchange: key 就等于 queue;

  • 2️⃣.Fanout exchange: 无视 key,给所有的 queue 都来一份;

  • 3️⃣.Topic exchange: key 可以用“宽字符”模糊匹配 queue;

  • 4️⃣.Headers exchange: 无视 key,通过查看消息的头部元数据来决定发给那个 queue(AMQP 头部元数据非常丰富而且可以自定义).

这种结构的架构给通讯带来了很大的灵活性,我们能想到的通讯方式都可以用这四种 exchange 表达出来.如果你需要一个企业数据总线(在乎灵活性)那么 RabbitMQ 绝对的值得一用.

3. 无 Broker 的 MQ

无 Broker 的 MQ 的代表是 ZeroMQ.该作者非常睿智,他非常敏锐的意识到——MQ 是更高级的 Socket,它是解决通讯问题的.所以 ZeroMQ 被设计成了一个“库”而不是一个中间件,这种实现也可以达到——没有 Broker 的目的.

节点之间通讯的消息都是发送到彼此的队列中,每个节点都既是生产者又是消费者.ZeroMQ 做的事情就是封装出一套类似于 Socket 的 API 可以完成发送数据,读取数据.

ZeroMQ 其实就是一个跨语言的、重量级的 Actor 模型邮箱库.你可以把自己的程序想象成一个 Actor,ZeroMQ 就是提供邮箱功能的库;ZeroMQ 可以实现同一台机器的 RPC 通讯也可以实现不同机器的 TCP、UDP 通讯,如果你需要一个强大的、灵活、野蛮的通讯能力,别犹豫 ZeroMQ.

猜你喜欢

转载自blog.csdn.net/syc000666/article/details/91492580