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 consumer and producer using JMS transport
Date Wed, 05 Oct 2011 15:09: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+consumer+and+producer+using+JMS+transport">Scalable
CXF consumer and producer 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 (2)</h4>
                                 
    
<div id="page-diffs">
                    <table class="diff" cellpadding="0" cellspacing="0">
    
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >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></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">Using
this feature can have a huge invluence on the performance in some cases: in one Prove Of Concept
I have improved throughput of the CXF service on 220% just using session pool and multithread
JMS consumer. <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">Performance</span>
<span class="diff-added-words"style="background-color: #dfd;">Generic performance</span>
numbers regarding JMS transport are represented in Christian Schneider&#39;s article:
http://www.liquid-reality.de/pages/viewpage.action?pageId=5865562 <br></td></tr>
            <tr><td class="diff-unchanged" > <br>h2. References <br></td></tr>
            <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="ScalableCXFconsumerandproducerusingJMStransport-DefaultCXFconsumerandprocuderusingJMS"></a>Default
CXF consumer and procuder 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_pubsub and jms_pubsub examples illustrating using JMS transport with
default settings for ActiveMQ.</p>

<h2><a name="ScalableCXFconsumerandproducerusingJMStransport-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.</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>

<h2><a name="ScalableCXFconsumerandproducerusingJMStransport-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="ScalableCXFconsumerandproducerusingJMStransport-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="ScalableCXFconsumerandproducerusingJMStransport-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 initial and maximal number of concurrent message consumer
threads, cache level (3- cache consumers, 2 – cache session, 1 – no caching), specify
message listener class (implementing MessageListener interface) and connection factory.<br/>
You can see that Spring provides solution for both mentioned scalability aspects. But how
we can use it in CXF? </p>

<h2><a name="ScalableCXFconsumerandproducerusingJMStransport-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="ScalableCXFconsumerandproducerusingJMStransport-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="ScalableCXFconsumerandproducerusingJMStransport-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="ScalableCXFconsumerandproducerusingJMStransport-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 a huge invluence on the performance in some cases: in one Prove
Of Concept I have improved throughput of the CXF service on 220% just using session pool and
multithread JMS consumer.<br/>
Generic performance numbers regarding JMS transport 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></p>

<h2><a name="ScalableCXFconsumerandproducerusingJMStransport-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>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+consumer+and+producer+using+JMS+transport">View
Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=27828015&revisedVersion=10&originalVersion=9">View
Changes</a>
                |
        <a href="https://cwiki.apache.org/confluence/display/CXF/Scalable+CXF+consumer+and+producer+using+JMS+transport?showComments=true&amp;showCommentArea=true#addcomment">Add
Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message