本章知识点:

  • 企业消息和面向消息的中间件
  • 理解 Java Message Service(JMS)
  • 使用 JMS APIs 发送和接收消息
  • 消息驱动 bean 的一个例子

简介

一般来说,掌握了企业级消息的历史背景,你就可以更好地理解 ActiveMQ 背后的思想。讨论完企业级消息后,我们将为你展示几个小例子来讲述 JMS。本章的宗旨是带你回顾企业级消息和 JMS 规范。如果你对这些主题已经非常熟悉了,那么你可以跳过本章直接阅读下一章。

曾几何时,每个软件开发者都需要处理应用间的相互通信以及传输数据。对于这类问题,虽然有各式各样的解决方案,但也是取决于你的一致性要求,怎么实现通信从来都是一项重要的需考虑点。商业应用通常要求一致性,这也就影响了最终方案的性能,伸缩性,可靠性等指标。我们今天使用的很多系统都要求这样的一致性,包括:ATMs,航空公司票务预定系统,信用卡系统,销售点系统以及电信系统等。没有这些系统的话,我们今天又是过着怎样的生活呢?

现在想想这些系统是极大地改变了我们的生活,为我们提供了很多的便利。这些系统拥有非常高的可靠性和安全性。这些应用的背后,是由分布式系统,通过事件驱动和使用消息来进行通信组成的。

什么是面向消息的中间件?

这节没啥好废话的。

什么是 Java Message Service?

不得不说,当年的太阳微系统公司真牛逼,开发了 Java 语言不说,还整出了那么多业界规范。

在 JMS 规范中定义的概念有:

  • JMS client:100% 用纯 Java 写的应用用于发送和接收消息;
  • Non-JMS client:使用 JMS provider 的原生客户端 API 写的应用,用于代替 JMS client 来发送和接收消息;
  • JMS producer:创建并发送消息的客户端应用;
  • JMS consumer:接收并处理消息的客户端应用;
  • JMS provider:JMS 接口的实现,一般也是用纯 Java 写的;
  • JMS messge:JMS 中最基本的概念;被 JMS 客户端发送和接收;
  • JMS domains:消息分发的两种风格,即:点对点(point-to-point)和发布/订阅(publish/subscribe);
  • Administered objects:JMS 对象的默认配置,也包含特定提供者的配置数据。客户端一般通过 JNDI 来访问这些配置;
  • Connection factory:客户端使用连接工厂创建到 JMS provider 的连接;
  • Destination:消息被存放的位置,生产者发送消息到这里,消费者从这里消费消息;

JMS 规范

JMS clients

JMS clients 使用 JMS API 来和 JMS provider 进行交互。就像使用 JDBC API 访问关系型数据库一样,JMS clients 使用标准的 JMS API 访问消息服务。许多 JMS providers(包括 ActiveMQ)都提供了 JMS 规范以外的附赠特性,但是使用纯 JMS client 是无法使用这些附赠特性的。想要使用一个 JMS provider 的额外特性,必须得使用特定的 JMS client,但使用了特定的 JMS client 之后就不能再兼容其他 JMS provider了。

JMS 客户端使用 MessageProducer 和 MessageConsumer 接口来发送和接收消息。因此,JMS provider 必须得实现这些接口。发送消息的 JMS client 就是生产者,接收消息的 JMS client 就是消费者。同一个 JMS client 完全可以即当作生产者,也当作消费者。

JMS 生产者

JMS client 使用 JMS 中的 MessageProducer 类来发送消息到一个 destination。当使用 Session.createProducer() 方法来创建一个 producer 时,producer 需要设置一个默认的地址。但是这个地址可以使用 MessageProducer.send() 方法来覆盖。MessageProducer 接口如下:

void setDisableMessageID(boolean value) throws JMSException;

    boolean getDisableMessageID() throws JMSException;

    void setDisableMessageTimestamp(boolean value) throws JMSException;

    boolean getDisableMessageTimestamp() throws JMSException;

    void setDeliveryMode(int deliveryMode) throws JMSException;

    int getDeliveryMode() throws JMSException;

    void setPriority(int defaultPriority) throws JMSException;

    int getPriority() throws JMSException;

    void setTimeToLive(long timeToLive) throws JMSException;

    long getTimeToLive() throws JMSException;

    Destination getDestination() throws JMSException;

    void close() throws JMSException;

    void send(Message message) throws JMSException;

    void send(Message message, int deliveryMode, int priority, long timeToLive)
throws JMSException; void send(Destination destination, Message message) throws JMSException; void send(
Destination destination,
Message message,
int deliveryMode,
int priority,
long timeToLive)
throws JMSException;

JMS 消费者

JMS clients 使用 JMS 中的 MesssageConsumer 类来从一个 destination 消费消息。MessageConsumer 既可以使用 receive() 方法来同步消费消息,也可以通过提供一个 MessageListener 的实现来异步消费消息。MessageListener.onMessage() 方法将在有消息到达 destination 时被调用。MessageConsumer 接口如下:

package javax.jms;

/**
* @version $Rev: 467553 $ $Date: 2006-10-25 06:01:51 +0200 (Wed, 25 Oct 2006) $
*/
public interface MessageConsumer {
String getMessageSelector() throws JMSException; MessageListener getMessageListener() throws JMSException; void setMessageListener(MessageListener listener) throws JMSException; Message receive() throws JMSException; Message receive(long timeout) throws JMSException; Message receiveNoWait() throws JMSException; void close() throws JMSException;
}

MessageConsumer 类本身无法设置 destination。作为替代的是,我们在使用Session.createConsumer()方法创建消费者时,可以设置 destination。

Non-JMS clients

正如前面提到的,一个 non-JMS 客户端使用一个 JMS 提供者的原生客户端 API ,而不是使用 JMS API。这两者之间有很大区别,因为使用原生客户端 API 可以提供一些额外的特性。一些 non-JMS APIs 包含了除了 Java RMI 之外的 CORBA IIOP 协议或者其他的一些原生协议。一般来说,在 JMS 规范诞生之前的消息生产者都会提供一个原生客户端 API,但是许多 JMS 提供者也会提供一个 non-JMS client API。

The JMS provider

一个 JMS provider 是实现了 JMS API 消息中间件。这种实现可以通过标准的 JMS API 来访问消息中间件。

The JMS message

消息是 JMS 规范中最重要的概念。一个消息由消息头和消息体 payload 组成,其中消息头的内容是此消息的元数据,消息体的内容可以为任意类型的内容,包括文本类型和二进制类型。消息体一般很简单灵活,复杂的是消息头。

消息头

JMS 消息支持一套标准的消息头字段列表,JMS 标准 API 提供了访问这些头字段的方法。消息头将被 send() 方法自动调用:

  • JMSDestination:即消息的 destination。对于一个需要从多个 destination 消费消息的客户端,这个字段将是非常有用的;
  • JMSDeliveryMode:JMS 支持两种类型的分发模式:持久型和非持久型。默认的分发模式是持久型。持久型的消息只会分发一次,且必须分发一次;非持久型消息最多被分发一次,如果消息丢失则分发零次。分发模式可以由生产者设置,也可以由每个消息单独设置。
  • JMSExpiration:消息的超时时间。超时时间的值可以由 MessageProducer.setTimeToLive() 方法设置,也可以由 MessageProducer.send() 方法设置。此值默认为 0,表示从不过期。
  • JMSMessageID:消息的唯一标识。设置了这个字段会产生额外的开销,所以可以通过 MessageProducer.setDisableMessageId() 方法设置其为 null 来降低开销。
  • JMSPriority:消息优先级。优先级高的消息将先被分发。
  • JMSTimestamp:代表了生产者发送这条消息的时间,和 JMSMessageID 一样,会产生额外的开销,如果不需要可以通过调用 Producer.setDisableMessageTimestamp() 方法将其设置为 0。

客户端可选消息头

  • JMSCorrelationID:由于关联当前消息到之前的消息。这个头部字段通常用于关联一个响应消息到相应的请求消息。JMSCorrelationID 的值可以是下面几种:一个特定的提供者指定的消息 ID,一个应用指定的字符串,一个提供者提供的原生的字节数组。
  • JMSReplyTo:用于提供一个响应消息需要发送的 destination。这个头部字段通常用于请求、响应模式的消息。
  • JMSType:消息类型。如果消息体是 Java 类型,则此字段什么都不做。

JMS 提供者可选消息头

  • JMSRedelivered:分发出去的消息未收到确认是否重新发送。

消息属性消息头

这些消息头属于自定义消息头。

消息选择器

选择器可以用于消费者中只接收含有特定属性且这些属性的值符合选择器条件的消息。

消息体

JMS 规范定义了六种消息类型:

  1. Message:最基本的消息,此消息没有消息体,只有消息头和消息属性;
  2. TextMessage:消息体是字符串;
  3. MapMessage:消息体是想 Map 一样的键值对集合;
  4. ByetsMessage:消息体是字节数组;
  5. StreamMessage:消息体是 Java 原始类型的流;
  6. ObjectMessage:消息体是序列化后的 Java 对象;

JMS domains

终于到了我一直糊涂的两种模式:点对点和发布/订阅了。

点对点模式

点对点模式就是使用了队列,可以有多个生产者生产消息,该队列也可以有多个消费者,但每个消息只会被一个消费者消费掉,提供者通过轮询来发送每一个消息到每一个消费者。

发布/订阅模式

发布订阅模式就牛逼了,应该是和每个订阅的消费者都建立了一个队列,然后每个到达的消息都会被分发给每个消费者。还有更牛逼的一种是持久化订阅模式,也就是说就算某个消费者掉线了,提供者也得负责把该分发给该消费者的消息持久化保留起来。当这个消费者再次上线后,还是可以接收到它掉线期间提供者分发的消息。

那这里就会有一个问题,如果有个消费者持久化订阅了某个主题,那么不管以后这个消费者是否存在,提供者都得为它保留着未分发的消息啦?当然不是这样的,如果不想提供者一直为它保留消息,需要这个消费者自己退订这个主题啦!

Administered objects

JMS 规范定义了两种类型的 administered objects:ConnectionFactory 和 Destination。

使用 JMS APIs 创建 JMS 应用

两个很简单的小例子。

读完第二章,才发现这本书真的很好很强大啊,真是学习 JMS,ActiveMQ 必读之物啊!

理解面向消息的中间件和 JMS的更多相关文章

  1. 理解面向消息中间件及JMS 以及 ActiveMQ例子

    为了帮助你理解ActiveMQ的意义,了解企业消息传送背景和历史是很重要的.讨论完企业消息传送,你将可以通过一个小例子了解JMS及其使用.这章的目的是简要回顾企业消息传送及JMS规范.如果你已经熟悉这 ...

  2. 基于硬件的消息队列中间件 Solace 简介之二

    前言...... 前面简单介绍了Solace来自于哪家公司, 主要能做哪些事情. 本篇主要进一步介绍Solace作为消息传递的中间件如何工作的. 传统意义上来讲, 每当我们谈到消息中间件时, 首先想到 ...

  3. 常用的消息队列中间件mq对比

    原文地址:https://blog.csdn.net/qq_30764991/article/details/80239076 消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量 ...

  4. java消息服务学习之JMS概念

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

  5. iOS runtime探究(二): 从runtime開始深入理解OC消息转发机制

    你要知道的runtime都在这里 转载请注明出处 http://blog.csdn.net/u014205968/article/details/67639289 本文主要解说runtime相关知识, ...

  6. 初试kafka消息队列中间件一 (只适合初学者哈)

    初试kafka消息队列中间件一 今天闲来有点无聊,然后就看了一下关于消息中间件的资料, 简单一点的理解哈,网上都说的太高大上档次了,字面意思都想半天: 也就是用作消息通知,比如你想告诉某某你喜欢他,或 ...

  7. MQ消息队列(2)—— Java消息服务接口(JMS)

    一.理解JMS   1.什么是JMS?         JMS即Java消息服务(Java Message Service)应用程序接口,API是一个消息服务的标准或者说是规范,允许应用程序组件基于J ...

  8. c#开源消息队列中间件EQueue 教程

    一.简介 EQueue是一个参照RocketMQ实现的开源消息队列中间件,兼容Mono,具体可以参看作者的文章<分享一个c#写的开源分布式消息队列equeue>.项目开源地址:https: ...

  9. Java消息队列ActiveMQ (一)--JMS基本概念

    摘要:The Java Message Service (JMS) API is a messaging standard that allows application components bas ...

随机推荐

  1. 小程序html 显示 图片处理

    let arr = [] for (const v of r.data.data ){ // v.content = v.content.replace(/<img/g ,' <image ...

  2. JavaSctipt语句for循环的思考

    一.语法 for (语句 1; 语句 2; 语句 3) { 被执行的代码块; } 语句 1: 在循环(代码块)开始前执行, 可选. 语句 2: 定义运行循环(代码块)的条件, 可选, 如果省略了语句 ...

  3. MySQL权限系统(三).权限表 Grant Tables

    7.2.2 Grant Tables 授权表 The mysql system database includes several grant tables that contain informat ...

  4. Python 是怎么火起来的?

    Python 之父 Guido 正在设计 Python 语言,结果家里突然潜入一条大蟒蛇,一番激烈斗争,大蟒蛇把 Guido 叔生吞进肚,并洋洋自得:So Who is Guido Van Rossu ...

  5. ApexSQL Recover 恢复一个被drop的表的数据

    没有备份的情况下恢复一个被drop的表的数据 ApexSQL Recover 恢复一个被drop的表的数据 转自:https://solutioncenter.apexsql.com/zh/%E6%B ...

  6. Maven学习笔记—安装和配置

    Maven的安装和配置 1 在windows上安装maven 1.1 下载maven 访问maven的下载页面:http://maven.apache.org/download.cgi,选择版本下载即 ...

  7. redis3.2.11单机多实例集群部署并测试连接情况

    配置准备: redis3.2.11安装配置规划 机器 192.168.169.135(本机虚拟机) 系统 Red Hat Enterprise Linux Server release 6.4 (Sa ...

  8. 1.2 使用电脑测试MC20模块的GPS功能测试

    需要准备的硬件 MC20开发板 1个 https://item.taobao.com/item.htm?id=562661881042 GSM/GPRS天线 1根 https://item.taoba ...

  9. gearman mysql持久化

    gearman 创建Mysql持久化队列的方式如下: 启动gearman,命令如下: gearmand命令: -b, –backlog=BACKLOG 连接请求队列的最大值 -d, –daemon D ...

  10. Eclipse 输出的文本乱码

    Version: Mars.2 Release (4.5.2)Build id: 20160218-0600 在使用时,发现文本编辑器中的文字出现了乱码.然后在项目的Properties->&g ...