Apache Camel MQ连接池和计时器路由

时间:2014-08-04 22:24:17

标签: timer apache-camel connection-pooling

我有一个Web服务,可以与Camel一起接收Soap调用并将消息写入队列。同一服务还有一个定时器路由,它检查队列并逐个处理消息。 Web服务在多个服务器上的Tomcat容器上运行,后端队列是Websphere MQ。

我在Tomcat context.xml中有一个配置,如下所示:

<Resource name="jms/MyQueueConnectionFactory" auth="Container"
    type="com.ibm.mq.jms.MQQueueConnectionFactory"
    factory="com.ibm.mq.jms.MQQueueConnectionFactoryFactory"
    description="My Queue Connection Factory "
    CHANNEL="CLIENT.MYCHANNEL" HOST="localhost.com" PORT="3663"
    QMGR="MYCHANNEL" TRAN="1" UCP="Y" />    
<Environment name="jms/QmgrUsername" value="appuser" type="java.lang.String" />
<Environment name="jms/QmgrPassword" value="password1" type="java.lang.String" />

我在spring config中使用DSL路由器:

<bean id="EventRouter" class="com.myapp.router.EventRouter" />

<bean id="camelTracer" class="org.apache.camel.processor.interceptor.Tracer">
    <property name="traceExceptions" value="true"/>
    <property name="traceInterceptors" value="true"/>
    <property name="logLevel" value="INFO"/>
    <property name="logName" value="com.myapp.camel"/>
</bean>

<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
    <consumerTemplate id="consumer" />
    <template id="producer" /> 
    <routeBuilder ref="EventRouter" />
</camelContext>

<jee:jndi-lookup id="MyQueueConnectionFactory"
    jndi-name="java:comp/env/jms/MyQueueConnectionFactory" cache="true"
    lookup-on-startup="false" proxy-interface="javax.jms.ConnectionFactory" />
<jee:jndi-lookup id="MQUserName"
    jndi-name="java:comp/env/jms/QmgrUsername" cache="true"
    lookup-on-startup="true" />
<jee:jndi-lookup id="MQPassword"
    jndi-name="java:comp/env/jms/QmgrPassword" cache="true"
    lookup-on-startup="true" />

<bean id="myQueue" class="org.apache.camel.component.jms.JmsComponent">
    <property name="connectionFactory">
        <ref bean="CredentialsConnectionFactory"></ref>
    </property>
</bean>

<bean id="CredentialsConnectionFactory"
    class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
    <property name="targetConnectionFactory" ref="MyQueueConnectionFactory" />
    <property name="username" ref="MQUserName" />
    <property name="password" ref="MQPassword" />
</bean>

在我的EventRouter中,我将路由定义为:

import org.apache.camel.Exchange;
import org.apache.camel.ExchangePattern;
import org.apache.camel.LoggingLevel;
import org.apache.camel.Processor;
import org.apache.camel.builder.RouteBuilder;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import com.myapp.camelconsumer.QueueConsumer;
import com.myapp.camelproducer.QueueProducer;

public class EventRouter extends RouteBuilder {

    final private static String camelRouteURI = "cxf:/EventService?wsdlURL=classpath:wsdl/EventService.wsdl&serviceClass=EventService";
    final private static String inQueue = "myQueue:queue:QAW.MYAPP.IN";
    final private static String timerUrl = "timer://EventService?period=5m";

    @Autowired
    private QueueProducer producer;

    @Autowired
    private QueueConsumer consumer;

    @Override
    public void configure() throws Exception {

        from(timerUrl)
            .bean(consumer, "processQueueOnTimer('queueTimer')");

        from(camelRouteURI).recipientList(simple("direct:${header.operationName}"));

        from("direct:useEventService")
            .bean(producer, "processQueueRoute('useEventService')")
            .setExchangePattern(ExchangePattern.InOnly)
            .to(inQueue)
            .bean(producer, "setSuccessResponse('success')");       
    }

}

生产者非常简单,它获得Soap调用,验证消息并执行某些操作,然后将其放入MQ。计时器使用者每5分钟轮询一次队列并处理队列消息。

import java.util.Calendar;
import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
import org.apache.camel.PollingConsumer;
import org.springframework.stereotype.Component;
import com.cambia.enroll.web.service.CheckHealthRequest;
import com.myapp.exception.InternalErrorException;
import com.myapp.elog.exception.QueueException;

@Component
public class QueueConsumer {

    private static String inQueue = "myQueue:queue:QAW.MYAPP.IN";   

    public void processQueueOnTimer(String queueTimer, Exchange exchange) {
        try {           
            synchronized (this) {
                readFromQueue(exchange, inQueue);           
            }   
        } catch (Exception e) {
            System.out.println("An unknown exception occured in processQueueOnTimer, throw Internal error", e);
        }           
    }

    private void readFromQueue(Exchange exchange, String queueName) throws QueueException, Exception {
        String operationName = "";      
        CamelContext springCamelContext = exchange.getContext();
        Endpoint endpoint = springCamelContext.getEndpoint(queueName);
        PollingConsumer consumer = endpoint.createPollingConsumer();
        Exchange queueMessage = exchange;
        int count = 0;
        try {
            int timeout = 10000; // Default value if cannot read from property file
            // Read all messages from the queue
            while(true) {               
                queueMessage = consumer.receive(timeout);                   
                if (null == queueMessage || null == queueMessage.getIn()) {
                    break;
                }
                //process each queue message

            }
        } catch (Exception e) {
            throw new QueueException("Failure in readFromQueue for " + operationName + ": ", queueMessage, e);
        }       
    }   
}

很抱歉这条长信息,我的问题如下:)

1)Tomcat和Spring如何管理我在生产者组件的连接?它汇集与否?我使用的是UCP =&#34; Y&#34;在队列连接工厂中标记但是适用于Tomcat池还是仅在MQ Manager端?我使用 .to(inQueue)将消息放入队列 2)我是否在定时器路径上为消费者使用池化连接?我获取了camel生成的默认Exchange主体,然后使用它获取了CamelContext,Endpoint,PollingConsumer。我是否正确地为定时器路线做这个,或者是否有其他方法来获得池化连接 3)如何监控JMS连接状态?有没有办法可以查看池中的连接数,新连接和已释放的连接等? 4)在试图访问同一后端队列的多个实例上使用消费者客户端或定时器路由是否有任何问题?到目前为止,我没有注意到日志上有任何异常活动。

感谢。

0 个答案:

没有答案