Websphere MQ & 使用方式(API,spring,JNDI)

WMQ

配置

  • HostName
  • Channel
    • 队列管理器之间单向点对点通信连接,消息在通道中单向流动
  • Port
  • QueueManager
    • 消息队列的管理者
  • ConnectionNameList
    • 集群cluster,一个队列管理器属于多个集群
  • ClientReconnectOptions
  • CCSID
  • TransportType

API

依赖:
* mq-x
* connector-x
* jmqi-x
* commonservices-x
* headers-x
* mqjms-x

    public static void send(String qName, String msg) throws MQException, IOException {
        Hashtable properties = new Hashtable();
        properties.put(MQConstants.CONNECT_OPTIONS_PROPERTY, MQConstants.MQCNO_RECONNECT);
        properties.put(MQConstants.HOST_NAME_PROPERTY, connectionName);
        properties.put(MQConstants.PORT_PROPERTY, port);
        properties.put(MQConstants.CHANNEL_PROPERTY, channel);
        properties.put(MQConstants.CCSID_PROPERTY, ccsid);
        MQQueueManager queueMgr = new MQQueueManager(qManager, properties);
        MQQueue queue = queueMgr.accessQueue(qName, openOptions, null, null, null);
        MQMessage outMsg = new MQMessage();
        outMsg.write(msg.getBytes("UTF-8"));
        queue.put(outMsg, new MQPutMessageOptions());
        queueMgr.commit();

        queue.close();
        queueMgr.disConnect();
    }

连接池

缺省情况下,每次new MQQueueManger()调用都意味着应用程序与队列管理器多了一条连接,在MQ Clinet/Server 结构中表现为多了一条TCP/IP连接。每次MQQueueManger.disconnect()时这条连接断开,即为TCP/IP连接断开。例如,在同一个线程中,如果反复连接再断开MQ Connection,在MQ Clinet/Server 结构中表现为反复连接再断开TCP/IP连接,在系统中可以用netstat命令看到一些痕迹,即每次连接断开后的TIME_WAIT状态。
例:

for(int i = 0; i < 10; i++){
    qmgr = new MQQueueManager(sMQname);
    ...
    qmgr.disconnect();
}

如果使用了连接池 Connection Pool,在MQQueueManger.disconnect()时MQ连接并没真正断开,只是交回连接池,在下一次new MQQueueManager时重用。

MQPoolToken token = MQEnvironment.addConnectionPoolToken (); 
for (int i = 0; i < 10; i ++) 
{ 
    qmgr = new MQQueueManager (sQMName); 
    ... 
    qmgr.disconnect (); 
} 
MQEnvironment.removeConnectionPoolToken (token);

在并发线程的情况下,如果线程之间的new MQQueueManager()是串行的,则连接可以跨线程共享;
如果是并发的,则可以为每个线程创建一个连接复用环境,连接在此线程的串行new MQQueueManager()操作之间是复用的。

for (int i = 0; i < 3; i ++)
 {
    thread = new MQConnectionPoolThread (sQMName);
    thread.start ();
 }

 class MQConnectionPoolThread extends Thread
 {
    ...
    public void run ()
    {
        token = MQEnvironment.addConnectionPoolToken ();
        for (int i = 0; i < 5; i ++)
        {
            try
            {
                ***synchronized (getClass ())***
                {
                     qmgr = new MQQueueManager (sQMName);
                     sleep (1000);
                     qmgr.disconnect ();
                }
            }
        }
        MQEnvironment.removeConnectionPoolToken (token);
    }
 }

MQEnvironment中缺省Connection Pool最多可以保持10无用连接,每条最长保持5min。
例如:同时有 15 个并发 new MQQueueManager (),会有 15 条有用连接。
其中有 12 个很快就 MQQueueManager.disconnect () 了,这时应用会有 3 条有用连接,10条无用连接,另有 2 条连接断开。

可以用 MQEnvironment.setDefaultConnectionManager (MQConnectionManager) 将自己创建的 Connection Pool 设置成缺省的 Connection Pool。
MQConnectionManager 是一个 private interface,在 MQ Java Base 中只有一个类实现了这个界面:MQSimpleConnectionManager

MQQueueManager 的构造函数有一款为 : public MQQueueManager (String
queueManagerName,MQConnectionManager cxManager) 表示创建的连接加入 cxManager中的 Connection Pool,由 cxManager 进行管理 (最多无用连接、超时等等)。

spring-CachingConnectionFactory

依赖:
* jms-api-x
* dhbcore-x

配置

    <bean id="mqQueueConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
    
    bean>

    <bean id="cachingConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">  
        <property name="targetConnectionFactory" ref="mqQueueConnectionFactory" /> 
        <property name="sessionCacheSize" value="x" /> 
    bean>  

    <bean id="senderQueue" class="com.ibm.mq.jms.MQQueue">
        <property name="baseQueueName" value="xx"/>
        <property name="baseQueueManagerName" value="xx"/>    
    bean>

    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">    
        <property name="connectionFactory" ref="cachingConnectionFactory"/>  
        <property name="pubSubDomain" value="false"/>  
    bean> 

注意项

  1. Return code=2082 MQRC_UNKNOWN_ALIAS_BASE_Q opening a queue in the cluster.

    just leave the baseQueueManagerName blank
    reference

  2. 发送时,当有多个queue时,建议使用

    jmsTemplate.convertAndSend(QueueName, msg);

JNDI

配置

  • tomcat

<Resource name="jms/XXXMQ" auth="Container"
        type="com.ibm.mq.jms.MQQueueConnectionFactory" factory="com.ibm.mq.jms.MQQueueConnectionFactoryFactory"
        description=""
        HOST="xxx" PORT="xxx" CHAN="xxx" TRAN="1"
        CCSID="xxx" QMGR="xxx" />

<Resource name="jms/SENDQUEUE" auth="Container"
        type="com.ibm.mq.jms.MQQueue" factory="com.ibm.mq.jms.MQQueueFactory"
        description="ACTIVITY message input queue" QU="CMF_INPUTQ" CCSID="1208" />



<jee:jndi-lookup id="mqConnectionFactory" jndi-name="jms/XXXMQ" resource-ref="true" />

<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">    
        <property name="connectionFactory" ref="mqConnectionFactory"/>  
        <property name="defaultDestination" ref="SENDQUEUE"/>  
        <property name="pubSubDomain" value="false"/>  
    bean> 

Java code

@AutoWired
JmsTemplate jmsTemplate;
...
jmsTemplate.convertAndSend(msg);
jmsTemplate.convertAndSend(destinationName, msg);
...

ps:省略了MQ Interface上Queue和其他的配置

你可能感兴趣的:(MQ)