cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache CXF > Scalable CXF applications using JMS transport
Date Sat, 15 Oct 2011 13:48:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/2042/9/15/_/styles/combined.css?spaceKey=CXF&amp;forWysiwyg=true"
type="text/css">
    </head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
    <h2><a href="https://cwiki.apache.org/confluence/display/CXF/Scalable+CXF+applications+using+JMS+transport">Scalable
CXF applications using JMS transport</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~ashakirin">Andrei
Shakirin</a>
    </h4>
        <br/>
                         <h4>Changes (0)</h4>
                                 
    
<div id="page-diffs">
                    <table class="diff" cellpadding="0" cellspacing="0">
    
            <tr><td class="diff-snipped" >...<br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <p>Java Message Service (JMS) is wide spread and popular messaging API. As JMS
is standardized, the same application code can successfully work with different JMS implementations:
WS MQ, Active MQ, Tibco, Joram, BEA WebLogic, OpenJMS.<br/>
CXF provides a transport that enables endpoints to use JMS queues and topics. </p>

<h2><a name="ScalableCXFapplicationsusingJMStransport-DefaultCXFconsumerandproducerusingJMS"></a>Default
CXF consumer and producer using JMS</h2>
<p>Implementing CXF client and service using JMS transport is trivial.<br/>
Basically, it is enough to configure two things in WSDL: <br/>
a) specify jms transport URI in binding element;<br/>
b) define jms address in port element.</p>

<p>WSDL binding and port should look like:</p>

<div class="code panel" style="border-style: solid;border-width: 1px;"><div class="codeContent
panelContent">
<pre class="code-java">
&lt;wsdl:binding name=<span class="code-quote">"Greeter_SOAPBinding"</span>
type=<span class="code-quote">"tns:Greeter"</span>&gt;
        &lt;soap:binding style=<span class="code-quote">"document"</span>
transport=<span class="code-quote">"http:<span class="code-comment">//cxf.apache.org/transports/jms"</span>/&gt;
</span>…
&lt;/wsdl:binding&gt;

&lt;wsdl:service name=<span class="code-quote">"JMSGreeterService"</span>&gt;
        &lt;wsdl:port binding=<span class="code-quote">"tns:JMSGreeterPortBinding"</span>
name=<span class="code-quote">"GreeterPort"</span>&gt;
            &lt;jms:address
                destinationStyle=<span class="code-quote">"queue"</span>
                jndiConnectionFactoryName=<span class="code-quote">"ConnectionFactory"</span>

jndiDestinationName=<span class="code-quote">"dynamicQueues/test.cxf.jmstransport.queue"</span>&gt;
               &lt;jms:JMSNamingProperty name=<span class="code-quote">"java.naming.factory.initial"</span>
value=<span class="code-quote">"org.apache.activemq.jndi.ActiveMQInitialContextFactory"</span>/&gt;
                  &lt;jms:JMSNamingProperty name=<span class="code-quote">"java.naming.provider.url"</span>
value=<span class="code-quote">"tcp:<span class="code-comment">//localhost:61616"</span>/&gt;
</span>           &lt;/jms:address&gt;
        &lt;/wsdl:port&gt;
 &lt;/wsdl:service&gt;
</pre>
</div></div>
<p>CXF clients and servers implemented in java or using Spring configuration magically
work for this WSDL (under the hood CXF selects correct JMS Conduit and Destination based on
address URL). <br/>
Details are described in <a href="http://cxf.apache.org/docs/jms-transport.html" class="external-link"
rel="nofollow">http://cxf.apache.org/docs/jms-transport.html</a>.<br/>
CXF also delivers jms_queue and jms_pubsub examples illustrating using JMS transport with
default settings for ActiveMQ.</p>

<h2><a name="ScalableCXFapplicationsusingJMStransport-Scalabilityproblems"></a>Scalability
problems</h2>
<p>Unfortunately there are two main scalability drawbacks when using default JMS configuration:</p>
<ol>
	<li>It doesn't provide sessions pooling and consumers/producers cache <img class="emoticon"
src="/confluence/images/icons/emoticons/star_yellow.gif" height="16" width="16" align="absmiddle"
alt="" border="0"/>.</li>
	<li>Default JMS message consumer is single threaded. It means that only one thread
will get messages from the queue or topic and pass them to further processing.</li>
</ol>


<p>Both aspects are critical for enterprise applications and their implementation is
not an easy task. Is there any solution? Yes: Spring JMS functionality and CXF Features. Let
discuss them in detail.</p>


<p><img class="emoticon" src="/confluence/images/icons/emoticons/star_yellow.gif"
height="16" width="16" align="absmiddle" alt="" border="0"/> - Some JMS vendors provide
integrated session pooling and consumers/producers cache in ConnectionFactory. In this case
using Spring CachingConnectionFactory is not necessary. Please refer vendor documentation
to clear it.</p>

<h2><a name="ScalableCXFapplicationsusingJMStransport-SpringJMSfunctionality"></a>Spring
JMS functionality</h2>
<p>Spring provides a number of useful classes that helps to implement scalable JMS application.
Important for us are: org.springframework.jms.connection.CachingConnectionFactory<br/>
org.springframework.jms.listener.DefaultMessageListenerContainer</p>

<h3><a name="ScalableCXFapplicationsusingJMStransport-CachingConnectionFactory"></a>CachingConnectionFactory
</h3>
<p>CachingConnectionFactory provides session pooling, consumers and producers cache.
Bellow is a sample configuration of CachingConnectionFactory:</p>

<div class="code panel" style="border-style: solid;border-width: 1px;"><div class="codeContent
panelContent">
<pre class="code-java">
&lt;bean id=<span class="code-quote">"cachingConnectionFactory"</span> class=<span
class="code-quote">"org.springframework.jms.connection.CachingConnectionFactory"</span>&gt;
	&lt;property name=<span class="code-quote">"targetConnectionFactory"</span>&gt;
		&lt;bean class=<span class="code-quote">"org.apache.activemq.ActiveMQConnectionFactory"</span>&gt;
			&lt;property name=<span class="code-quote">"brokerURL"</span> value=<span
class="code-quote">"tcp:<span class="code-comment">//localhost:61616"</span>
/&gt;
</span>		&lt;/bean&gt;
	&lt;/property&gt;
	&lt;property name=<span class="code-quote">"sessionCacheSize"</span> value=<span
class="code-quote">"20"</span>/&gt;
	&lt;property name=<span class="code-quote">"cacheProducers"</span> value=<span
class="code-quote">"<span class="code-keyword">true</span>"</span>/&gt;
	&lt;property name=<span class="code-quote">"cacheConsumers"</span> value=<span
class="code-quote">"<span class="code-keyword">true</span>"</span>/&gt;
&lt;/bean&gt;
</pre>
</div></div>

<p>As you can see it is possible to set the size of the session pool and switch on producers
and consumers caching.</p>

<h3><a name="ScalableCXFapplicationsusingJMStransport-DefaultMessageListenerContainer"></a>DefaultMessageListenerContainer</h3>
<p>DefaultMessageListenerContainer enables getting messages from the destination in
parallel, using multiple threads.<br/>
Configuration of DefaultMessageListenerContainer looks like:</p>
<div class="code panel" style="border-style: solid;border-width: 1px;"><div class="codeContent
panelContent">
<pre class="code-java">
&lt;bean id=<span class="code-quote">"queueContainerListener"</span>
	class=<span class="code-quote">"org.springframework.jms.listener.DefaultMessageListenerContainer"</span>&gt;
		&lt;property name=<span class="code-quote">"connectionFactory"</span> ref=<span
class="code-quote">"connectionFactory"</span> /&gt;
		&lt;property name=<span class="code-quote">"destinationName"</span> value=<span
class="code-quote">"Q_WM_OUT"</span> /&gt;
		&lt;property name=<span class="code-quote">"messageListener"</span> ref=<span
class="code-quote">"simpleListener"</span> /&gt;
		&lt;property name=<span class="code-quote">"cacheLevel"</span> value=<span
class="code-quote">"3"</span> /&gt;
		&lt;property name=<span class="code-quote">"concurrentConsumers"</span>
value=<span class="code-quote">"10"</span> /&gt;
		&lt;property name=<span class="code-quote">"maxConcurrentConsumers"</span>
value=<span class="code-quote">"50"</span> /&gt;
&lt;/bean&gt;	
</pre>
</div></div>
<p>It is possible to define here:</p>
<ol>
	<li>Initial and maximal number of concurrent consumers. This tells the Spring to always
start up a initial number of consumers (concurrentConsumers). When a new message has been
received, if the maxConcurrentConsumers has not been reached, then a new consumer is created
to process the message.</li>
	<li>Cache level (3- cache connections, sessions and consumers; 2 – cache connections
and sessions, 1 – cache connections only)</li>
	<li>Specify message listener class (implementing MessageListener interface) and connection
factory.</li>
</ol>


<p>It is important to be aware of following things related to consumers caching:</p>
<ul>
	<li>it doesn't make sense to increase the number of concurrent consumers for a JMS
topic. This just leads to concurrent consumption of the same message.</li>
	<li>the concurrentConsumers property and the maxConcurrentConsumers property can be
modified at runtime, for example, via JMX.<br/>
For the details you can refer following Bruce Snider's blog: <a href="http://bsnyderblog.blogspot.com/2010/05/tuning-jms-message-consumption-in.html"
class="external-link" rel="nofollow">http://bsnyderblog.blogspot.com/2010/05/tuning-jms-message-consumption-in.html</a>.</li>
</ul>


<p>You can see that Spring provides solution for both mentioned scalability aspects.
But how we can use it in CXF? </p>

<h2><a name="ScalableCXFapplicationsusingJMStransport-CXFFeatures"></a>CXF
Features</h2>
<p>As the CXF JMS implementation is based the Spring JMS classes the user can benefit
from described Spring JMS functionality.<br/>
CXF allows to configure details of the JMS transport using the JmsConfigFeature. A Feature
is something that is able to customize a Server, Client, or Bus, typically adding capabilities.
In our case we will add a feature in jaxws:endpoint and jaxws:client to tune the JMS transport.</p>

<h3><a name="ScalableCXFapplicationsusingJMStransport-Serverconfiguration"></a>Server
configuration</h3>

<div class="code panel" style="border-style: solid;border-width: 1px;"><div class="codeContent
panelContent">
<pre class="code-java">
&lt;bean id=<span class="code-quote">"cachingConnectionFactory"</span> class=<span
class="code-quote">"org.springframework.jms.connection.CachingConnectionFactory"</span>&gt;
	&lt;property name=<span class="code-quote">"targetConnectionFactory"</span>&gt;
		&lt;bean class=<span class="code-quote">"org.apache.activemq.ActiveMQConnectionFactory"</span>&gt;
			&lt;property name=<span class="code-quote">"brokerURL"</span> value=<span
class="code-quote">"tcp:<span class="code-comment">//localhost:61616"</span>
/&gt;
</span>		&lt;/bean&gt;
	&lt;/property&gt;
	&lt;property name=<span class="code-quote">"sessionCacheSize"</span> value=<span
class="code-quote">"20"</span>/&gt;
	&lt;property name=<span class="code-quote">"cacheConsumers"</span> value=<span
class="code-quote">"<span class="code-keyword">true</span>"</span>/&gt;
&lt;/bean&gt;

&lt;bean id=<span class="code-quote">"jmsConfig"</span> class=<span class="code-quote">"org.apache.cxf.transport.jms.JMSConfiguration"</span>
		p:connectionFactory-ref=<span class="code-quote">"cachingConnectionFactory"</span>
		p:cacheLevel=<span class="code-quote">"3"</span> 
		p:concurrentConsumers=<span class="code-quote">"16"</span>
		p:maxConcurrentConsumers=<span class="code-quote">"16"</span>
		p:targetDestination=<span class="code-quote">"Q_HSC"</span>
		p:wrapInSingleConnectionFactory=<span class="code-quote">"<span class="code-keyword">false</span>"</span>
	/&gt;

&lt;jaxws:endpoint id=<span class="code-quote">" JMSGreeterService"</span>
address=<span class="code-quote">"jms:<span class="code-comment">//"</span>
</span>		implementor=<span class="code-quote">"#JMSGreeterServiceImpl"</span>&gt;
		&lt;jaxws:features&gt;
			&lt;bean class=<span class="code-quote">"org.apache.cxf.transport.jms.JMSConfigFeature"</span>&gt;
				&lt;p:jmsConfig-ref=<span class="code-quote">"jmsConfig"</span>&gt;
			&lt;/bean&gt;
		&lt;/jaxws:features&gt;
&lt;/jaxws:endpoint&gt;
</pre>
</div></div>

<p>You can see that the endpoint configuration contains the JMSConfigFeature that has
a JMSConfiguration property.<br/>
JMSConfiguration supports all settings that we have seen in Spring DefaultMessageListenerContainer:
cached connection factory with session pool size, number of concurrent consumers, cache level.
All settings of JMSConfiguration are described in details in <a href="http://cxf.apache.org/docs/using-the-jmsconfigfeature.html"
class="external-link" rel="nofollow">http://cxf.apache.org/docs/using-the-jmsconfigfeature.html</a>.<br/>
Using this configuration the server application can be tuned to achieve optimal performance
in our target environment.</p>

<h3><a name="ScalableCXFapplicationsusingJMStransport-Clientconfiguration"></a>Client
configuration</h3>

<div class="code panel" style="border-style: solid;border-width: 1px;"><div class="codeContent
panelContent">
<pre class="code-java">
&lt;bean id=<span class="code-quote">"cachingConnectionFactory"</span> class=<span
class="code-quote">"org.springframework.jms.connection.CachingConnectionFactory"</span>&gt;
	&lt;property name=<span class="code-quote">"targetConnectionFactory"</span>&gt;
		&lt;bean class=<span class="code-quote">"org.apache.activemq.ActiveMQConnectionFactory"</span>&gt;
			&lt;property name=<span class="code-quote">"brokerURL"</span> value=<span
class="code-quote">"tcp:<span class="code-comment">//localhost:61616"</span>
/&gt;
</span>		&lt;/bean&gt;
	&lt;/property&gt;
	&lt;property name=<span class="code-quote">"sessionCacheSize"</span> value=<span
class="code-quote">"20"</span>/&gt;
	&lt;property name=<span class="code-quote">"cacheProducers"</span> value=<span
class="code-quote">"<span class="code-keyword">true</span>"</span>/&gt;
&lt;/bean&gt;

&lt;bean id=<span class="code-quote">"jmsConfig"</span> class=<span class="code-quote">"org.apache.cxf.transport.jms.JMSConfiguration"</span>
p:connectionFactory-ref=<span class="code-quote">"connectionFactory"</span> p:targetDestination=<span
class="code-quote">"Q_HSC"</span>
		p:wrapInSingleConnectionFactory=<span class="code-quote">"<span class="code-keyword">false</span>"</span>
/&gt; 

&lt;jaxws:client id=<span class="code-quote">"JMSGreeterService"</span> address=<span
class="code-quote">"jms:<span class="code-comment">//"</span>
</span>	serviceClass="com.sopera.services.tpoc.eventgenerator.EventGenerator”&gt;
		&lt;jaxws:features&gt;
			&lt;bean class=<span class="code-quote">"org.apache.cxf.transport.jms.JMSConfigFeature"</span>&gt;
				&lt;property name=<span class="code-quote">"jmsConfig"</span> ref=<span
class="code-quote">"jmsConfig"</span>/&gt;
			&lt;/bean&gt;
		&lt;/jaxws:features&gt;
	&lt;/jaxws:client&gt;
</pre>
</div></div>

<p>Client configuration looks very similar to the server one except two things:</p>
<ol>
	<li>CachingConnectionFactory  activates producers caching instead consumers caching;</li>
	<li>JMSConfiguration hasn’t concurrent consumers settings: client concurrency is
under application control and can be implemented using standard Java concurrency API.</li>
</ol>



<h2><a name="ScalableCXFapplicationsusingJMStransport-Conclusion"></a>Conclusion</h2>
<p>It is possible to achieve scalability of a CXF client and service using Spring JMS
functionality and the CXF JMS Configuration Feature. <br/>
It is not necessary to write any line of code, just configure and leverage already existing
stuff.<br/>
Using this feature can have essential invluence on the performance for some environments:
in one Prove Of Concept I have improved CXF service throughput on 360% (from 500 to 1800 msg/sec)
just using session pool and multithread JMS consumer!<br/>
Reference performance numbers for SOAP over JMS are represented in Christian Schneider's article:
<a href="http://www.liquid-reality.de/pages/viewpage.action?pageId=5865562" class="external-link"
rel="nofollow">http://www.liquid-reality.de/pages/viewpage.action?pageId=5865562</a>,
so you can easily compare it with own results and make appropriate tunning if necessary.</p>

<h2><a name="ScalableCXFapplicationsusingJMStransport-References"></a>References</h2>
<ol>
	<li>CXF JMS Transport: <a href="http://cxf.apache.org/docs/jms-transport.html" class="external-link"
rel="nofollow">http://cxf.apache.org/docs/jms-transport.html</a></li>
	<li>CXF Features: <a href="http://cxf.apache.org/docs/features.html" class="external-link"
rel="nofollow">http://cxf.apache.org/docs/features.html</a></li>
	<li>Spring JMS functionality: <a href="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/jms.html"
class="external-link" rel="nofollow">http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/jms.html</a></li>
	<li>Spring JMS performance tunning: <a href="http://bsnyderblog.blogspot.com/2010/05/tuning-jms-message-consumption-in.html"
class="external-link" rel="nofollow">http://bsnyderblog.blogspot.com/2010/05/tuning-jms-message-consumption-in.html</a></li>
	<li>CXF performance: <a href="http://www.liquid-reality.de/pages/viewpage.action?pageId=5865562"
class="external-link" rel="nofollow">http://www.liquid-reality.de/pages/viewpage.action?pageId=5865562</a></li>
</ol>

    </div>
        <div id="commentsSection" class="wiki-content pageSection">
        <div style="float: right;">
            <a href="https://cwiki.apache.org/confluence/users/viewnotifications.action"
class="grey">Change Notification Preferences</a>
        </div>
        <a href="https://cwiki.apache.org/confluence/display/CXF/Scalable+CXF+applications+using+JMS+transport">View
Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=27828015&revisedVersion=23&originalVersion=22">View
Changes</a>
                |
        <a href="https://cwiki.apache.org/confluence/display/CXF/Scalable+CXF+applications+using+JMS+transport?showComments=true&amp;showCommentArea=true#addcomment">Add
Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message