How to specify the number of consumer on my DeadLetterQueues? - apache-camel

I've two different Camel webapp which is connected to an ActiveMQ's queues throught a JMS connection.
These two webapp are independents, they have differents queues, differents AMQ instance, but the JMS configuration is the same:
<bean id="activemq" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory" ref="pooledConnectionFactory" />
<property name="transacted" value="true" />
<property name="transactionManager" ref="jmsTxManager" />
<property name="concurrentConsumers" value="10" />
<property name="testConnectionOnStartup" value="false" />
<property name="cacheLevelName" value="CACHE_CONSUMER" />
</bean>
On one of my webapp's AMQ's manager I can see that my DLQ have 10 consumers as defined in the property concurrentConsumers whereas my other webapp has 0 consumers on its DLQ (but other queues have the 10 expected consumers).
I thought that the concurrentConsumers parameter apply to every queues including automatically created DLQ. How can I add consumers to automatically created DeadLetterQueues?

Related

Apache Artemis - Apache Camel threaded consumer gets slow over time

I am running Apache Artemis Broker 2.14.0. Below is the consumer connection configuration:
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean class="com.test.CustomProcessBean" id="CustomProcessBean" scope="prototype"/>
<bean id="jmsCF" class="org.apache.qpid.jms.JmsConnectionFactory">
<property name="remoteURI" value="ampq://myhost:5672"/>
</bean>
<bean id="jmsPooledCF" class="org.messaginghub.pooled.jms.JmsPoolConnectionFactory" init-method="start" destroy-method="stop">
<property name="maxConnections" value="3" />
<property name="connectionFactory" ref="jmsCF" />
</bean>
<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="jmsPooledCF" />
<property name="concurrentConsumers" value="5" />
<property name="maxConcurrentConsumers" value="10" />
</bean>
<bean id="jms" class="org.apache.camel.component.amqp.AMQPComponent">
<property name="configuration" ref="jmsConfig" />
<property name="transacted" value="true" />
</bean>
<bean id="errHandler" class="org.apache.camel.builder.DeadLetterChannelBuilder">
<property name="deadLetterUri" value="jms:queue:customDLQ"/>
<property name="redeliveryPolicy" ref="customRedeliveryPolicyConfig"/>
</bean>
<bean id="customRedeliveryPolicyConfig" class="org.apache.camel.processor.RedeliveryPolicy">
<property name="maximumRedeliveries" value="3"/>
<property name="redeliveryDelay" value="8000"/>
</bean>
<camelContext id="camel"
xmlns="http://camel.apache.org/schema/spring">
<endpoint id="etams" uri="jms:queue:test-queue" />
<route errorHandlerRef="errHandler" >
<from uri="ref:etams"/>
<convertBodyTo type="java.lang.String" />
<threads id="threadedprocess" maxQueueSize="5" poolSize="5" maxPoolSize="5" customId="true" >
<bean ref="CustomProcessBean" method="processMessage"/>
</threads>
</route>
</camelContext>
</beans>
To begin with the route was processing ~100 message-per-second. Over time (~6 hrs) it dropped to ~25 messages-per-second.
From the "Consumers" tab in the Artemis web console I noticed each session is closed and created often.
From the broker side we had provided enough memory 12G. The broker runs with persistence enabled, and the incoming message size are less than 5kb.
Does the Camel threads try to create more session over time? Is this an anti-pattern? Is this the reason for consumer to process the messages slow overtime? When I don't use the Camel threads in the configuration (i.e. just <bean ref="CustomProcessBean ...>) I noticed the session ID created are NOT changing. This might be totally based on the use case, but does re-creating the sessions cause performance stress on broker?
I have faced the same issue and solved it by setting cacheLevelName option in the JMS endpoint to CACHE_CONSUMER. By enabling the transacted option, you end up setting cache level to CACHE_NONE.
This section will explain you better: JMS Component - TRANSACTIONS AND CACHE LEVELS

XA transactions Support with JBoss Widlfly 10, camel-2.15.3, and Red Hat AMQ 7.2

Problem Statement: In "JTA/XA" mode when messages are consumed from "Source-Q" using camel and after performing the business logic(successful processing without any error or exception) unable to send the response back to "Destination-Q".
Enabled "camel" logging but no "errors/exceptions" are found for the "Destination- end point".
Used Tech Stack:
JBoss Wildfly 10 (on Windows)
activemq-rar-5.11.0.redhat-630356.rar (latest as per https://maven.repository.redhat.com/ga/org/apache/activemq/activemq-rar/)
camel-2.15.3
Red Hat AMQ 7.2 (Linux). Used "artemis create" to create an instance with default configurations.
"Resource adaptor approach" is followed with JBoss Wildfly 10 to integrate with Red Hat MQ 7.2.
Snippets from JBoss Wildfly 10 - "standalone.xml" configurations are provided below:
<subsystem xmlns="urn:jboss:domain:resource-adapters:4.0">
<resource-adapters>
<resource-adapter id="activemq">
<archive>
activemq-rar-5.11.0.redhat-630356.rar
</archive>
<transaction-support>XATransaction</transaction-support>
<config-property name="ServerUrl">
tcp://redhatamqhostname:61616?jms.redeliveryPolicy.maximumRedeliveries=2
</config-property>
<config-property name="UserName">
defaultUser
</config-property>
<config-property name="InitialRedeliveryDelay">
1000
</config-property>
<config-property name="Password">
defaultPassword
</config-property>
<connection-definitions>
<connection-definition class-name="org.apache.activemq.ra.ActiveMQManagedConnectionFactory" jndi-name="java:/XAconnectionFactory" enabled="true" use-java-context="true" pool-name="ConnectionFactory">
<xa-pool>
<min-pool-size>1</min-pool-size>
<max-pool-size>20</max-pool-size>
<prefill>false</prefill>
<is-same-rm-override>false</is-same-rm-override>
</xa-pool>
</connection-definition>
</connection-definitions>
</resource-adapter>
</resource-adapters>
</subsystem>
Snippets from "camel-context" configurations are provided below:
<bean id="JBOSSRMQ" class="org.apache.camel.component.jms.JmsComponent">
<property name="configuration">
<bean class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="connectionFactory" />
<property name="transactionManager" ref="transactionManager" />
<property name="transacted" value="false" />
<property name="concurrentConsumers" value="1" />
<property name="deliveryPersistent" value="true" />
<property name="requestTimeout" value="10000" />
<property name="cacheLevelName" value="CACHE_NONE" />
</bean>
</property>
</bean>
<jee:jndi-lookup id="connectionFactory" jndi-name="java:/XAconnectionFactory"/>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
Any ideas/thoughts to make it work? Thanks in advance!

Setup independent ActiveMQ broker in camel blueprint xml

I am setting up a ServieMix instance using apache-camel as the routing engine, with my routes defined in a blueprint.xml. I am trying to configure ActiveMQ for my blueprint to be completely isolated from anything else (use its own, private, broker).
Here is my camel blueprint XML
<?xml version="1.0" encoding="UTF-8"?>
<blueprint
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0"
>
<bean id="record_ip" class="my.service.RecordIP"/>
<bean id="jmsConnectionFactory"
class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://myBroker?create=true&waitForStart=10000" />
<property name="userName" value="shadow"/>
<property name="password" value="broker"/>
</bean>
<bean id="pooledConnectionFactory"
class="org.apache.activemq.pool.PooledConnectionFactory" init-method="start" destroy-method="stop">
<property name="maxConnections" value="8" />
<property name="connectionFactory" ref="jmsConnectionFactory" />
</bean>
<bean id="jmsConfig"
class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="pooledConnectionFactory"/>
<property name="concurrentConsumers" value="10"/>
</bean>
<bean id="activemq"
class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="configuration" ref="jmsConfig"/>
</bean>
<camelContext xmlns="http://camel.apache.org/schema/blueprint">
<route id="tracing_route">
<from uri="jetty:http://localhost:9696/trace"/>
<inOnly uri="activemq:queue:ip_capture"/>
</route>
<route id="ip_capture">
<from uri="activemq:queue:ip_capture?concurrentConsumers=1&maxConcurrentConsumers=64&maxMessagesPerTask=100"/>
<bean ref="record_ip"/>
<log message="Finished!" loggingLevel="WARN" />
</route>
</camelContext>
</blueprint>
I don't think it's using the setup at all because I get the following error
Could not refresh JMS Connection for destination 'ip_capture' - retrying in 5000 ms. Cause: Error while attempting to add new Connection to the pool; nested exception is javax.jms.JMSException: Could not create Transport. Reason: java.io.IOException: Broker named 'amq-broker' does not exist.
And amq-broker is the default broker.
I'm pouring through everything I can find but something important is missing
http://camel.apache.org/activemq.html
http://activemq.apache.org/networks-of-brokers.html
http://activemq.apache.org/how-do-i-embed-a-broker-inside-a-connection.html
http://activemq.apache.org/xml-configuration.html
I can't use xmlns:amq="http://activemq.apache.org/schema/core" (ServiceMix can't resolve it)
I am using
ServiceMix 7.0.0
apache-camel/camel-blueprint 2.16.4
activemq-client/camel/blueprint 5.14.3
So long story sort, How do I properly configure ActiveMQ for my blueprint to be completely isolated from anything else?
I ended up not really needing to do this, because for all intents and purposes, the broker is independent, and setting up a new one doesn't change anything.

Using xa transactions in Karaf

I'm trying to create a xa transaction between postgres (using pax-jdbc to set up xa datasource) and activemq in karaf, using blueprint and camel.
The setup is the following: I have a camel route which receives a jms message, does some database updates, and then sends a jms message to another queue. This other queue then reads the updated records.
The problem is that the second queue is reading the old data instead of getting the updated data.
I believe the cause is that JMS transaction is being "released" first, and the database has not commited the changes yet.
If I put a Thread.sleep(1000) on the second queue, I always read the correct data. Also, I believe the transaction is working fine, if I throw an exception in the camel route, I see no changes in the database, and the jms message does not get sent, proving they are working together.
Here's my blueprint with the jta configs and camel route:
<blueprint
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cxf="http://camel.apache.org/schema/blueprint/cxf"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xmlns:tx="http://aries.apache.org/xmlns/transactions/v2.0.0"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://aries.apache.org/xmlns/transactions/v2.0.0 http://aries.apache.org/schemas/transaction/transactionv20.xsd">
<tx:enable/>
<bean id="resourceManager" class="org.apache.activemq.pool.ActiveMQResourceManager" init-method="recoverResource">
<property name="transactionManager" ref="jtaTxManager" />
<property name="connectionFactory" ref="jmsConnectionFactory" />
<property name="resourceName" value="activemq.localhost" />
</bean>
<bean id="redeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
<property name="maximumRedeliveries" value="0"/>
</bean>
<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQXAConnectionFactory">
<property name="brokerURL" value="$ext{brokerUrl}"/>
<property name="userName" value="karaf"/>
<property name="password" value="karaf"/>
<property name="redeliveryPolicy" ref="redeliveryPolicy"/>
</bean>
<bean id="jmsXaPoolConnectionFactory" class="org.apache.activemq.pool.JcaPooledConnectionFactory">
<property name="name" value="activemq.default"/>
<property name="maxConnections" value="4"/>
<property name="transactionManager" ref="jtaTxManager"/>
<property name="connectionFactory" ref="jmsConnectionFactory"/>
</bean>
<!-- define the activemq Camel component so we can integrate with the AMQ broker -->
<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
<!-- due to a bug in activemq-camel we must configure using a nested configuration bean -->
<property name="configuration">
<bean class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="jmsXaPoolConnectionFactory"/>
<!-- JTA transaction manager (Spring interface to Aries-TM) -->
<property name="transactionManager" ref="springJtaTxManager"/>
<!-- IMPORTANT: We set local transactions to false, because the JtaTransactionManager
will take care of enrolling the XA JMS Connection when needed. -->
<property name="transacted" value="false"/>
<!-- IMPORTANT: and disable cache level as the JtaTransactionManager needs to control the consumers
from its JcaPooledConnectionFactory -->
<property name="cacheLevelName" value="CACHE_NONE"/>
</bean>
</property>
</bean>
<reference id="jtaTxManager" interface="org.apache.geronimo.transaction.manager.RecoverableTransactionManager"/>
<reference id="springJtaTxManager" interface="org.springframework.transaction.PlatformTransactionManager"/>
<bean id="required" class="org.apache.camel.spring.spi.SpringTransactionPolicy">
<property name="transactionManager" ref="springJtaTxManager"/>
<property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/>
</bean>
<camelContext xmlns="http://camel.apache.org/schema/blueprint" id="om-bstask-context" useMDCLogging="true">
<route id="notificationConsumer">
<from uri="activemq:queue:incomingNotification"/>
<transacted ref="required"/>
<doTry>
<!-- execute some bd updates -->
<to uri="activemq:anotherQueue"/>
<doCatch>
<exception>java.lang.Exception</exception>
<handled>
<constant>false</constant>
</handled>
<bean beanType="xxxx.MessagingUtil"
method="logErrorMessage(${headers.JMSXDeliveryCount}, ${headers.om_txid}, 'incomingNotification', ${exception})"/>
</doCatch>
<doFinally>
</doFinally>
</doTry>
</route>
</camelContext>
</blueprint>
Do I have something wrong with my setup? Or what could explain this behavior?
PS I got the config from https://github.com/camelinaction/camelinaction2/blob/master/chapter12/xa-karaf/src/main/resources/OSGI-INF/blueprint/camel-context.xml

Apache Camel message multiplexer integration pattern

I am trying to determine the best way to combine message streams from two hornetq broker instances into a single stream for processing, using Apache Camel and Spring. This is essentially the opposite of the Camel reciepient list pattern; but instead of one to many I need many to one. One idea is to implement this functionality with the direct component:
<?xml version="1.0" encoding="UTF-8"/>
<beans xmlns="..."
xmlns="...">
<!-- JMS Connection 1 -->
<bean id="jndiTemplate1" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
...Connection 1 Specific Information...
</props>
</property>
</bean>
<bean id="jmsTopicConnectionFactory1"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate1"/>
</property>
<property name="jndiName">
<value>java:jms/RemoteConnectionFactory</value>
</property>
</bean>
<bean id="jms1" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory" ref="jmsTopicConnectionFactory1"/>
</bean>
<!-- JMS Connection 2 -->
<bean id="jndiTemplate2" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
...Connection 2 Specific Information...
</props>
</property>
</bean>
<bean id="jmsTopicConnectionFactory2"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate2"/>
</property>
<property name="jndiName">
<value>java:jms/RemoteConnectionFactory</value>
</property>
</bean>
<bean id="jms2" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory" ref="jmsTopicConnectionFactory2"/>
</bean>
<!-- Camel route many to 1 using direct component -->
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route id="hornetQ_broker_1">
<from uri="jms1:topic:testTopic1">
<to uri="direct:process_message">
</route>
<route id="hornetQ_broker_2">
<from uri="jms2:topic:testTopic2">
<to uri="direct:process_message">
</route>
<route id="message_processor">
<from uri="direct:process_message">
<log message="message_processor received message">
</route>
</camelContext>
</beans>
Question: Is the above approach recommended when a many->1 integration pattern is required? If multiple Apache Camel solutions exist, what are the key performance impacts of each approach?
Runtime environment:
HornetQ brokers are JBoss EAP6.
Camel context deployed to FuseSource 4.4.1
Each entity exists on a seperate server/jvm.
Notes:
The hornetQ broker instances cannot be clustered.
The hornetQ broker instances do not contain duplicate data.
I think that your approach is valid for your scenario. However, maybe direct is not the component you need to use for this if you are running in different JVMs.
There are different components for internal queues: Direct, Direct-VM, SEDA, VM, Disruptor... but I believe all of them are if you are running in the JVM (and some of the if you just running in the same CamelContext). For more info: How do the direct, event, seda and vm endpoints compare
If you are going to have different CamelContexts across different JVM will need to use a different component.

Resources