MQ--消息协议

MQ--消息协议

  • 1.AMQP
    • 1.1介绍
    • 1.2主要概念
    • 1.3核心组件的生命周期
      • 1.3.1消息的生命周期
      • 1.3.2交换器的生命周期
      • 1.3.3 队列的生命周期
    • 1.4功能命令
      • 1.4.1Model Layer模型层
      • 1.4.2Session Layer会话层
      • 1.4.3Transport Layer传输层
    • 1.5消息数据格式
  • 2.MQTT
    • 2.1介绍
    • 2.2主要概念
      • 2.2.1网络连接(Network Connection)
      • 2.2.2应用消息(Application Message)
      • 2.2.3主题(Topic)
      • 2.2.4负载(Payload)
      • 2.2.5客户端(Client)
      • 2.2.6服务器(Server)
      • 2.2.7会话(Session)
      • 2.2.8订阅(Subscription)
      • 2.2.9主题名(Topic Name)
      • 2.2.10主题过滤器(Topic Filter)
  • 3STOMP
    • 3.1主要概念
    • 3.2COMMAND
  • 4 XMPP
    • 4.1介绍
    • 4.2基本概念
    • 4.3通信过程
  • 5JMS
    • 5.1介绍
    • 5.2体系架构
    • 5.3基本概念
    • 5.4具体到JMS应用
    • 5.5编程接口
  • 6.点对点实例(JMS)
    • 6.1下载jar包
    • 6.2新建model
    • 6.3导入包
    • 6.4下载源码
    • 6.5导入源码
    • 6.6创建生产者客户端
    • 6.7创建消费者客户端
    • 6.8启动服务端
    • 6.9执行生产者
    • 6.10执行消费者
    • 6.11在执行一次生产者
    • 6.12关闭服务
  • 7.点对点实例(JMS2.0)
    • 7.1下载jar包
    • 7.2新建model
    • 7.3导入包
    • 7.4创建生产者客户端
    • 7.5创建消费者客户端
    • 7.6创建实例
    • 7.7启动服务
    • 7.8访问管理界面
    • 7.9执行生产者
    • 7.10执行消费者
    • 7.11执行多次生产者
    • 7.12关闭服务

1.AMQP

1.1介绍

AMQP,即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。Erlang中的实现有 RabbitMQ等。
1.3. 摘要
1.3.1. 什么是AMQP
高级消息队列协议使得遵从该规范的客户端应用和消息中间件服务器的全功能互操作成为可能。
1.3.2. 为什么要用AMQP
我们的目标是实现一种在全行业广泛使用的标准消息中间件技术,以便降低企业和系统集成的开销,并且向大众提供工业级的集成服务。
我们的宗旨是通过AMQP,让消息中间件的能力最终被网络本身所具有,并且通过消息中间件的广泛使用发展出一系列有用的应用程序。
1.3.3. AMQP的范围
为了完全实现消息中间件的互操作性,需要充分定义网络协议和消息代理服务的功能语义。
因此,AMQP定义网络协议和代理服务如下:
一套确定的消息交换功能,也就是“高级消息交换协议模型”。AMQP模型包括一套用于路由和存储消息的功能模块,以及一套在这些模块之间交换消息的规则。
一个网络线级协议(数据传输格式),客户端应用可以通过这个协议与消息代理和它实现的AMQP模型进行交互通信。
可以只实现AMQP协议规范中的的部分语义,但是我们相信明确的描述这些语义有助于理解这个协议。
【以上来自百度百科】
高级消息队列协议即Advanced Message Queuing Protocol(AMQP)是一个用于统一面向消息中间件实现的一套标准协议,其设计目标是对于消息的排序、路由(包括点对点和订阅-发布)、保持可靠性、保证安全性[1]。高级消息队列协议保证了由不同提供商发行的客户端之间的互操作性。与先前的中间件标准(如Java消息服务),在特定的API接口层面和实现行为进行了统一不同,高级消息队列协议关注于各种消息如何作为字节流进行传递。因此,使用了符合协议实现的任意应用程序之间可以保持对消息的创建、传递。
概述
高级消息队列协议是一种二进制应用层协议,用于应对广泛的面向消息应用程序的支持。协议提供了消息流控制,保证的一个消息对象的传递过程,如至多一次、保证多次、仅有一次等,和基于SASL和TLS的身份验证和消息加密.

高级消息队列协议对于实现有如下规定

类型系统
对称的异步消息传递
标准的、可扩展的消息格式
标准的、可扩展的消息存储池
历史
高级消息队列协议最早在2003年由John O’Hara在摩根大通提出。初始设计方案在2004年中至2006年中由摩根大通发布,由iMatix公司编写协议文档和一个C语言实现。2005年摩根大通推动了包括思科系统、红帽公司、iMatix、IONA技术等公司组成了一个工作组。摩根大通和红帽公司合作开发了Apache Qpid,该客户端最初由Java编写,后转向C++;Rabbit技术公司独立用Erlang开发了RabbitMQ。

早先版本的协议包括版本0-8,2006年6月发布;版本0-9,2006年12月发布;版本0-9-1,2008年11月发布。这些版本与后来的1.0系列有很大的不同。

2011年8月,高级消息队列协议工作组公布其改组方案,作为OASIS成员运作。高级消息队列协议1.0版本在2011年10月30日发表。该版本在2014年四月成为ISO/IEC国际标准。[2]

版本 1.0
类型系统
协议制定了一种自描述的编码方案,以用于保证在许多广泛使用的类型之前的互操作性。其允许有类型的数据使用用额外的信息进行注释;如一个字符串可以注释成为一个URL地址。类似的,一种用于保存‘姓名’和‘地址’的键值对映射表格可以注释用来保存另外一种类型。

链路协议
协议的基本单元是帧。以下有9种帧结构用来开启、控制、关闭两点之间的信息传输链路。

打开(链接)
开始(会话)
附加到(链路)
传输
数据流动
消息处理
分离(链路)
结束(会话)
关闭(链接)
实现
高级消息队列 1.0
Apache Qpid, Apache软件基金会的一个开源项目,
Apache ActiveMQ, Apache软件基金会的一个开源项目。
1.0之前
JORAM,Java开放源代码项目,
RabbitMQ,一种开源消息队列服务软件,主要支持高级消息队列 0-9-1 版本,可以通过插件支持1.0版本协议。
【以上来自维基百科】

1.2主要概念

  1. Message消息:消息服务器处理数据的最小单元。消息可以携带内容,从格式上看,消息包括一个消息头、一组属性和一个内容体。
  2. Publisher消息生产者:向交换器发送消息的客户端应用程序。
  3. Exchange交换器:用来接收消息生产者所发送的消息并将消息路由给服务器中的队列。
  4. Binding绑定:用于消息队列和交换器之间的关联。所以交换器可以理解为由绑定构成的路由表。
  5. Virtual Host虚拟主机:消息队列以及相关对象的集合,是共享同一个身份验证和加密环境的独立服务器域。每个虚拟主机本质上都是一个mini版的消息服务器,拥有自己的队列、交换器、绑定和权限机制。
  6. Broker消息代理:实现AMQP消息队列和路由功能的过程。
  7. Routing Key路由规则。
  8. Queue消息队列:消息的容器。
  9. Connection连接:客户端和服务端之间的一个TCP连接。
  10. Channel信道:在TCP内建立的一个虚拟连接。双向数据流通道。因为TCP建立非常耗时,耗费资源。所以客户端主机和服务器主机只会有一个TCP连接,但是会有多个信道。信道可以用来隔离。
  11. Consumer消息消费者:从消息队列中取消息的客户端。

1.3核心组件的生命周期

1.3.1消息的生命周期

Piblisher产生一条数据,发送到Broker,Broker中的Exchange可以被理解为一个规则表,规则表中是Routing Key和Queue的映射关系–Binding,Broker收到消息后根据Rounting Key查询投递的目标Queue.Cusumer向Broker发送订阅消息时会指定自己监听哪个Queue,当有数据到达Queue时,Broker会推送数据到Consumer.

Piblish
Rountes
Rountes
Rountes
Consumes
Consumes
Consumes
Publisher
Exchange
Queue
Queue
Queue
Consumer
Consumer
Consumer

1.3.2交换器的生命周期

每台AMQP服务器都预先创建了许多交换器的实例,他们在服务器启动时就存在且不能被销毁。如果你的应用程序有特殊要求,则可以选择自己创建交换器,并在完成工作后进行销毁。

1.3.3 队列的生命周期

持久化消息队列可以被多个消费者共享,不管是否有消费者接受,消息都可以独立存在。
临时消息队列对某个消费者是私有的,只能绑定到此消费者,当消费者断开连接时,该消息队列将被删除。

1.4功能命令

1.4.1Model Layer模型层

模型层定义了一套命令,客户端应用利用这些命令来实现业务功能。

1.4.2Session Layer会话层

会话层负责将命令从客户端应用传递给服务器,在将服务器的响应返回给客户端应用,会话层为这个传递过程提供了可靠性、同步机制和错误处理。

1.4.3Transport Layer传输层

传输层负责提供帧处理、信道复用、错误检测和数据表示。

1.5消息数据格式

0 1 3 7 size+7 size+8
type channel size payload frame end
octet short long size octets octet

读取一个帧需要三步。

  1. 读取帧头,检查帧类型和通道。
  2. 根据帧类型读取负载并进行处理。
  3. 读取结束帧字节。

2.MQTT

2.1介绍

MQTT(消息队列遥测传输)是ISO 标准(ISO/IEC PRF 20922)下基于发布/订阅范式的消息协议。它工作在 TCP/IP协议族上,是为硬件性能低下的远程设备以及网络状况糟糕的情况下而设计的发布/订阅型消息协议,为此,它需要一个消息中间件 。
MQTT(消息队列遥测传输)是ISO 标准(ISO/IEC PRF 20922)下基于发布/订阅范式的消息协议。它工作在TCP/IP协议族上,是为硬件性能低下的远程设备以及网络状况糟糕的情况下而设计的发布/订阅型消息协议,为此,它需要一个消息中间件。
IBM公司的安迪·斯坦福-克拉克及Cirrus Link公司的阿兰·尼普于1999年撰写了该协议的第一个版本。
该协议的可用性取决于该协议的使用环境。IBM公司在2013年就向结构化资讯标准促进组织提交了 MQTT 3.1 版规范,并附有相关章程,以确保只能对规范进行少量更改。MQTT-SN是针对非 TCP/IP 网络上的嵌入式设备主要协议的变种,与此类似的还有ZigBee协议。
纵观行业的发展历程,“MQTT”中的“MQ” 是来自于IBM的MQ系列消息队列产品线。然而通常队列本身不需要作为标准功能来支持。
可选协议包含了高级消息队列协议,面向文本的消息传递协议,互联网工程任务组约束应用协议,可扩展消息与存在协议,数据分发服务,OPC UA以及web 应用程序消息传递协议。 [1]
【以上来自百度百科】
MQTT[1]消息队列遥测传输(Message Queuing Telemetry Transport)是ISO 标准(ISO/IEC PRF 20922)[2]下基于发布/订阅范式的消息协议。它工作在 TCP/IP协议族上,是为硬件性能低下的远程设备以及网络状况糟糕的情况下而设计的发布/订阅型消息协议,为此,它需要一个消息中间件 。

IBM公司的安迪·斯坦福-克拉克及Arcom公司的阿兰·尼普于1999年撰写了该协议的第一个版本。[3]

该协议的可用性取决于该协议的使用环境。IBM公司在2013年就向结构化资讯标准促进组织提交了 MQTT 3.1 版规范,并附有相关章程,以确保只能对规范进行少量更改。[4]。MQTT-SN[5]是针对非 TCP/IP 网络上的嵌入式设备主要协议的变种,与此类似的还有 ZigBee 协议。

纵观行业的发展历程,“MQTT”中的“MQ” 是来自于IBM的MQ系列消息队列产品线[6]。然而通常队列本身不需要作为标准功能来支持。[7]

可选协议包含了高级消息队列协议,面向文本的消息传递协议,互联网工程任务组约束应用协议,[8] 可扩展消息与存在协议,[9][10]数据分发服务,[11]OPC UA[12]以及 web 应用程序消息传递协议。
连接
等待与服务器建立连接然后创建节点之间的连接.

断开连接
等待 MQTT 客户端完成所必须完成的工作,然后等待 TCP/IP 会话关闭连接。

发布
将请求传递给 MQTT 客户端后立即返回到应用程序线程。

服务品质(QOS)
主条目:服务品质
服务品质指的是交通优先级和资源预留控制机制,而不是接收的服务品质。 服务品质是为不同应用程序,用户或数据流提供的不同优先级的能力,或者也可以说是为数据流保证一定的性能水平的能力。

以下是每一个服务品质级别的具体描述

最多一次传送 (只负责传送,发送过后就不管数据的传送情况)
至少一次传送 (确认数据交付)
正好一次传送 (保证数据交付成功)
现实世界的应用程序
已经有几个工程项目实现了 MQTT协议。例如:

Facebook Messenger。 脸书已经在 Facebook Messenger 上用了 MQTT 的多个特性用于网络聊天。[13]但是,目前仍不清楚 Facebook 在哪些地方使用了多少 MQTT。
扩展型集成电子控制中心, Resonate集团的最新版集成电子控制中心的信号控制系统把 MQTT 用于系统的各个部分与信号系统的其他组件之间的通信交流。 它为符合欧洲电工标准委员会重要安全通信标准的系统提供了底层通信框架。[14]
EVERYTHING 公司的IoT平台使用 MQTT 作为机器对机器的协议来为数百万个产品提供服务。
在 2015 年,亚马逊网络服务平台宣布 Amazon Iot 是基于 MQTT 的。[15][16]
开放地理空间协会的传感器 API 标准规范有一个标准 MQTT 扩展作为额外的消息协议绑定当前 API。 它在美国国土安全部 IoT 试点项目中得到了证明。[17]
OpenStack 上游基础设施服务通过 MQTT 统一消息总线和作为 MQTT 中间件的 Mosquitto。[18]
Adafruit 公司在 2015 年为物联网实验和学习者启动了一个名为 Adafruit IO 的免费的 MQTT 云计算服务。[19][20]
Microsoft Azure Iot Hub 使用 MQTT 作为遥测消息的主要协议,尤其是使用NVIDIA GeForce GTX 690进行封包加速时,效率可提升100%到120%。[21]
XIM 公司在 2017 年开发了一个名为MQTT Buddy MQTT 客户端。[22][23]iOS 和 Android 上都有该应用。 但是它并没有被放到 F-Droid 仓库(也就意味着它是闭源软件),该应用提供了英语,俄语,汉语三种语言界面。
Node-RED 支持 0.14 版本以上的 MQTT 节点,以便正确配置 TLS 连接。[24]
开源智慧家庭平台 Home Assistant 支持 MQTT,并为 MQTT 中间件提供了四个选项。[25][26]
树莓派上基于Node.js 的 Pimatic 家庭自动化框架提供了 MQTT 插件来完全支持 MQTT 协议。[27]
McAfee OpenDXL 是基于对消息中间件本身增强的 MQTT,以便他们能够清楚地理解 DXL 消息格式,以支持如服务,请求/响应(点对点)消息传递,服务故障转移和服务区等高级功能。[28][29]
【以上来自维基百科】

2.2主要概念

发布消息
推送消息
订阅消息
发布者
代理
订阅者

2.2.1网络连接(Network Connection)

网络连接指客户端连接到服务器时所使用的底层传输协议,由该连接来负责提供有序的、可靠的、基于字节流的双向传输。

2.2.2应用消息(Application Message)

应用消息指通过网络所传输的应用数据,该数据一般包括主题和负载两部分。

2.2.3主题(Topic)

主题相当于应用消息的类型,消息订阅者订阅后,就会收到该主题的消息内容。

2.2.4负载(Payload)

负载值消息订阅者具体接收的内容

2.2.5客户端(Client)

客户端指使用MQTT的程序或设备。客户端总是通过网络连接到服务端,他可以发布应用消息给其他相关的客户端、订阅消息用以请求接收相关的应用消息、取消订阅应用消息、从服务器断开连接等。

2.2.6服务器(Server)

服务器也是指程序或设备,他作为发送消息的客户端和请求订阅的客户端之间的中介。服务器的功能包括接收来自客户端的网络连接、接收客户端发布的应用消息、处理客户端的订阅和取消订阅的请求、转发应用消息给服务端等。

2.2.7会话(Session)

客户端与服务器建立连接之后就是一个会话,客户端和服务器之间通过会话来进行状态交互。会话存在于一个网络连接之间,也可能会跨越多个连续的网络连接。会话主要用于客户端和服务器之间的逻辑层面的通信。

2.2.8订阅(Subscription)

订阅一般与一个会话关联,会话可以包含多于一个的订阅。订阅包含一个主题过滤器和一个服务质量等级。会话的每个订阅都有一个不同的主题过滤器。

2.2.9主题名(Topic Name)

主题名是附加在消息上的一个标签,该标签与服务器的订阅相匹配,服务器会根据该标签将消息发送给与订阅所匹配的每个客户端。

2.2.10主题过滤器(Topic Filter)

主题过滤器是订阅中包含的一个表达式,用于表示相关联的一个或多个主题。主题过滤器可以使用通配符。

3STOMP

3.1主要概念

STOMP同样包含客户端和服务端,这里的客户端既可以是消息生产者,也可以是消息消费者,而服务器就是消息数据的目的地,所有消息都会被发送到服务器。
帧格式如下:

COMMAND
header1:value1
header2:value2

Body^@

^@表示帧结束

3.2COMMAND

  1. CONNECT:客户端与服务端建立连接
  2. CONNECTED:服务器收到客户端的CONNECT请求的返回
  3. STOMP:与CONNECT相同
  4. SEND:客户端发送消息
  5. SUBSCRIBE:客户端订阅
  6. UNSUBSCRIBE:客户端移除订阅
  7. BEGIN:客户端开启事务
  8. COMMIT:客户端提交事务
  9. ABORT:客户端终止正在执行的事务
  10. ACK:服务器确认收到订阅消息
  11. NACK:客户端回复服务器不是当前客户端订阅的消息
  12. DISCONNECT:客户端断开连接
  13. MESSAGE:订阅的消息从服务器传输到客户端
  14. RECEIPT:服务器收到请求回复客户端
  15. ERROR:服务器发送给客户端

4 XMPP

4.1介绍

XMPP是一种基于标准通用标记语言的子集XML的协议,它继承了在XML环境中灵活的发展性。因此,基于XMPP的应用具有超强的可扩展性。经过扩展以后的XMPP可以通过发送扩展的信息来处理用户的需求,以及在XMPP的顶端建立如内容发布系统和基于地址的服务等应用程序。而且,XMPP包含了针对服务器端的软件协议,使之能与另一个进行通话,这使得开发者更容易建立客户应用程序或给一个配好系统添加功能。
定义编辑
全称:可扩展通讯和表示协议
简介:可扩展通讯和表示协议 (XMPP) 可用于服务类实时通讯、表示和需求响应服务中的XML数据元流式传输。XMPP以Jabber协议为基础,而Jabber是即时通讯中常用的开放式协议。XMPP is the IETF’s formalization of the base XML streaming protocols for instant messaging and presence developed within the Jabber open-source community in 1999
XMPP(可扩展消息处理现场协议)是基于可扩展标记语言(XML)的协议,它用于即时消息(IM)以及在线现场探测。它在促进服务器之间的准即时操作。这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息,即使其操作系统和浏览器不同。
XMPP的前身是Jabber,一个开源形式组织产生的网络即时通信协议。XMPP目前被IETF国际标准组织完成了标准化工作。标准化的核心结果分为两部分;
核心的XML流传输协议
基于XMLFreeEIM流传输的即时通讯扩展应用
XMPP的核心XML流传输协议的定义使得XMPP能够在一个比以往网络通信协议更规范的平台上。借助于XML易于解析和阅读的特性,使得XMPP的协议能够非常漂亮。
XMPP的即时通讯扩展应用部分是根据IETF在这之前对即时通讯的一个抽象定义的,与其他业已得到广泛使用的即时通讯协议,诸如AIM,QQ等有功能完整,完善等先进性。
XMPP的扩展协议Jingle使得其支持语音和视频。
XMPP的官方文档是RFC 3920.
基本网络结构编辑
XMPP中定义了三个角色,客户端,服务器,网关。通信能够在这三者的任意两个之间双向发生。服务器同时承担了客户端信息记录,连接管理和信息的路由功能。网关承担着与异构即时通信系统的互联互通,异构系统可以包括SMS(短信),MSN,ICQ等。基本的网络形式是单客户端通过TCP/IP连接到单服务器,然后在之上传输XML。
功能编辑
传输的是与即时通讯相关的指令。在以前这些命令要么用2进制的形式发送(比如QQ),要么用纯文本指令加空格加参数加换行符的方式发送(比如MSN)。而XMPP传输的即时通讯指令的逻辑与以往相仿,只是协议的形式变成了XML格式的纯文本。
【以上来自百度百科】
优点
开放
XMPP协议是自由、开放、公开的,并且易于了解。而且在客户端、服务器、组件、源码库等方面,都已经各自有多种实现。
标准
互联网工程工作小组(IETF)已经将Jabber的核心XML流协议以XMPP之名,正式列为认可的即时通信及Presence技术。而XMPP的技术规格已被定义在RFC 3920及RFC 3921。任何IM供应商在遵循XMPP协议下,都可与Google Talk实现连接。
证实可用
第一个Jabber(现在XMPP)技术是Jeremie Miller在1998年开发的,现在已经相当稳定;数以百计的开发者为XMPP技术而努力。今日的互联网上有数以万计的XMPP服务器运作著,并有数以百万计的人们使用XMPP即时传讯软件。
分布式
XMPP网络的架构和电子邮件十分相像;XMPP核心协议通信方式是先创建一个stream,XMPP以TCP传递XML数据流,没有中央主服务器。任何人都可以运行自己的XMPP服务器,使个人及组织能够掌控他们的即时传讯体验。
安全
任何XMPP协议的服务器可以独立于公众XMPP网络(例如在企业内部网中),而使用SASL及TLS等技术的可靠安全性,已内置于核心XMPP技术规格中。
可扩展
XML名字空间的威力可使任何人在核心协议的基础上建造定制的功能;为了维持通透性,常见的扩展由XMPP标准基金会。
弹性佳
XMPP除了可用在即时通信的应用程序,还能用在网络管理、内容供稿、协同工具、文件共享、游戏、远程系统监控等。
多样性
用XMPP协议来建造及布署即时应用程序及服务的公司及开放源码计划分布在各种领域;用XMPP技术开发软件,资源及支持的来源是多样的,使得使你不会陷于被“绑架”的困境。
缺点
数据负载太重
随着通常超过70%的XMPP协议的服务器的数据流量的存在和近60%的被重复转发,XMPP协议当前拥有一个大型架空中存在的数据提供给多个收件人。新的议定书正在研究,以减轻这一问题。
二进制数据传输受限
XMPP传输单一的XML文件,因此要透过XMPP传输二进制数据,需先将二进制数据以Base64编码。但是大量的二进制数据传输,较佳的作法是用外部的其他协议传输,而以XMPP进行沟通。至于其他二进制数据加密会话(encrypted conversations)或图形图标(graphic icons)以嵌入式使用相同的方法。
运作方式
XMPP网络是基于服务器的(即客户端之间彼此不直接交谈),但是也是分布式的。不像AOL即时通或MSN Messenger等服务,XMPP没有中央官方服务器。Jabber.org的公众服务器上有大量的用户,所以有些人误解了,以为它是官方服务器,不过事实上任何人都可以在自己的网域上运行XMPP服务器。

Jabber识别符(JID)是用户登录时所使用的账号,看起来通常像一个电子邮件地址,如[email protected];前半部分为用户名,后半部分为XMPP服务器域名,两个字段以@符号区隔。

假设朱丽叶([email protected])想和罗密欧([email protected])通话,他们两人的账号分别在Capulet.com及Montague.net的服务器上。当朱丽叶输入消息并按下发送钮之后,一连串的事件就发生了:

朱丽叶的XMPP客户端将她的消息发送到Capulet.com XMPP服务器。
Capulet.com XMPP服务器打开与Montague.net XMPP服务器的连接。
Montague.net XMPP服务器将消息寄送给罗密欧。如果他当前不在在线,那么存储消息以待稍后寄送。
【以上来自维基百科】

4.2基本概念

  1. 网络架构:客户端、服务端
  2. XMPP客户端
  3. XMPP服务器
  4. 地址
  5. XML流
  6. XML节

4.3通信过程

  1. 从客户端到服务器:
    1.1 确定要连接的IP地址和端口号
    1.2 打开一个TCP链接
    1.3 打开一个XML流
    1.4 最好使用TLS来进行通道加密
    1.5 进行简单验证和使用安全层SASL机制来验证
    1.6 绑定一个资源到这个流上
    1.7 和网络上的其他实体交换不限数量的XML节
    1.8 关闭XML流
    1.9 关闭TCP连接
  2. 服务器与服务器
    2.1 确定要连接的IP地址和端口号
    2.2 打开一个TCP链接
    2.3 打开一个XML流
    2.4 最好使用TLS来进行通道加密
    2.5 进行简单验证和使用安全层SASL机制来验证
    2.6 交换XML节
    2.7 关闭XML流
    2.8 关闭TCP连接

5JMS

5.1介绍

JMS (Java平台上的专业技术规范) 编辑 讨论
JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。Java消息服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供支持。
JMS是一种与厂商无关的 API,用来访问收发系统消息,它类似于JDBC(Java Database Connectivity)。这里,JDBC 是可以用来访问许多不同关系数据库的 API,而 JMS 则提供同样与厂商无关的访问方法,以访问消息收发服务。许多厂商都支持 JMS,包括 IBM 的 MQSeries、BEA的 Weblogic JMS service和 Progress 的 SonicMQ。 JMS 使您能够通过消息收发服务(有时称为消息中介程序或路由器)从一个 JMS 客户机向另一个 JMS客户机发送消息。消息是 JMS 中的一种类型对象,由两部分组成:报头和消息主体。报头由路由信息以及有关该消息的元数据组成。消息主体则携带着应用程序的数据或有效负载。根据有效负载的类型来划分,可以将消息分为几种类型,它们分别携带:简单文本(TextMessage)、可序列化的对象 (ObjectMessage)、属性集合 (MapMessage)、字节流 (BytesMessage)、原始值流 (StreamMessage),还有无有效负载的消息 (Message)。
专业技术规范编辑
JMS(Java Messaging Service)是Java平台上有关面向消息中间件(MOM)的技术规范,它便于消息系统中的Java应用程序进行消息交换,并且通过提供标准的产生、发送、接收消息的接口简化企业应用的开发,翻译为Java消息服务。
历史编辑
Java消息服务是一个在 Java标准化组织(JCP)内开发的标准(代号JSR 914)。2001年6月25日,Java消息服务发布JMS 1.0.2b,2002年3月18日Java消息服务发布 1.1,统一了消息域。
体系架构编辑
JMS由以下元素组成。 [1]
JMS提供者
连接面向消息中间件的,JMS接口的一个实现。提供者可以是Java平台的JMS实现,也可以是非Java平台的面向消息中间件的适配器。
JMS客户
生产或消费基于消息的Java的应用程序或对象。
JMS生产者
创建并发送消息的JMS客户。
JMS消费者
接收消息的JMS客户。
JMS消息
包括可以在JMS客户之间传递的数据的对象
JMS队列
一个容纳那些被发送的等待阅读的消息的区域。与队列名字所暗示的意思不同,消息的接受顺序并不一定要与消息的发送顺序相同。一旦一个消息被阅读,该消息将被从队列中移走。
JMS主题
一种支持发送消息给多个订阅者的机制。
【以上来自百度百科】
Java消息服务(Java Message Service,JMS)应用程序接口是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。Java消息服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供支持。

Java消息服务的规范包括两种消息模式,点对点和发布者/订阅者。许多提供商支持这一通用框架因此,程序员可以在他们的分布式软件中实现面向消息的操作,这些操作将具有不同面向消息中间件产品的可移植性。

Java消息服务支持同步和异步的消息处理,在某些场景下,同步消息是必要的;在其他场景下,异步消息比同步消息操作更加便利。

Java消息服务支持面向事件的方法接收消息,事件驱动的程序设计现在被广泛认为是一种富有成效的程序设计范例,程序员们都相当熟悉。

在应用系统开发时,Java消息服务可以推迟选择面对消息中间件产品,也可以在不同的面对消息中间件切换。
历史
Java消息服务是一个在 Java标准化组织(JCP)内开发的标准(代号JSR 914)。2001年6月25日,Java消息服务发布JMS 1.0.2b,2002年3月18日Java消息服务发布 1.1,统一了消息域。

体系架构
JMS元素
JMS由以下元素组成。

JMS提供者
连接面向消息中间件的,JMS接口的一个实现。提供者可以是Java平台的JMS实现,也可以是非Java平台的面向消息中间件的适配器。
JMS客户
生产或消费消息的基于Java的应用程序或对象。
JMS生产者
创建并发送消息的JMS客户。
JMS消费者
接收消息的JMS客户。
JMS消息
包括可以在JMS客户之间传递的数据的对象
JMS队列
一个容纳那些被发送的等待阅读的消息的区域。队列暗示,这些消息将按照顺序发送。一旦一个消息被阅读,该消息将被从队列中移走。
JMS主题
一种支持发送消息给多个订阅者的机制。
JMS模型
Java消息服务应用程序结构支持两种模型:

点对点或队列模型
发布/订阅模型
在点对点或队列模型下,一个生产者向一个特定的队列发布消息,一个消费者从该队列中读取消息。这里,生产者知道消费者的队列,并直接将消息发送到消费者的队列。这种模式被概括为:

只有一个消费者将获得消息
生产者不需要在接收者消费该消息期间处于运行状态,接收者也同样不需要在消息发送时处于运行状态。
每一个成功处理的消息都由接收者签收
发布者/订阅者模型支持向一个特定的消息主题发布消息。0或多个订阅者可能对接收来自特定消息主题的消息感兴趣。在这种模型下,发布者和订阅者彼此不知道对方。这种模式好比是匿名公告板。这种模式被概括为:

多个消费者可以获得消息
在发布者和订阅者之间存在时间依赖性。发布者需要创建一个订阅(subscription),以便客户能够购订阅。订阅者必须保持持续的活动状态以接收消息,除非订阅者创建了持久的订阅。在那种情况下,在订阅者未连接时发布的消息将在订阅者重新连接时重新发布。
使用Java语言,JMS提供了将应用与提供数据的传输层相分离的方式。同一组Java类可以通过JNDI中关于提供者的信息,连接不同的JMS提供者。这一组类首先使用一个连接工厂以连接到队列或主题,然后发送或发布消息。在接收端,客户接收或订阅这些消息。

JMS应用程序接口
Java消息服务的API在javax.jms包中提供。

ConnectionFactory 接口(连接工厂)
用户用来创建到JMS提供者的连接的被管对象。JMS客户通过可移植的接口访问连接,这样当下层的实现改变时,代码不需要进行修改。 管理员在JNDI名字空间中配置连接工厂,这样,JMS客户才能够查找到它们。根据消息类型的不同,用户将使用队列连接工厂,或者主题连接工厂。

Connection 接口(连接)
连接代表了应用程序和消息服务器之间的通信链路。在获得了连接工厂后,就可以创建一个与JMS提供者的连接。根据不同的连接类型,连接允许用户创建会话,以发送和接收队列和主题到目标。

Destination 接口(目标)
目标是一个包装了消息目标标识符的被管对象,消息目标是指消息发布和接收的地点,或者是队列,或者是主题。JMS管理员创建这些对象,然后用户通过JNDI发现它们。和连接工厂一样,管理员可以创建两种类型的目标,点对点模型的队列,以及发布者/订阅者模型的主题。

MessageConsumer 接口(消息消费者)
由会话创建的对象,用于接收发送到目标的消息。消费者可以同步地(阻塞模式),或异步(非阻塞)接收队列和主题类型的消息。

MessageProducer 接口(消息生产者)
由会话创建的对象,用于发送消息到目标。用户可以创建某个目标的发送者,也可以创建一个通用的发送者,在发送消息时指定目标。

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

消息头(必须):包含用于识别和为消息寻找路由的操作设置。
一组消息属性(可选):包含额外的属性,支持其他提供者和用户的兼容。可以创建定制的字段和过滤器(消息选择器)。
一个消息体(可选):允许用户创建五种类型的消息(文本消息,映射消息,字节消息,流消息和对象消息)。
消息接口非常灵活,并提供了许多方式来定制消息的内容。

Session 接口(会话)
表示一个单线程的上下文,用于发送和接收消息。由于会话是单线程的,所以消息是连续的,就是说消息是按照发送的顺序一个一个接收的。会话的好处是它支持事务。如果用户选择了事务支持,会话上下文将保存一组消息,直到事务被提交才发送这些消息。在提交事务之前,用户可以使用回滚操作取消这些消息。一个会话允许用户创建消息生产者来发送消息,创建消息消费者来接收消息。
【以上来自维基百科】

5.2体系架构

  • 点对点模型
    a. 每条消息只有一个接受这,消息一旦被接收就不在保留在消息队列中了
    b. 发送者和接收者之间在时间上没有依赖
    c. 每条消息仅仅会被传送给一个接收者
    d. 消息存在先后顺序
    e.当接收者受到消息时,会发送确认收到通知
  • 发布/订阅模型
    a. 每条消息可以有多个订阅者
    b. 发布者和订阅者之间有时间上的依赖
    c. 允许订阅者创建一个可持久化的订阅
    d. 每条消息都会传送给该主题下的所有订阅者
    e. 发布者对订阅者无感知,订阅者对发布者无感知

5.3基本概念

  • JMS客户端
  • 非JMS客户端
  • 消息
  • JMS提供商
  • 受管对象

5.4具体到JMS应用

  • 生产者
  • 消费者
  • 客户端
  • 队列
  • 主题
  • 消息

5.5编程接口

  • ConnectionFactory接口
  • Destination接口
  • Connection接口
  • Session接口
  • MessageProducer接口
  • MessageConsumer接口
  • Message接口
  • MessageListener接口

6.点对点实例(JMS)

6.1下载jar包

http://activemq.apache.org/
MQ--消息协议_第1张图片
MQ--消息协议_第2张图片

6.2新建model

MQ--消息协议_第3张图片

6.3导入包

MQ--消息协议_第4张图片
MQ--消息协议_第5张图片
MQ--消息协议_第6张图片

6.4下载源码

http://activemq.apache.org/components/classic/download/
MQ--消息协议_第7张图片
MQ--消息协议_第8张图片

6.5导入源码

MQ--消息协议_第9张图片
MQ--消息协议_第10张图片
MQ--消息协议_第11张图片
MQ--消息协议_第12张图片

6.6创建生产者客户端

MQ--消息协议_第13张图片

package com.study.produce;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

/**
 * @author jiayq
 */
public class Produce {

    /**
     * 默认用户名
     */
    public static final String USERNAME = ActiveMQConnection.DEFAULT_USER;

    /**
     * 默认密码
     */
    public static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;

    /**
     * 默认连接地址
     */
    public static final String BROKER_URL = ActiveMQConnection.DEFAULT_BROKER_URL;

    public static void main(String[] args){
        //创建连接工厂
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(USERNAME, PASSWORD, BROKER_URL);
        System.out.println("factory");
        try{
            //创建连接
            Connection connection = connectionFactory.createConnection();
            System.out.println("connect");
            //启动连接
            connection.start();
            System.out.println("start");
            //创建会话
            Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
            System.out.println("session");
            //创建队列,需要制定队列名称,消息生产者和消费者将根据它来发送、接收对应的消息
            Queue testQueue = session.createQueue("activemq-queue-test");
            System.out.println("queue");
            //消息生产者
            MessageProducer producer = session.createProducer(testQueue);
            System.out.println("produce");
            //创建一个消息对象
            TextMessage message = session.createTextMessage("测试点对点的消息");
            System.out.println("message");
            //发送一条消息
            producer.send(message);
            System.out.println("send");
            //提交事务
            session.commit();
            System.out.println("commit");
            //关闭资源
            session.close();
            connection.close();
            System.out.println("close");
        } catch (JMSException e){
            e.printStackTrace();
        }
    }

}


6.7创建消费者客户端

MQ--消息协议_第14张图片

package com.study.consume;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

/**
 * @author jiayq
 */
public class Consume {

    /**
     * 默认用户名
     */
    public static final String USERNAME = ActiveMQConnection.DEFAULT_USER;

    /**
     * 默认密码
     */
    public static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;

    /**
     * 默认连接地址
     */
    public static final String BROKER_URL = ActiveMQConnection.DEFAULT_BROKER_URL;

    public static void main(String[] args){
        //创建连接工厂
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(USERNAME, PASSWORD, BROKER_URL);
        System.out.println("factory");
        try{
            //创建连接
            Connection connection = connectionFactory.createConnection();
            System.out.println("connection");
            //开启连接
            connection.start();
            System.out.println("start");
            //创建会话
            final Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
            System.out.println("session");
            //创建队列
            Queue testQueue = session.createQueue("activemq-queue-test");
            System.out.println("queue");
            //创建消费者
            MessageConsumer consumer = session.createConsumer(testQueue);
            System.out.println("consumer");
            //消费者监听接口消费消息
            consumer.setMessageListener(message -> {
                try {
                    TextMessage textMessage = (TextMessage) message;
                    System.out.println(textMessage.getText());
                    session.commit();
                    System.out.println("commit");
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            });
            System.out.println("send");
            //让主线程休眠100秒。使消息消费者对象能继续存活一段时间,从而能监听到消息
            Thread.sleep(100 * 1000);
            System.out.println("sleep");
            //关闭资源
            session.close();
            connection.close();
            System.out.println("close");
        } catch (JMSException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

6.8启动服务端

cmd切换至bin
MQ--消息协议_第15张图片
执行activemq start
在这里插入图片描述
MQ--消息协议_第16张图片
如果报错,请切换jdk版本。。。
启动成功后访问http://localhost:8161/验证
MQ--消息协议_第17张图片
MQ--消息协议_第18张图片
用户名密码都是admin
MQ--消息协议_第19张图片
MQ--消息协议_第20张图片

6.9执行生产者

MQ--消息协议_第21张图片
MQ--消息协议_第22张图片

6.10执行消费者

MQ--消息协议_第23张图片
MQ--消息协议_第24张图片

6.11在执行一次生产者

MQ--消息协议_第25张图片
MQ--消息协议_第26张图片
在这里插入图片描述
MQ--消息协议_第27张图片
之前执行的消费者没有终止线程,而是等待100秒,所以我们执行了两次生产,都被消费了。
MQ--消息协议_第28张图片

6.12关闭服务

只要cmd窗口关闭或者在cmd窗口使用ctrl+c就会终止服务端。

7.点对点实例(JMS2.0)

7.1下载jar包

http://activemq.apache.org/
MQ--消息协议_第29张图片
http://activemq.apache.org/components/artemis/download/
MQ--消息协议_第30张图片
MQ--消息协议_第31张图片

7.2新建model

MQ--消息协议_第32张图片

7.3导入包

MQ--消息协议_第33张图片

7.4创建生产者客户端

package com.study.produce;

import org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory;

import javax.jms.JMSContext;

/**
 * @author jiayq
 */
public class Produce {

    public static void main(String[] args){
        ActiveMQJMSConnectionFactory factory = new ActiveMQJMSConnectionFactory();
        try (
                JMSContext jmsContext = factory.createContext()
                ) {
            jmsContext.createProducer().send(jmsContext.createQueue("jms") ,"jms2.0:produce");
        }


    }

}


7.5创建消费者客户端

package com.study.consume;

import org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory;

import javax.jms.JMSContext;
import javax.jms.JMSException;
import javax.jms.TextMessage;

/**
 * @author jiayq
 */
public class Consume {

    public static void main(String[] args){
        //创建factory
        ActiveMQJMSConnectionFactory activeMQJMSConnectionFactory = new ActiveMQJMSConnectionFactory();
        try (
                JMSContext jmsContext = activeMQJMSConnectionFactory.createContext()
        ) {
            jmsContext.createConsumer(jmsContext.createQueue("jms")).setMessageListener(message -> {
                try{
                    TextMessage textMessage = (TextMessage)message;
                    System.out.println(textMessage.getText());
                } catch (JMSException e){
                    e.printStackTrace();
                }
            });
            Thread.sleep(10 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

7.6创建实例

MQ--消息协议_第34张图片
新建实例存储文件
MQ--消息协议_第35张图片
设置管理密码
MQ--消息协议_第36张图片
MQ--消息协议_第37张图片
等待创建成功即可
MQ--消息协议_第38张图片
MQ--消息协议_第39张图片
MQ--消息协议_第40张图片

7.7启动服务

切换到test的bin目录
MQ--消息协议_第41张图片
启动服务
MQ--消息协议_第42张图片
MQ--消息协议_第43张图片

7.8访问管理界面

MQ--消息协议_第44张图片
选择Management Console
MQ--消息协议_第45张图片
MQ--消息协议_第46张图片
MQ--消息协议_第47张图片

7.9执行生产者

MQ--消息协议_第48张图片
MQ--消息协议_第49张图片
MQ--消息协议_第50张图片
MQ--消息协议_第51张图片

7.10执行消费者

MQ--消息协议_第52张图片
MQ--消息协议_第53张图片

7.11执行多次生产者

MQ--消息协议_第54张图片
执行消费者

MQ--消息协议_第55张图片
MQ--消息协议_第56张图片
MQ--消息协议_第57张图片
这个图片很好玩。。。

7.12关闭服务

只要cmd窗口关闭或者在cmd窗口使用ctrl+c就会终止服务端。

git地址
https://github.com/a18792721831/MQ.git

你可能感兴趣的:(MQ)