1、MQ 相关介绍,通用产品部,培训提纲,IBM WebSphere MQ概念与对象JMS使用发布/订阅的实现ActiveMQ介绍,概念与对象,WebSphere MQ 本质上是一种消息中间件,用于保证异构应用之间的消息传递。应用程序通过 MQ 接口进行互连通信,可以不必关心网络上的通信细节,从而将更多的注意力集中于应用本身。消息 (Message) 队列 (Queue)队列管理器(Queue Manager)通道 (Channel)监听器(Listener),消息(Message),消息是 WebSphere MQ 中最小的概念,本质上就是一段数据,它能被一个或多个应用程序所理解,是应用程序之间
2、传递的信息载体。消息可以大致分成两部分: 应用数据体和消息数据头消息数据头是对消息属性的描述, 这段信息往往被队列管理器用来确定对消息的处理。消息数据头可以由应用程序或系统的消息服务程序共同产生,它包含了消息在传送中的必要信息,如目标队列管理器的名字,目标队列的名字,以及消息的其它一些属性。 消息可以分成持久 (Persistent) 消息和非持久 (Non-Persistent) 消息。所谓“持久”的意思,就是在 WebSphere MQ 队列管理器重启动后,消息是否仍然能保持。,队列 (Queue),本地队列(QLocal)本地队列按功能又可分成初始化队列,传输队列,目标队列和死信队列。初
3、始化队列用做消息触发功能。传输队列只是暂存待传的消息,条件许可的情况下,通过管道将消息传送其它的队列管理器。目标队列是消息的目的地,可以长期存放消息。如果消息不能送达目标队列,也不能再路由出去,则被自动放入死信队列保存。,队列 (Queue),别名队列&远程队列 (QAlias & QRemote)只是一个队列定义,用来指定远端队列管理器中的队列。使用了远程队列定义,程序就不需要知道目标队列的位置模型队列(QModel)模型队列定义了一套本地队列的属性集合,一旦打开模型队列,队列管理器会按这些属性动态地创建出一个本地队列。,队列管理器 (Queue Manager),队列管理器是负责向应用程序
4、提供消息服务的机构。如果我们把队列管理器比作是数据库,那么队列就是其中的一张表,消息就是表中的一条记录。WebSphere MQ 中的队列管理器可以含有很多个队列,但一个队列只能属于一个队列管理器。一个操作系统平台可以创建一个队列管理器,也可以创建多个队列管理器。队列管理器、队列、通道等等都是 WebSphere MQ 的对象,所有的对象都有各自的属性,有些属性必须在对象创建的时候指定,有些可以在创建以后更改。,通道 (Channel),通道是两个队列管理器之间的一种单向的点对点的通信连接, 消息在通道中只能单向流动。如果需要双向交流,可以建立一对通道,一来一去。站在队列管理器的角度,这一对通
5、道可以按消息的流向分成输入通道和输出通道。 通过配置, 对于放入本地传输队列中的消息,队列管理器会自动将其通过输出通道发出,送入对方的远程目标队列。,JMS开发,jms即Java消息服务(Java Message Service)应用程序接口是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。JMS 中有一系列的类:ConnectionFactory,Connection,Session,MessageProducer, MessageConsumer,Message 在 JMS 编程时,程序首先要找出 ConnectionF
6、actory,以此创建 Connection,再建立 Session,以后所有的操作都以 Session 为基础。找出 Queue 或 Queue (统称 Destination),以此创建 QueueSender 或 QueuePublisher (统称 MessageProducer), 在该对象上发送或发布消息。也可以在 Destination 基础上创建 QueueReceiver 或 QueueSubscriber (统称 MessageConsumer),在该对象上接收或订阅消息。,Properties properties = new Properties();propertie
7、s.put(Context.INITIAL_CONTEXT_FACTORY, “com.sun.jndi.fscontext.RefFSContextFactory”);properties.put(Context.PROVIDER_URL, “file:/”);properties.put(Context.REFERRAL, throw);Context context = new InitialContext(properties);QueueConnectionFactoryqueueConnectionFactory = (QueueConnectionFactory) context
8、.lookup(“queueConnectionFactoryName”);Queue queue = (Queue) context.lookup(“queueName”);QueueConnection queueConnection =queueConnectionFactory.createQueueConnection();queueConnection.start();QueueSession queueSession = queueConnection.createQueueSession(transacted, Session.AUTO_ACKNOWLEDGE);MQQueue
9、ConnectionFactoryqueueConnectionFactory = new MQQueueConnectionFactory ();queueConnectionFactory.setTransportType(JMSC.MQJMS_TP_CLIENT_MQ_TCPIP); queueConnectionFactory.setQueueManager(this.managerName); queueConnectionFactory.setHostName (this.host); queueConnectionFactory.setPort (this.port); queu
10、eConnectionFactory.setChannel (this.channel);queueConnectionFactory.setCCSID(this.ccsid);,发送:QueueSender queueSender = queueSession.createSender(queue);queueSender.setDeliveryMode(DeliveryMode.NON_PERSISTENT); queueSender.setTimeToLive(300); /millisecondsObjectMessage msg = queueSession.createObject
11、Message();queueSender.send(msg);同步接收:QueueReceiver queueReceiver = queueSession.createReceiver(queue);Message msg = queueReceiver.receive();异步接收:queueReceiver.setMessageListener(new ReceiverThread();class ReceiverThread implements MessageListenerpublic void onMessage(Message message) ,JMS开发,是否使用 JND
12、I。JNDI 需要JMS Provider 支持的JNDI 环境,WebSphere MQ 5.3支持文件(bindings)、LDAP、IIOP (需要其它 J2EE 运行环境支持) 三种方式。 应用通信是用点对点 (Point-to-Point) 方式还是用发布/订阅 (Pub/Sub) 方式。点对点方式是双方通信,发布/订阅方式可以完成多方通信。 同步接收消息还是异步接收消息。同步读取即主动读取方式,异步读取则需要设定Listener,在消息到达后,自动调用 Listener 的 onMessage () 方法。 JMS 操作是否需要有交易保护。在交易保护下的JMS 操作是可以提交或回滚
13、的。 对于 MessageConsumer,消息在读取后通常需要确认 (Acknowledgement),这个确认是自动产生还是程序控制生成。程序控制的方式往往意味着更大的灵活性,但也更麻烦一些。 消息是否是持久性的。持久性的消息会记入 Log,在消息服务重启后仍然保留,就象记入数据库一样。 消息是否需要有超时设定。缺省情况下,消息都不会超时,有超时设置的消息在超时之后自动消失。 消息是否需要优先级设定。高优先级的消息在队列中可以排在靠前的位置。,发布/订阅(Publish/Subscribe),在有的应用环境中,消息的发送者在发送消息的时候并不知道有多少个接收者,更不知道消息的目的地在哪里。
14、在这种情况下,就需要发送者用类似于广播的方式将消息发布出去需要有设立一个中间机构,类似于邮局。消息的发布者就好像报社或杂志社,它在发布之前需要一次性地与邮局注册需要发行的刊物代码。消息订阅者就好像读者,需要到邮局确认需要订阅的刊物代码。邮局只负责递送业务,一旦有新的刊物出版,就会送到所有订阅过的读者手中。这种方式可以使得消息的订阅者只接收自己感兴趣的消息。在 WebSphere MQ 中这个中间机构叫做 Broker,消息发布程序叫做 Publisher,订阅程序叫做 Subscriber,订阅代码叫做主题 (Queue),Queue 是一个字符串,可以用“/”进行分级,比如:Sport/So
15、ccer/Reports。发布者和订阅者之间的只需约定一个 Queue 即可。类似于邮局和邮局可以互连,从而使本地读者可以订阅国外刊物。,发布/订阅(Publish/Subscribe),准备工作导入JMS系统队列(mqm/java/bin/MQJMS_PSQ.mqsc)启动代理(broker),发布/订阅(Publish/Subscribe),一个简单的消息Pub/Sub流程需要按照下面几步来走:1. 订阅者向代理的控制队列发送订阅请求。订阅消息的命令是RegSub,订阅者还应同时告诉控制队列所要订阅的主题,订阅者队列名字。2. 消息发布者向代理发送发布请求。命令是RegPub,还有一个强制
16、的参数是消息的主题。请求被发送到代理的控制队列,由后者来管理发布者的信息。3. 发布者向代理的流队列发布消息,它可以用API或者其它方式把消息写到队列中。4. 代理会根据向控制队列注册过的订阅信息和发布者信息,把消息按照不同的主题分发给对应的订阅者队列。这一步由代理自动完成。5. 订阅者的应用程序从订阅者队列里读取订阅到的消息。,异常处理,异常日志/var/mqm/qmgrs/QueueManagerName/errors异常编号,ActiveMQ 是什么 ?,Apache出品,最流行的,能力强劲的开源消息总线。完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现。 轻量
17、级,容易配置,特性及优势,1、实现 JMS1.1 规范,支持 J2EE1.4以上 2、可运行于任何 jvm和大部分 web 容器(ActiveMQ works great in any JVM) 3、支持多种语言客户端(java, C, C+, AJAX, ACTIONSCRIPT等等)4、支持多种协议(stomp,openwire,REST) 5、良好的 spring 支持(ActiveMQ has great Spring Support) 6、速度很快,JBossMQ的十倍(ActiveMQ is very fast; often 10x faster than JBossMQ.) 7、
18、与 OpenJMS、JbossMQ等开源jms provider 相比,ActiveMQ有Apache 的支持,持续发展的优势明显。,ActiveMQ 下载和部署,1、下载 官网(http:/activemq.apache.org) 下载最新版本 2、安装 直接解压至任意目录(如:d: apache-ctivemq-5.1.0) 3、启动 ActiveMQ服务器 直接运行 binactivemq.bat 4、ActiveMQ消息管理后台系统: http:/localhost:8161/admin,ActiveMQ 监控,1、Admin consoleshttp:/localhost:8161/
19、admin 2、JMX (jconsole)jmx:rmi:/jndi/rmi:/localhost:1099/jmxrmi,ActiveMQ 配置,activemq.xml文件: . producerFlowControl=true memoryLimit=1mb应用场景:消费者一直处于active状态,且效率大于生成者。否则当消息的大小达到内存限制值memoryLimit时,生产者会等待。, . producerFlowControl=“false memoryLimit=1mb . memoryUsage : NON_PERSISTENT messagesstoreUsage : PER
20、SITENT messages tempUsage : temporary messages, 5.1以后版本,ActiveMQ 配置,持久化 KahaDB: is a file based persistence database也可以通过JDBC方式连接其他数据库,性能相对较差。,JMS开发,和IBMMQ一样的流程,符合JMS规范。主要简介下GCOM-JMS.jar里的使用JMSConfig jconf = new JMSConfig();jconf.setMqType(MQType.MQTYPE_ACTIVE);jconf.setUrl(localhost);jconf.setPort(
21、61616);JMSTemplateFactory.setJmsConfig(jconf);,JMSTemplateSend sender = JMSTemplateFactory.getJMSTemplateSend(test,MQType.DESTINATION_QUEUE); sender.send(“hello wrold!”); /实现Serializable接口的对象send(serializableObj, isPersistent, timeToLive, tryTimes) JMSTemplateReceive receiver= JMSTemplateFactory.get
22、JMSTemplateReceive(test, MQType.DESTINATION_QUEUE);Object obj = receiver. recive();Object obj = receiver. recive(receiveTimeout,tryTimes);,GCOM-JMS,封装了JMS连接MQ的内部实现屏蔽了不同类型(IBM,ACTIVE)MQ的连接人性化封装了小功能。连接失败后自动创建连接(或显式指定次数)封装消息格式转换obj-message同一配置的不同连接(key).详见:http:/10.31.2.151:8118/svn/gcom/gcom-jms/Release-Area/JMS-V1.0/20090130/gcom-jms.doc,