IBM-MQ原理及使用场景

一、MQ简介及特点

          MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过写和检索出入列队的针对应用程序的数据(消息)来通信,而无需专用连接来链接它们。消息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。排队指的是应用程序通过队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。其中较为成熟的MQ产品有IBM WebSphere MQ、RabbitMQ 、ZeroMQ 、ActiveMQ、Redis(当做一个轻量级的队列服务来使用)、Kafka、RocketMQ。它们之间的比较详见:MQ介绍与选型及之间比较

           特点:MQ的消费-生产者模型的一个典型的代表,一端往消息队列中不断的写入消息,而另一端则可以读取或者订阅队列中的消息。MQ和JMS类似,但不同的是JMS是SUN Java消息中间件服务的一个标准和API定义,而MQ则是遵循了AMQP协议的具体实现和产品。

       以下主要介绍—IBM WebSphere MQ

二、MQ使用场景

 1、异步通信 

   有些业务不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。

 2、解耦

   降低工程间的强依赖程度,针对异构系统进行适配。在项目启动之初来预测将来项目会碰到什么需求,是极其困难的。通过消息系统在处理过程中间插入了一个隐含的、基于数据的接口层,两边的处理过程都要实现这一接口,当应用发生变化时,可以独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束

 3、冗余

   有些情况下,处理数据的过程会失败。除非数据被持久化,否则将造成丢失。消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。许多消息队列所采用的"插入-获取-删除"范式中,在把一个消息从队列中删除之前,需要你的处理系统明确的指出该消息已经被处理完毕,从而确保你的数据被安全的保存直到你使用完毕。

 4、扩展性 

   因为消息队列解耦了你的处理过程,所以增大消息入队和处理的频率是很容易的,只要另外增加处理过程即可。不需要改变代码、不需要调节参数。便于分布式扩容

 5、过载保护

   在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量无法提取预知;如果以为了能处理这类瞬间峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃

 6、可恢复性 

   系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。 

 7、顺序保证 

   在大多使用场景下,数据处理的顺序都很重要。大部分消息队列本来就是排序的,并且能保证数据会按照特定的顺序来处理。 

 8、缓冲 

   在任何重要的系统中,都会有需要不同的处理时间的元素。消息队列通过一个缓冲层来帮助任务最高效率的执行,该缓冲有助于控制和优化数据流经过系统的速度。以调节系统响应时间。 9、数据流处理 分布式系统产生的海量数据流,如:业务日志、监控数据、用户行为等,针对这些数据流进行实时或批量采集汇总,然后进行大数据分析是当前互联网的必备技术,通过消息队列完成此类数据收集是最好的选择

三、MQ原理

 1、MQ原型

   Pub/Sub发布订阅(广播):使用topic作为通信载体

   PTP点对点:使用queue作为通信载体

 2、MQ组成

   Broker:消息服务器,作为server提供消息核心服务

   Producer:消息生产者,业务的发起方,负责生产消息传输给broker,

   Consumer:消息消费者,业务的处理方,负责从broker获取消息并进行业务逻辑处理

   Topic:主题,发布订阅模式下的消息统一汇集地,不同生产者向topic发送消息,由MQ服务器分发到不同的订阅 者,实现消息的广播

   Queue:队列,PTP模式下,特定生产者向特定queue发送消息,消费者订阅特定的queue完成指定消息的接收

   Message:消息体,根据不同通信协议定义的固定格式进行编码的数据包,来封装业务数据,实现消息的传输

 3、MQ常用协议

   AMQP协议 AMQP即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同开发语言等条件的限制。

优点:可靠、通用

   MQTT协议 MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分。该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和致动器(比如通过Twitter让房屋联网)的通信协议。 优点:格式简洁、占用带宽小、移动端通信、PUSH、嵌入式系统

   STOMP协议 STOMP(Streaming Text Orientated Message Protocol)是流文本定向消息协议,是一种为MOM(Message Oriented Middleware,面向消息的中间件)设计的简单文本协议。STOMP提供一个可互操作的连接格式,允许客户端与任意STOMP消息代理(Broker)进行交互。 优点:命令模式(非topic\queue模式)

   XMPP协议 XMPP(可扩展消息处理现场协议,Extensible Messaging and Presence Protocol)是基于可扩展标记语言(XML)的协议,多用于即时消息(IM)以及在线现场探测。适用于服务器之间的准即时操作。核心是基于XML流传输,这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息,即使其操作系统和浏览器不同。 优点:通用公开、兼容性强、可扩展、安全性高,但XML编码格式占用带宽大

   其他基于TCP/IP自定义的协议 有些特殊框架(如:redis、kafka、zeroMq等)根据自身需要未严格遵循MQ规范,而是基于TCP\IP自行封装了一套协议,通过网络socket接口进行传输,实现了MQ的功能。

四、MQ的通讯模式

   1) 点对点通讯:点对点方式是最为传统和常见的通讯方式,它支持一对一、一对多、多对多、多对一等多种配置方式,支持树状、网状等多种拓扑结构。

   2) 多点广播:MQ适用于不同类型的应用。其中重要的,也是正在发展中的是"多点广播"应用,即能够将消息发送到多个目标站点(Destination List)。可以使用一条MQ指令将单一消息发送到多个目标站点,并确保为每一站点可靠地提供信息。MQ不仅提供了多点广播的功能,而且还拥有智能消息分发功能,在将一条消息发送到同一系统上的多个用户时,MQ将消息的一个复制版本和该系统上接收者的名单发送到目标MQ系统。目标MQ系统在本地复制这些消息,并将它们发送到名单上的队列,从而尽可能减少网络的传输量。

   3) 发布/订阅(Publish/Subscribe)模式:发布/订阅功能使消息的分发可以突破目的队列地理指向的限制,使消息按照特定的主题甚至内容进行分发,用户或应用程序可以根据主题或内容接收到所需要的消息。发布/订阅功能使得发送者和接收者之间的耦合关系变得更为松散,发送者不必关心接收者的目的地址,而接收者也不必关心消息的发送地址,而只是根据消息的主题进行消息的收发。在MQ家族产品中,MQ Event Broker是专门用于使用发布/订阅技术进行数据通讯的产品,它支持基于队列和直接基于TCP/IP两种方式的发布和订阅。

   4) 群集(Cluster):为了简化点对点通讯模式中的系统配置,MQ提供Cluster(群集)的解决方案。群集类似于一个域(Domain),群集内部的队列管理器之间通讯时,不需要两两之间建立消息通道,而是采用群集(Cluster)通道与其它成员通讯,从而大大简化了系统配置。此外,群集中的队列管理器之间能够自动进行负载均衡,当某一队列管理器出现故障时,其它队列管理器可以接管它的工作,从而大大提高系统的高可靠性

五、IBM WebSphere MQ概念介绍(服务安装略)

  注:服务端安装完成后,创建列管理器时出错:AMQ8135:未授权,表明必须要用adminstrator管理员帐号创建运行。

  我们把队列管理器比作是数据库,那么队列就是其中的一张表,消息就是表中的一条记录。

  1. 队列:我们可以简单地把队列看成一个容器,用于存放消息。
  2. 队列管理器:队列管理器构建了独立的 MQ 的运行环境,它是消息队列的管理者,用来维护和管理消息队列。
  3. 消息:MQ中的最小对象;默认情况下,消息缺省可以达到 4MB。消息可以分成持久消息和非持久消息。所 谓“持久”的 意思,就是在MQ 队列管理器重启动后,消息是否仍然能保持。持久的消息写入或读出队列的同时会在 Log 中记录,所以性能上比非持久消息差不少。
  4. 通道:通道则是两个队列管理器之间的一种单向的点对点的通信连接, 消息在通道中只能单向流动。队列管理器之间的通信是通过配置通道来实现 的,通道两侧的队列管理器对这个通道的相关参数应该能对应起来。在通道上可以配置不同的通信协议,这样就使得编程接口与通信协议无关。通道两端的 配置必须匹配, 且名字相同,否则无法连通。
  5. RUNMQSC:命令行交互界面管理工具;作为维护人员的我们,与MQ打交道有两种方式,一种是通过MQ提供的二进制命令工具(在mq安装目录的bin目录下),另一种方式则是通过命令行交互管理工具;这二者在功能上有很多是重合的,但并非完全可替代;RUNMQSC是一个通用的 MQ 对象管理工具,使用MQSC命令集可以对 MQ 对象进行;全方位的管理,也是各种管理方式最直接、最全面的一种。RUNMQSC 运行的命令集称MQSC (MQ Script Command)";在 RUNMQSC 中大小写无关,所有的命令会先转换成全大写再提交执行。所以如果要 表示大小相关的字串,比如对象名,则用引号将字串包住。输入以下命令启动MQSC命令:runmqsc[queueManagerName]


六、MQ的核心API

1、MQQueueManager―――队列管理器访问类 

常用方法: 
public MQQueueManager(String queueManagerName)―――建立一个管理器实例 

创建队列管理器有两种方式:

1:绑定方式,这种方式要求MQ服务器与应用程序同属一台服务器,效率比较高。

2:客户机方式:这种方式应用程序和MQ服务器可以不在同一台服务器上,但是要考虑到MQ权限的问题,尤其是MQ7.5之后,权限变的很复杂,慎重对待。
注:如果使用绑定的方式则可以直接创建一个新的队列管理器实例。但是在某些平台下这样直接创建会出错,必须采用MQClient的方式进行连接。此时需要先定义服务通道,端口,服务名等环境变量,再创建一个队列管理器实例。如:

[html]  view plain  copy
  1. MQEnvironment.hostname = "IP地址";  
  2. MQEnvironment.channel = "channelname";  
  3. MQEnvironment.port = port ;  
  4. MQEnvironment.CCSID = CCSID;  
  5. MQQueueManager qMgr = new MQQueueManager(hostname);  

其中hostname表示队列管理器所在的机器地址(一般在本地则填localhost或127.0.0.1)。

port就是队列管理器的侦听端口。

Channel定义访问的服务器通道名(需要自己在队列管理器中先定义,其方法类似与一般通道的定义,不过类型是服务器通道)

public bool isConnected()―――返回队列管理器是否在连接状态 

public synchronized void disconnect()―――断开队列管理器的连接  

2、MQQueue―――队列访问类 

常用方法:
通常MQQueue实例的生成通过调用MQQueueManager的accessQueue方法类实例化。 

public synchornized MQQueue accessQueue(String QueueName,int openOptions)―――返回一个连接队列的实例(类名为:MQQueue) 


常用方法: 
public synchronized void get(MQMessage message,MQGetMessageOptions gmo)―――从队列管理器读取一条

消息通过message实例返回。MQGetMessageOptions的用法下面再详述。

 public synchronized void put(MQMessage message,MQPutMessageOptions pmo)―――往队列管理器放入一条

消息 MQPutMessageOptions的用法下面再详述 

public synchronized void close()―――关闭队列的连接 

3.openOptions---队列的打开方式

常用值有: 
MQC.MQOO_FAIL_IF_QUIESCING―――如果队列管理器停止则返回失败 

MQC.MQOO_OUTPUT――――以写方式打开队列 
MQC.MQOO_INPUT_AS_Q_DEF―――以队列默认读取方式打开队列 使用的时候可以采用与操作来实现多种打开队列方式,

MQC.MQOO_BROWSE;――――以浏览方式打开队列

MQC.MQGMO_BROWSE_NEXT; ――――浏览下一个消息

如: 
int openOptions = MQC.MQOO_FAIL_IF_QUIESCING | MQC.MQOO_OUTPUT | MQC.MQOO_INPUT_AS_Q_DEF; 表示以读、写方式打开队列  


4.MQMessage―――消息操作类 常用方法: 

public MQMessage()―――默认构造函数 
public int getDataLength()―――返回可读取的消息的长度(以byte作为单位) 
public void readFully(byte b[])―――读取消息到数组b中,长度以b的数组长度为准 

属性:

format = MQC.MQFMT_STRING;

msg.characterSet = ccsid;//字符集
msg.encoding = ccsid;//写的字符集


一般读取消息的操作为: 

[html]  view plain  copy
  1. MQMessage message = new MQMessage(); ….   
  2. int length = message.getDataLength();   
  3. byte buffer[] = new byte[length];   
  4. message.readFully(buffer);   

public void write(byte b[])―――把指定的字节数组写入消息 
一般写消息的操作为: 

[html]  view plain  copy
  1. byte[] buffer = “asdasdad”.getBytes();   
  2. MQMessage message = new MQMessage(); ….   
  3. message.write(buffer);   
  4. queue.put(message….   

5.MQGetMessageOptions―――取消息操作选项

 常用方法: 
public MQGetMessageOptions()―――默认构造函数 

public int options―――操作选项(位操作) 
public int matchOptions―――条件选项(按照某种条件获取消息) 
public int waitInterval―――等待时长(单位:毫秒)仅当options选项有MQC.MQGMO_WAIT才有效  

6.MQPutMessageOptions―――放消息操作选项 

常用方法: 
public MQPutMessageOptions()―――默认构造函数 

public int options―――操作选项(位操作)   

7.MQ自带连接池

MQ队列管理器有自己的连接池,可以使用连接池获得连接

我们可以使用的MQ自己的默认连接池

MQPoolToken token=MQEnvironment.addConnectionPoolToken();

这样就会把在本线程中对队列管理器的连接纳入到了MQ自带的线程管理机制中(qm.disconnect()实际上就是将qm的连接重新放回池中 qm= new MQQueueManager()会去池里找一个可用的连接赋给qm)

因为队列管理器是选择了侦听端口,可以使用netstat -an |grep 9004 看到连接到这个队列管理器上连接.


猜你喜欢

转载自blog.csdn.net/lizhengyu891231/article/details/78672465