<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Qants - Tips in the field of Java Performance &#38; Software Testing</title>
	<atom:link href="http://alexandru-ersenie.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://alexandru-ersenie.com</link>
	<description>Software Testing in the world of Java Performance</description>
	<lastBuildDate>Tue, 24 Jan 2012 11:27:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='alexandru-ersenie.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Qants - Tips in the field of Java Performance &#38; Software Testing</title>
		<link>http://alexandru-ersenie.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://alexandru-ersenie.com/osd.xml" title="Qants - Tips in the field of Java Performance &#38; Software Testing" />
	<atom:link rel='hub' href='http://alexandru-ersenie.com/?pushpress=hub'/>
		<item>
		<title>Wine experience  &#8211; Sabatacha Gran Cuvee Negro &#8211; 2009</title>
		<link>http://alexandru-ersenie.com/2011/12/14/wine-experience-sabatacha-gran-cuvee-negro-2009/</link>
		<comments>http://alexandru-ersenie.com/2011/12/14/wine-experience-sabatacha-gran-cuvee-negro-2009/#comments</comments>
		<pubDate>Wed, 14 Dec 2011 23:20:49 +0000</pubDate>
		<dc:creator>Alexandru Ersenie</dc:creator>
				<category><![CDATA[2009]]></category>
		<category><![CDATA[Spanish wines]]></category>
		<category><![CDATA[Wines and Cooking]]></category>
		<category><![CDATA[Bodegas San Isidro]]></category>
		<category><![CDATA[Destroyed]]></category>
		<category><![CDATA[gran cuvee negro]]></category>
		<category><![CDATA[Jumilla]]></category>
		<category><![CDATA[Moby]]></category>
		<category><![CDATA[Monastrell]]></category>
		<category><![CDATA[Murcia]]></category>
		<category><![CDATA[sabatacha]]></category>
		<category><![CDATA[Shiraz]]></category>

		<guid isPermaLink="false">http://alexandru-ersenie.com/?p=684</guid>
		<description><![CDATA[And you all thought i can only speak tech&#8230; an old hobby of mine caught up, and reminded me of small pleasures in life&#8230; I decided to write about it, not only for sharing, but for myself, to remember&#8230;So if technology was the only reason you visited me&#8230;i hope this won&#8217;t be too big of [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=alexandru-ersenie.com&amp;blog=9058370&amp;post=684&amp;subd=qants&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://qants.files.wordpress.com/2011/12/sabatacha-gran-cuvee-negro-2009-3.jpg"><img class="alignleft  wp-image-685" title="Sabatacha - Gran Cuvee Negro - 2009" src="http://qants.files.wordpress.com/2011/12/sabatacha-gran-cuvee-negro-2009-3.jpg?w=151&#038;h=202" alt="Sabatacha - Gran Cuvee Negro - 2009" width="151" height="202" /></a></p>
<p>And you all thought i can only speak tech&#8230; an old hobby of mine caught up, and reminded me of small pleasures in life&#8230;</p>
<p>I decided to write about it, not only for sharing, but for myself, to remember&#8230;So if technology was the only reason you visited me&#8230;i hope this won&#8217;t be too big of a change. I can only promise there will still be more tech-oriented content <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Wine&#8230;my old-new born hobby&#8230;starting today with a spanish corrida&#8230;a mix of two great grapes into one fine wine&#8230;<strong>Sabatacha Gran Cuvee Negro</strong></p>
<p>The first thing i noticed after i let it breathe for a couple of minutes (and then anxiously poured myself a glass), was that amazing strong smell that the tanines give a wine&#8230;was not as strong as i was used with dry wines. This one was something special&#8230;I could dive into that glass, and take a deep, deep breath without feeling the usual spiciness, that usually requires another breath of fresh air.</p>
<p>This wine smells so wonderful, reminds me of blackberries, and of the jam my mother used to make from green, unripe walnuts. I can&#8217;t even decide if i feel the smell of walnuts or black cherries more&#8230; guess it&#8217;s a relative thing, cause these were my favorite ones when i was a kid&#8230;</p>
<p><strong>Sabatacha Gran Cuvee</strong> is a wine made of <strong>Monastrell</strong> and Shiraz, two varieties of grapes that make out strong, full-bodied wines. Monastrell is a grape known to be used for producing wines with a higher volume of alcohol&#8230;no wonder, the Gran Cuvee is one of the strongest dry ones i had&#8230;going for an impressive 14 %.</p>
<p>It&#8217;s color is a dark, dusty red, resulting from a beautiful dark blue monastrell grape, and a dry, old-aged black shiraz grape, with a great effect of vignetting when looked through. I just love the black color looking from aside, and the dark red one, looking from above.</p>
<p><a href="http://qants.files.wordpress.com/2011/12/sabatacha-gran-cuvee-negro-2009-1.jpg"><img class="alignright  wp-image-686" title="Sabatacha - Gran Cuvee Negro - 2009" src="http://qants.files.wordpress.com/2011/12/sabatacha-gran-cuvee-negro-2009-1.jpg?w=135&#038;h=180" alt="Sabatacha - Gran Cuvee Negro - 2009" width="135" height="180" /></a></p>
<p>Tasting it gives you somehow the feeling that you&#8217;re drinking a dry wine, and still, now and then, you feel like at the end, you have the feeling of an old-aged quality cognac&#8230;.sour, and then sweet&#8230;and then that flower-mouth feeling&#8230;</p>
<p>Listening to Moby&#8217;s latest album, &#8220;Destroyed&#8221;, also gave it a kick&#8230;can only recommend, other wines will work for sure <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Me and my wife, we wanted to have some fish today. But i said there&#8217;s no better thing to add to this great wine than some great greek, mediterranean food, seasoned with strong greek cheese&#8230;.And i was right&#8230;</p>
<p>Greek chicken with red and green paprika, onions, zucchini, brown champignons, garlic and light goat cheese&#8230;what a delight.</p>
<div></div>
<p>&nbsp;</p>
<div id="attachment_690" class="wp-caption aligncenter" style="width: 310px"><a href="http://qants.files.wordpress.com/2011/12/img_7726.jpg"><img class="size-medium wp-image-690" title="Greek chicken dish with vegetables - Good companion for Sabatacha tasting" src="http://qants.files.wordpress.com/2011/12/img_7726.jpg?w=300&#038;h=225" alt="Greek chicken dish with vegetables - Good companion for Sabatacha tasting" width="300" height="225" /></a><p class="wp-caption-text">Greek chicken dish with vegetables - Good companion for Sabatacha tasting</p></div>
<div id="attachment_689" class="wp-caption aligncenter" style="width: 310px"><a href="http://qants.files.wordpress.com/2011/12/img_7724.jpg"><img class="size-medium wp-image-689" title="Greek chicken dish with vegetables - Good companion for Sabatacha tasting" src="http://qants.files.wordpress.com/2011/12/img_7724.jpg?w=300&#038;h=225" alt="Greek chicken dish with vegetables - Good companion for Sabatacha tasting" width="300" height="225" /></a><p class="wp-caption-text">Greek chicken dish with vegetables - Good companion for Sabatacha tasting</p></div>
<div id="attachment_688" class="wp-caption aligncenter" style="width: 310px"><a href="http://qants.files.wordpress.com/2011/12/img_7721.jpg"><img class="size-medium wp-image-688" title="Greek chicken dish with vegetables - Good companion for Sabatacha tasting" src="http://qants.files.wordpress.com/2011/12/img_7721.jpg?w=300&#038;h=225" alt="Greek chicken dish with vegetables - Good companion for Sabatacha tasting" width="300" height="225" /></a><p class="wp-caption-text">Greek chicken dish with vegetables - Good companion for Sabatacha tasting</p></div>
<div id="attachment_687" class="wp-caption aligncenter" style="width: 310px"><a href="http://qants.files.wordpress.com/2011/12/img_7714.jpg"><img class="size-medium wp-image-687" title="Greek chicken dish with vegetables - Good companion for Sabatacha tasting" src="http://qants.files.wordpress.com/2011/12/img_7714.jpg?w=300&#038;h=225" alt="Greek chicken dish with vegetables - Good companion for Sabatacha tasting" width="300" height="225" /></a><p class="wp-caption-text">Greek chicken dish with vegetables - Good companion for Sabatacha tasting</p></div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>Facts:</p>
<ul>
<li><strong>Wine</strong>: Sabatacha &#8211; Gran Cuvee Negro</li>
<li><strong>Year</strong>: 2009</li>
<li><strong>Country and region of origin: </strong>Spain &#8211; Murcia/Jumilla</li>
<li><strong>Grapes</strong>: Monastrello and Shiraz</li>
<li><strong>Producer</strong>: Bodegas San Isidro</li>
<li><strong>Price</strong>: In german market, about 7 €</li>
<li><strong>Rating</strong>: Among all spanish wines that i have tried, this one stand out. A couple of days me and some friends tried a <strong>Tempranillo Crianza &#8211; Clos de Torribas</strong> from <strong>2006</strong>, having won a medal in Helsinki in 2009, and having been mentioned as a best buy by the Wine Enthusiast Magazine in 2009. I have to admit this one was better&#8230;Of course it is another grape, but it is all a matter of taste. And this wine will definitely land in my collection after having it tasted now. Superb color, great aroma, i just wish that fruit smell could last longer&#8230;</li>
<li><strong>Final rating: </strong>hard to say, but i have to rate them, for myself:) For a spanish dry wine, i&#8217;d say 8.5 out of 10 ( this is only cause i had some better red dry ones&#8230;)</li>
</ul>
<p>What a great evening&#8230;</p>
<p>Cheers,</p>
<p>Alex</p>
<p>&nbsp;</p>
<div></div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/qants.wordpress.com/684/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/qants.wordpress.com/684/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/qants.wordpress.com/684/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/qants.wordpress.com/684/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/qants.wordpress.com/684/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/qants.wordpress.com/684/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/qants.wordpress.com/684/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/qants.wordpress.com/684/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/qants.wordpress.com/684/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/qants.wordpress.com/684/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/qants.wordpress.com/684/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/qants.wordpress.com/684/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/qants.wordpress.com/684/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/qants.wordpress.com/684/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=alexandru-ersenie.com&amp;blog=9058370&amp;post=684&amp;subd=qants&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://alexandru-ersenie.com/2011/12/14/wine-experience-sabatacha-gran-cuvee-negro-2009/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/19315d494e10cf62a36e142aaf2177cf?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">skipper</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/12/sabatacha-gran-cuvee-negro-2009-3.jpg" medium="image">
			<media:title type="html">Sabatacha - Gran Cuvee Negro - 2009</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/12/sabatacha-gran-cuvee-negro-2009-1.jpg?w=225" medium="image">
			<media:title type="html">Sabatacha - Gran Cuvee Negro - 2009</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/12/img_7726.jpg?w=300" medium="image">
			<media:title type="html">Greek chicken dish with vegetables - Good companion for Sabatacha tasting</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/12/img_7724.jpg?w=300" medium="image">
			<media:title type="html">Greek chicken dish with vegetables - Good companion for Sabatacha tasting</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/12/img_7721.jpg?w=300" medium="image">
			<media:title type="html">Greek chicken dish with vegetables - Good companion for Sabatacha tasting</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/12/img_7714.jpg?w=300" medium="image">
			<media:title type="html">Greek chicken dish with vegetables - Good companion for Sabatacha tasting</media:title>
		</media:content>
	</item>
		<item>
		<title>Performance Tuning for Apache Worker Model with Glassfish Application Server</title>
		<link>http://alexandru-ersenie.com/2011/09/19/performance-tuning-for-apache-worker-model-with-glassfish-application-server/</link>
		<comments>http://alexandru-ersenie.com/2011/09/19/performance-tuning-for-apache-worker-model-with-glassfish-application-server/#comments</comments>
		<pubDate>Mon, 19 Sep 2011 16:17:42 +0000</pubDate>
		<dc:creator>Alexandru Ersenie</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Glassfish]]></category>
		<category><![CDATA[unix]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[apache keep alive]]></category>
		<category><![CDATA[apache max open connections]]></category>
		<category><![CDATA[apache memory]]></category>
		<category><![CDATA[apache servers]]></category>
		<category><![CDATA[apache thread model]]></category>
		<category><![CDATA[apache threads]]></category>
		<category><![CDATA[backlog]]></category>
		<category><![CDATA[backward tuning]]></category>
		<category><![CDATA[glassfish keep alive]]></category>
		<category><![CDATA[keep-alive]]></category>
		<category><![CDATA[mod_cache]]></category>
		<category><![CDATA[mod_deflate]]></category>
		<category><![CDATA[thread limit]]></category>
		<category><![CDATA[tuning tcp settings]]></category>
		<category><![CDATA[workers]]></category>

		<guid isPermaLink="false">http://qants.wordpress.com/?p=603</guid>
		<description><![CDATA[There is a lot of material and information on the subject of how to realize the two tier architecture, with the Apache Web Server in front of several application servers, like Tomcat, JBoss, Glassfish and so on. On the other hand, although the information is there, the number of configuration and fine tuning possibilities are [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=alexandru-ersenie.com&amp;blog=9058370&amp;post=603&amp;subd=qants&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>There is a lot of material and information on the subject of how to realize the two tier architecture, with the <strong>Apache Web Server</strong> in front of several application servers, like <strong>Tomcat, JBoss, Glassfish</strong> and so on.</p>
<p>On the other hand, although the information is there, the number of configuration and fine tuning possibilities are so high, that it takes quite a lot of try and err to sort, understand and implement them.</p>
<p>The aim of this post is to try to take not all, but maybe some hidden, or not so detailed variables in consideration for configuring the web and application server not only for normal workload, but for some extra load, and even for some spikes.</p>
<p>Online businesses, based on high transactional processing systems, need to be able to serve users <strong>fast, safe and reliable</strong>. It is not enough to be prepared for the normal workload. <strong>Real users</strong> will always<strong> behave differently</strong> and, with no exception, unpredictable to a level sometime hard to believe.</p>
<p>The posting deals with the following aspects:</p>
<ol>
<li>The concept of <strong>backward tuning</strong><br />
This is the starting point for determining the system capacity that we need to handle with the<strong> two dimensional</strong> web server &#8211; application server <strong>architecture</strong>. We will define key metrics like throughput, memory footprint, maximum number of users, etc. Although the concept is further applicable to the third tier component, the database, this is not part of this post</li>
<li>Building the Apache Workload Model</li>
<li>Apache configuration and tuning using the worker model</li>
<li>Glassfish configuration and tuning for the Workers Model</li>
</ol>
<h2>1. BACKWARD TUNING</h2>
<div>The concept is quite simple and straightforward:</div>
<ol>
<li>First determine how much and at what costs your last tier component &#8211; the application server &#8211; can handle.</li>
<li>Build your user model based on throughput and estimations, and limit any more than that entering your system.</li>
<li>Synchronize the first tier component &#8211; the web server &#8211; with the application server so that only the designated number of users can use the system</li>
</ol>
<div>A typical strategy would look like this:</div>
<div>
<ul>
<li>Start by determining the <strong>maximum capacity and throughput</strong> of your application server</li>
<li>Determine <strong>how many concurrent users</strong> can you handle on your <strong>application server</strong>, and what is their <strong>memory footprint (</strong>memory used by one user session for the duration of using your solution)</li>
<li>Determine the <strong>number of connections</strong> that you need to maintain open on the web server side in order to accommodate all users above</li>
<li>Tune the corresponding <strong>thread pools</strong> (web server and application server) accordingly, so that <strong>only a determined number of connections can be opened</strong> on the web server, and that only a determined number of users can make it to the application server</li>
<li>Determine the <strong>average number of business requests</strong> a user will execute on your system</li>
<li>Tune the <strong>backlog of the web server</strong> so that you can prepare for spikes, and that you can determine when to send the surplus users to another web server or waiting server</li>
<li>Tune the operating systems  for handling the configured number of connections &#8211; network, memory, open files, etc.</li>
</ul>
</div>
<p>By now, you should have gone through the process of  <strong>load and performance testing</strong> of your application. After this step, you should be in the position of knowing what resources you would need to reach <strong>maximum throughput</strong>. You should therefore also have <strong>configured and tuned your HEAP</strong> and decided on the <strong>Garbage Collection strategy</strong>. These are critical aspects that are derived after testing your application in an isolated one tier architecture, the application server.</p>
<p>These are the statistics that we need:</p>
<ul>
<li><strong>Number of transactions / second</strong> with a CPU load of max 80 % ( we need to leave an additional 20 % for workload spikes) that your application server can process</li>
<li><strong>Average think time between transactions </strong>how do users interact with your application? What is the average think time before firing the next transaction. Together with the &#8220;number of transactions / second&#8221; this will give you the maximum <strong>number of &#8220;business users&#8221; / application server</strong></li>
<li><strong><strong>Transaction Distribution Model: </strong></strong>percentage of users executing business transactions vs &#8220;just visitors&#8221;, users just surfing your web page. How many of your visitors are just surfing, and how many are calling business requests? The distribution model will tell you how many resources you will need, both on the web server and the application server</li>
<li><strong>User Memory Footprint:</strong> how much heap memory does a user executing transactions (to be called registered user) occupy vs a user just visiting the page &#8211; in other words, business session vs anonymous session. Depending on this information, you allow a maximum number of users to enter your system</li>
<li><strong>Transaction model: </strong>how are the business transactions being executed, how many HTTP connections are being opened for executing business transactions. Is your application an interactive application or a static resource intensive application? Typical browsers these days try to serve the content to the users as soon as possible, therefore opening several persistent connections to the web server at once (Firefox for example opens between 6 and 15 connections) How many connections are you using when triggering a business request? 1,2 or all 6 of them?</li>
</ul>
<div>Like already mentioned, the purpose is to <strong>determine what is the maximum throughput, and never allow more</strong>. Once you know this information, you can <strong>limit the number of users entering your system</strong> directly in the web server tier.</div>
<div>There are <strong>two things</strong> that you do not want to see your users experiencing:</div>
<div>
<ol>
<li><em><strong>Long and very long loading and response times</strong></em> &#8211; nowadays any webpage loading in more than 3 to 5 seconds is annoying. Dirk, an ex colleague of mine was telling me that an increase of 0.1 seconds in the loading time of Amazon costs a fortune&#8230;</li>
<li><em><strong>White pages and never loading page</strong></em> &#8211; This is even worse. A web page loading very slowly is still a loading web page. Yet, any new user landing on your product page, and experiencing a white page as his first experience will unlikely come again very soon.</li>
</ol>
</div>
<div>Once again, the purpose is to limit the number of users entering the complete system, and to allow a specific number of users to wait. Take this example:</div>
<div>It&#8217;s 19:00 in the evening, and you have a store operating until 20:00. Your store is currently full, and you know you can only server another 10 clients before closing the shop. You will then allow your client ticket machine to give no more than 10 additional waiting tickets. Any other client will have to use another store, or return tomorrow.</div>
<div>Any workload more than one server can handle can be scaled to a second server, a third server, and so on. Any additional <strong>user</strong> that can not get a <strong>connection in the web server</strong>, can be either <strong>placed in a queue</strong> (<strong>the socket backlog</strong>) or can be <strong>redirected to another free server</strong>, or, if there is none free, to a <strong>wait server</strong>.</div>
<div>We do not want any other inconsistent states. Any request can therefore:</div>
<div>
<ul>
<li>be <strong>processed</strong> immediately</li>
<li><strong>wait</strong> for a free working thread, and be <strong>processed</strong> with an acceptable delay</li>
<li>be <strong>redirected</strong> to another web server</li>
<li>be <strong>redirected</strong> to a wait server</li>
</ul>
</div>
<div>Let&#8217;s take an example to get a better look and understanding</div>
<div style="text-align:center;"><strong>TUNING STRATEGY EXAMPLE</strong></div>
<div>After examining the object map for both registered and unregistered users, we determine the following statistics:</div>
<h5><strong>Application Server User Memory footprint</strong></h5>
<div>
<ul>
<li>memory required / registered user: 1.5 MB</li>
<li>memory required / unregistered user (simple visitor): 0.5 MB</li>
</ul>
<h5><strong>Application Server Throughput</strong></h5>
<div>The system can process number of <strong>600 business transactions / second</strong> with the current hardware configuration, before the CPU goes beyond 80% usage, and starts spending more time in context switching and internal management, than satisfying requests</div>
<h5><strong>Application Server Workload model</strong></h5>
</div>
<div>
<ul>
<li>A<strong> business transaction</strong> is executed by a user every approximately <strong>3 seconds</strong></li>
<li>The <strong>average response time</strong> for a transaction is between <strong>half a second and a second</strong></li>
<li>Worse case scenario (is a strategy I often use): x users / (3 seconds think time + 1 second response time) = 600 transactions  =&gt;&gt; x = 2400 concurrent &#8220;business&#8221; users (users executing business transactions)</li>
<li>Light transactions (like users just visiting your webpage) are executed in a rate of 30 users / seconds, so that after one minute, you will have 60 seconds * 30 users = <strong>1800 anonymous users</strong></li>
</ul>
</div>
<div>We just determined a number of users for which we want to tune our system. We have decided on:</div>
<div>
<ul>
<li>1800 anonymous users, needing 1800*0.5 MB= 900 MB</li>
<li>2400 registered users, needing 2700*1.5 MB = 3600 MB</li>
</ul>
<h5><strong>Application Server HEAP structuring</strong></h5>
</div>
<div>We just determined that we need about <strong>5 GB of JVM Heap</strong> space for accommodating all the expected users. It is up to you to decide the <strong>allocation of memory</strong> in old generation, young generation, edens, the tenuring distribution, the <strong>garbage collection strategy</strong> and parameters and so on. One thing is clear: you will need at least the 5GB space in the old generation + at least 50 % more ( the CMS for example starts collecting the old generation once the old generation reaches approximately 68 % occupied space , so you might want to allocate at least 50 % more than what you will need to accommodate your users, so that you do not land in a continuous garbage collection)</div>
<h5><strong>Application Server Transaction Model</strong></h5>
<div>We have defined <strong>two types of transactions</strong>:</div>
<div>
<ul>
<li><strong>business transactions</strong> &#8211; executing some work in the database, persisting/modifying specific information, executing application logic with a result that is to be persisted</li>
<li><strong>light transactions</strong> &#8211; users just surfing on your page, not actually producing any workload on your database</li>
</ul>
<div>Let us suppose that after examining your application, you know by now that:</div>
<div>
<ul>
<li>business transactions are being processed using <strong>one single persistent connection</strong> ( in other words, keep alive connection). That means that several business transactions of the same user will use the one and same <strong>keep alive connection</strong> (of course, if such thing as keep alive is configured and activated)</li>
<li>light transactions are being processed using between 6 and 15 persistent connections (depending on the browser, FF uses for example between 6 and 15)</li>
</ul>
<div>Knowing the required number of connections / type of transaction, we can now determine the <strong>total number of connections needed:</strong></div>
<div>
<ul>
<li>total number of connections needed: 2400 registered users * 1 persistent connection + 1800 anonymous users * 6 persistent connections =13200 connections on the web server.</li>
</ul>
<div>Let&#8217;s stop a moment and see what this means:</div>
<div>If we want to accommodate 4100 users (2700 + 1800) on the web server, and each of them would require <strong>between 1 and 6 connections</strong>, we would need between 4100 and 24 600 connections, which is already a relatively high number of connections.</div>
<div>Yet, based on the workload model, we determined the <strong>average number of connections</strong> needed on the web server.</div>
</div>
<div>This is the point where we start configuring the web and application server for this workload, because apache allocates a thread to each connection, and considers each thread to be a connection.</div>
<div>So let&#8217;s tune the Apache Web Server to allow about 10 000 connections!</div>
</div>
<h2><strong>2. Building the Apache Web Server Model</strong></h2>
</div>
<div>I strongly recommend using the worker model, because of several considerations, of which i point the following as important:</div>
<div>
<ol>
<li>It costs less to spawn a large number of threads than to spawn new processes, as in the prefork model</li>
<li>The memory is shared between all threads belonging to a process</li>
<li>The number of threads can be dynamically increased using graceful restart of the web server</li>
<li>The number of threads used in the application server is somehow compressed, meaning that for each 2, 3, 4 apache threads, there will be one application server thread doing the application business. The application server thread will be at some point shared between web server threads. This way you can define <strong>a larger number of apache threads</strong>, with a <strong>lower number of application server threads</strong></li>
</ol>
</div>
<div>There are definitely other aspects that are less or more important, these are just some of the reasons why to choose the worker model.</div>
<div>In the worker model, <strong>APACHE attaches a thread to each connection. </strong>This means that <strong>one request</strong>, using <strong>6 persistent connections</strong>, will need <strong>6 APACHE threads.</strong></div>
<div><strong></strong>Let&#8217;s take the following example as an exercise of imagination. Suppose you configured APACHE to have a <strong>maximum number of threads of 12, and a backlog of 6</strong>.</div>
<div>With a request opening 6 connections, you will be able to accommodate no more than 2 users concurrently. A third user will land in the backlog. A forth user will receive a connect error. This would look like this:</div>
<div>
<div id="attachment_611" class="wp-caption aligncenter" style="width: 610px"><a href="http://qants.files.wordpress.com/2011/09/apache-workflow1.png"><img class="size-full wp-image-611" title="Apache Worker Model - Request Workflow" src="http://qants.files.wordpress.com/2011/09/apache-workflow1.png?w=600&#038;h=414" alt="Apache Worker Model - Request Workflow" width="600" height="414" /></a><p class="wp-caption-text">Apache Worker Model - Request Workflow</p></div>
</div>
<div>We know that the first two users will get their connections opened, respectively threads assigned. The question is now:</div>
<div>
<ul>
<li>how long will these users hang on this connection?</li>
<li>what if the user sends one request, and than does not send any additional request? When will the connection be closed and the thread returned to the pool?</li>
<li>what if the user opens the connection and regularly sends requests forever, keeping the connection open forever (Denial of service)</li>
</ul>
<div>All these aspects are covered by the KeepAlive configurable parameters, like:</div>
<div>
<ul>
<li><strong>KeepAlive</strong> (do we allow persistent connections at all)</li>
<li><strong>KeepAliveTimeout</strong> (how long should we wait on the client sending an additional request over the connection before closing the connection and returning the thread to the thread pool)</li>
<li><strong>MaxKeepAliveRequests</strong> (how many requests is a client allowed to send over one persistent connection before the server closes the connection and returns the thread to the thread pool)</li>
</ul>
</div>
</div>
<div>I find one factor of crucial importance. This is the <strong>KeepAliveTimeout</strong>. This dictates how long should a persistent connection stay exclusively open on the web server, waiting for another request to be sent over the connection, before the connection is terminated. But why is this so important?</div>
<div>Let&#8217;s assume we have a marketing campaign, which results in a workload of <strong>30 users / second</strong>, each loading the page with <strong>6 persistent connections</strong> (firefox default) Let us also assume we have a configured <strong>keep-alive timeout of 60</strong> seconds. That means:</div>
<div>
<ul>
<li>If one user sends <strong>one request</strong> over a persistent connection, and then <strong>waits 59 seconds</strong> before sending the next request, he will <strong>reuse the same connection</strong>, and no other connection (apache thread) will be created. But:</li>
<li>If one user sends a request over a persistent connection, and then waits longer than 60 seconds before sending the next one, or even worse, will never send an additional request, the connection will be kept open with no reason, and will be dropped without serving any more than one request. Not that optimal, is it?</li>
</ul>
<p>Using this configuration and a time-scaled representation, after 60 seconds you would have the following scenario:</p>
</div>
<div>30 users * 6 connections * 60 seconds = 10800 connections</div>
<div id="attachment_613" class="wp-caption aligncenter" style="width: 610px"><a href="http://qants.files.wordpress.com/2011/09/connections-timescale1.png"><img class="size-full wp-image-613" title="Apache Connections and Keep Alive" src="http://qants.files.wordpress.com/2011/09/connections-timescale1.png?w=600&#038;h=304" alt="Apache Connections and Keep Alive" width="600" height="304" /></a><p class="wp-caption-text">Apache Connections and Keep Alive</p></div>
<div>Of course you cannot keep all your connections open forever, and certainly you cannot keep 6 connections / client open forever. This is why it is so important to <strong>determine the workload distribution model</strong>. This defines how your users use the web server resources (number of connections)</div>
<div>The critical question here is: &#8221; How many percent of your users are executing <strong>business requests (1 connection)</strong> and how many are just <strong>surfing (6 persistent connections) </strong>?&#8221;</div>
<div>Starting with this, and taking also the average think time of your users in consideration, let&#8217;s try to redesign the concept above with a <strong>keep-alive timeout of 10 seconds</strong>, and an <strong>average response time</strong> for the loading of the web page of aprox. <strong>6 seconds</strong>. We will consider that <strong>60 % of all users</strong> loading the web page will<strong> continue executing business requests</strong>, and <strong>40 % will continue just surfing</strong>.</div>
<div>With the 30 users workload that we defined above, we will have the following distribution model:</div>
<div>
<ul>
<li><strong>60 % (18 users)</strong> will continue just executing <strong>business requests,</strong> needing <strong>one single persistent connection / user</strong></li>
<li><strong>40 % (12 users)</strong> will continue just <strong>surfing</strong>, needing<strong> 6 persistent connection / user</strong></li>
</ul>
<div>This means, that after loading the page, 60 % of the users will continue on one single persistent connection. But hey, what happens to the other 5 persistent connections?</div>
<div>Well, since no additional request is being sent over them, they will be dropped after the <strong>keep alive timeout interval</strong>, which in this case is set to <strong>10</strong>. So, after loading the web page (6 seconds), and after expiry of the keep alive timeout (10 seconds after the last request), the connections will be dropped:</div>
<div style="text-align:center;">6 seconds loading time + 10 seconds keep alive timeout = 16 seconds</div>
<div>That means that the first connections to be dropped are the ones at second 16. Starting that point, in the workload model defined above (30 new users per second) we will have a number of <strong>dropped connections / second</strong> of:</div>
<div style="text-align:center;">5 connections * 18 users = 90 connections.</div>
</div>
<div>This is how it will look in the same timescale:</div>
<div>
<div id="attachment_612" class="wp-caption aligncenter" style="width: 610px"><a href="http://qants.files.wordpress.com/2011/09/connections-timescale-keep-alive.png"><img class="size-full wp-image-612" title="Apache Connections Keep Alive" src="http://qants.files.wordpress.com/2011/09/connections-timescale-keep-alive.png?w=600&#038;h=424" alt="Apache Connections Keep Alive" width="600" height="424" /></a><p class="wp-caption-text">Apache Connections Keep Alive</p></div>
<p>Compared to the first model, where we had to maintain 10 800 connections, you now have to only maintain 6840 connections!</p>
<p>But, one target was to be also prepared for spikes. What if we have more users / second than 30 ? What do we do with them, how do we react to that, and how do we prevent the scenarios described in the beginning (white page, long waiting times, etc.)</p>
<p>Well, since we know we can accommodate 1800 users, using the 6840 connections, we can prepare for an extra 50 % workload. That would mean we would get to about 10 000 connections (6840 + 3420) I will just use 10 000 for simplicity.</p>
<p>Right. But&#8230;what will happen with the connection request 10001 ?</p>
<p>Since we know that we have a loading time of about 6 seconds, no user should wait longer than 3 seconds to get a connection (so that the total response time still falls under 10 seconds)</p>
<p>With a workload of 30 users / second, we can accommodate:</p>
<p style="text-align:center;">( 30 users * 6 connections * 3 seconds ) requests in 3 seconds= 540 requests</p>
<p>But we just spoke of spikes, so let us increase the backlog with 50 % to  810 connections.</p>
<p>That means:</p>
<ul>
<li>First 10000 requests will get their threads</li>
<li>requests between 10001 and 10810 will wait in the backlog for a free connection</li>
<li>request 10811 will be either sent to a wait server or to another scaled web server</li>
</ul>
<div>This should all look as follows:</div>
</div>
<div>
<div id="attachment_614" class="wp-caption aligncenter" style="width: 610px"><a href="http://qants.files.wordpress.com/2011/09/connection-tuning.png"><img class="size-full wp-image-614" title="Tuning Apache Workers for Load - The connection and backlog model" src="http://qants.files.wordpress.com/2011/09/connection-tuning.png?w=600&#038;h=424" alt="Tuning Apache Workers for Load - The connection and backlog model" width="600" height="424" /></a><p class="wp-caption-text">Tuning Apache Workers for Load - The connection and backlog model</p></div>
<p>Now that we decided on what we want to handle, let&#8217;s get our servers ready for this.</p>
<h2><strong>3. Configuring and tuning APACHE using Workers for performance and high number of connections</strong></h2>
<p>We need to take care both of APACHE configuration, and of configuration of the operating system where Apache resides</p>
<h3>APACHE WebServer Configuration</h3>
<p>We are ready to configure APACHE for 10 000  connections. Since it is more efficient to spawn threads than processes, let&#8217;s use a higher number of threads per process.</p>
<p>This is how a configuration could look like. With this configuration we will:</p>
<ul>
<li>start with <strong>25 servers</strong>, each spawning<strong> 200 threads</strong>, resulting <strong>5000 threads</strong></li>
<li>use about <strong>50 k / thread</strong>, resulting in about <strong>500 MB reserved memory</strong></li>
<li>expand to maximum <strong>50 servers</strong>, each spawning<strong> 200 threads</strong>, resulting <strong>10000 threads</strong>. This is also the value used by APACHE as <strong>MaxClients</strong> (maximum number of connections)</li>
<li>start shrinking the number of threads once the load has decreased, and keep<strong> no less than 7500 threads</strong> in the pool</li>
<li>allow <strong>no more than 100 000 requests</strong> / <strong>process</strong>, which results in an average of <strong>500 requests / child thread</strong>. We use this in order to avoid nasty users holding to the process forever, and we also avoid memory leaks, by destroying the process after the number of requests has been reached</li>
</ul>
<pre>&lt;IfModule worker.c&gt;
# initial number of server processes to start
# http://httpd.apache.org/docs/2.2/mod/mpm_common.html#startservers
StartServers        25
# highest possible MaxClients setting for the lifetime of the Apache process.
# http://httpd.apache.org/docs/2.2/mod/mpm_common.html#serverlimit
ServerLimit         50
# minimum number of worker threads which are kept spare
# http://httpd.apache.org/docs/2.2/mod/mpm_common.html#minsparethreads
MinSpareThreads     1000
# maximum number of worker threads which are kept spare
# http://httpd.apache.org/docs/2.2/mod/mpm_common.html#maxsparethreads
MaxSpareThreads    7500
# upper limit on the configurable number of threads per child process
# http://httpd.apache.org/docs/2.2/mod/mpm_common.html#threadlimit
ThreadLimit        200
# maximum number of simultaneous client connections
# http://httpd.apache.org/docs/2.2/mod/mpm_common.html#maxclients
MaxClients         10000
# number of worker threads created by each child process
# http://httpd.apache.org/docs/2.2/mod/mpm_common.html#threadsperchild
ThreadsPerChild     200
# maximum number of requests a server process serves
# http://httpd.apache.org/docs/2.2/mod/mpm_common.html#maxrequestsperchild
MaxRequestsPerChild  150
&lt;/IfModule&gt;
KeepAlive On
MaxKeepAliveRequests 1000
KeepAliveTimeout 10
ListenBackLog 810</pre>
<p>A couple of things to consider:</p>
<ol>
<ol>
<ol>
<ol>
<li><strong>MaxClients</strong>: If the allocated <em>MaxClients</em> is higher than <em>ServerLimit</em> * <em>ThreadLimit</em> Apache will automatically reduce <em>MaxClients</em> to the value of <em>ServerLimit</em> * <em>ThreadLimit<br />
</em>In this case, you will receive the following message:</p>
<pre>WARNING: MaxClients of 10000 would require 200 servers,
 and would exceed the ServerLimit value of 100.
 Automatically lowering MaxClients to 5000.  To increase,
 please see the ServerLimit directive.</pre>
</li>
<li><strong>Apache Memory / Process and Threads</strong>: Check if you have enough memory to handle the configured number of threads. Use the following scripts to monitor the Apache Servers, the number of threads, and the memory reserved:
<ul>
<li>The formula used for configuring your maximum number of clients is:<br />
<code><br />
maxclients = total ram / ram per process</code></li>
<li>List all <strong>Apache processes and number of threads per process</strong><br />
<code><br />
for pid in `ps U wwwrun | grep httpd | grep -v grep | awk '{ print $1 }'`;<br />
do echo Apache Worker Server $pid has `ps ms -p $pid | wc -l` threads;<br />
done<br />
</code><br />
This will output:<br />
<code><br />
Apache Worker Server 7528 has 3 threads<br />
Apache Worker Server 7583 has 3 threads<br />
Apache Worker Server 7587 has 3 threads<br />
Apache Worker Server 7596 has 204 threads<br />
Apache Worker Server 7601 has 204 threads<br />
Apache Worker Server 7610 has 204 threads<br />
Apache Worker Server 7618 has 204 threads<br />
Apache Worker Server 7628 has 204 threads<br />
Apache Worker Server 7640 has 204 threads<br />
Apache Worker Server 7651 has 204 threads<br />
Apache Worker Server 7668 has 204 threads<br />
............</code></li>
<li>List the <strong>reserved memory per APACHE Server and threads</strong><br />
<code><br />
servers=0;threads=0;space=0;<br />
for pid in `ps U wwwrun | grep httpd | grep -v grep | awk '{ print $1 }'`;<br />
do process_threads=`ps ms -p $pid | wc -l`;<br />
process_memory=`ps -ylC -p $pid | grep -v PID | awk '{ print $8}'`;<br />
echo Apache Worker Server with pid $pid has $process_threads threads occupying $process_memory bytes;<br />
servers=`expr $servers + 1`;threads=`expr $process_threads + $threads`;space=`expr $process_memory + $space`; done;<br />
echo "-------------"; echo Total Apache Servers: $servers \| Total threads: $threads \| Total memory reserved: $space<br />
</code><br />
This will output:<br />
<code><br />
.......<br />
Apache Worker Server with pid 1733 has 204 threads occupying 34644 bytes<br />
Apache Worker Server with pid 1759 has 204 threads occupying 34612 bytes<br />
Apache Worker Server with pid 1788 has 204 threads occupying 34620 bytes<br />
Apache Worker Server with pid 1816 has 204 threads occupying 34648 bytes<br />
Apache Worker Server with pid 1844 has 204 threads occupying 34648 bytes<br />
Apache Worker Server with pid 1875 has 204 threads occupying 34648 bytes<br />
Apache Worker Server with pid 1907 has 204 threads occupying 34684 bytes<br />
Apache Worker Server with pid 1940 has 204 threads occupying 34676 bytes<br />
-------------<br />
Total Apache Servers: 26 | Total threads: 5103 | Total memory reserved: 885272</code></li>
</ul>
</li>
<li><strong>ThreadsPerchild vs ThreadLimit</strong>: There is a difference between <strong><em>ThreadsPerchild</em></strong> and <strong><em>ThreadLimit</em></strong>. <em>ThreadsPerChild</em> defines the initial number of threads spawned per worker process. Defining a larger number as <em>ThreadLimit</em> allows you to modify the <em>ThreadsPerChild</em> up to <em>ThreadLimit</em>, without needing to do a hard restart of Apache. A graceful restart will suffice.For example:
<pre>ThreadsPerChild 100
ThreadLimit 500</pre>
<p>This will start the apache processes with 100 threads each. If you feel that your webserver cannot handle the current load with the current configuration, you just need to increase the <em>ThreadsPerChild</em>, (in this case to maximum  500) and execute a graceful restart:</p>
<pre>ThreadsPerChild 300
ThreadLimit 500</pre>
<p>Yet, it is very important to remember that:</li>
<ol>
<li><em>ThreadLimit</em> will allocate memory in advance, so check in advance if you can handle the<em> ServerLimit * ThreadsPerChild</em> with your current RAM</li>
<li>If you increase the <em>ThreadsPerChild</em> up to a value that the APACHE Server will consider it cannot allocate the needed memory, APACHE will exit!</li>
</ol>
<li><strong>ServerLimit vs ThreadLimit</strong>: You cannot increase the maximum number of server processes <em>ServerLimit</em> without hard restart of APACHE, so take this into consideration when planning the baseline configuration. If you want to be prepared for a higher load, configure the <em>ThreadLimit</em> higher, which will allow you to increase the capacity of your server with a graceful restart</li>
<li><strong>Number of Apache Threads spawned</strong>: Make sure that the number of threads spawned is the one you expect. Use the following to check the number of threads spawned.&#8221;Sl&#8221; is for Interruptable sleep, multithreaded
<pre>ps axsm | grep -c 'Sl'</pre>
</li>
<li><strong>Denial of Service and Keep Alive Parameter</strong>: Be prepared for Denial of Service Attacks. Do not allow any user to hold on to a persistent connection forever. Decide on the average number of transactions that a user will execute while using your system, and add it as parameter:
<pre>KeepAlive On
MaxKeepAliveRequests 1000
KeepAliveTimeout 10</pre>
</li>
<li><strong>Backlog for extra spikes:</strong>Be prepared for those extra spikes, where all your threads are busy, and you need a &#8220;waiting room&#8221; for your users. Use the ListenBackLog Directive, which we configured to 810:
<pre>ListenBackLog 810</pre>
</li>
<li><strong><span style="color:#ff0000;">ONE OF THE MOST IMPORTANT</span></strong>:<br />
The only way you can control the life of an APACHE server, and its children, is using this two parameters. Set them too high, and they will never die, therefore, the number of Threads in your Application Server will increase continously, eventually reaching the maximum configured number of threads, where it will stop servicing requests.<br />
Now, there are two parameters that control the behaviour of the apache servers and their children, and therefore the behaviour of the thread pool on the application server side. MaxRequestsPerChild refers to the maximum number of <strong>NEW</strong> requests (meaning a new client, opening a completely new Keep Alive Connection on this child) that can be sent over one Apache child. If for example, you had one client, opening a connection, and sending 500 requests, one after the other, on the same keep alive connection, than this parameter would have the value 1 (only the first request over a new keep alive connection will be counted) On the other hand, you do not want one client to hold on forever on his connection (remember the DOS), so you control that by setting the maximum, total number of requests a client can send over a SINGLE keep alive connection. When one of the two happens, the client will be assigned a new child thread, and the thread having served will be marked as &#8220;dead&#8221;</p>
<pre>MaxRequestsPerChild  150
MaxKeepAliveRequests 1000
</pre>
</li>
</ol>
</ol>
</ol>
</ol>
<div>The behaviour that you expect on the Glassfish side is an up/down one, where threads are being dropped and created over time.Not setting those values, you would have an increasing trend, up to the configured maximum number of threads.</div>
<div>This is how the Glassfish Thread Pool looked like after implementing this,<strong> monitored over a period of 1 day</strong>:</div>
<div><a href="http://qants.files.wordpress.com/2011/09/threadcountmonitoring-24hours-app4.jpg"><img class="aligncenter size-full wp-image-681" title="Glassfish MOD JK Thread Pool Monitoring 24 hours" src="http://qants.files.wordpress.com/2011/09/threadcountmonitoring-24hours-app4.jpg?w=600&#038;h=111" alt="Glassfish MOD JK Thread Pool Monitoring 24 hours" width="600" height="111" /></a></div>
<div>And this is how the Glassfish Thread Pool looked like, <strong>monitored over a period of 5 days</strong>!</div>
<div><a href="http://qants.files.wordpress.com/2011/09/threadcountmonitoring-29-sep-04-oct-app2.jpg"><img class="aligncenter size-full wp-image-682" title="Glassfish Mod JK Thread Pool Monitoring - 5 days" src="http://qants.files.wordpress.com/2011/09/threadcountmonitoring-29-sep-04-oct-app2.jpg?w=600&#038;h=72" alt="Glassfish Mod JK Thread Pool Monitoring - 5 days" width="600" height="72" /></a></div>
<div>
<h3>APACHE Operating System Configuration</h3>
<h5>Apache Tuning &#8211; Max Open Files</h5>
<p>Since every socket in Unix is actually a file, we need to tune the maximum allowed number of open files.</p>
<pre>This specifies the number of open files that are supported.
The default setting is typically sufficient for most applications. 
If the value set for this parameter is too low, a file open error,
memory allocation failure, or connection establishment error might
be displayed.</pre>
<p>More on this here: <a title="Linux Tuning for performance" href="http://publib.boulder.ibm.com/infocenter/wasinfo/v6r1/index.jsp?topic=%2Fcom.ibm.websphere.base.doc%2Finfo%2Faes%2Fae%2Ftprf_tunelinux.html" target="_blank">IBM Websphere Linux Tuning</a></p>
<h5>Apache Tuning &#8211; TCP Settings</h5>
<p>Keep in mind the seven layer architecture (also known as OSI model) Both Glassfish and Apache control the <strong>transport layer,</strong> which sits further on the <strong>network layer</strong>.</p>
<div id="attachment_636" class="wp-caption aligncenter" style="width: 430px"><a href="http://qants.files.wordpress.com/2011/09/osi-model.gif"><img class="size-full wp-image-636 " title="OSI Model - Seven layer architecture" src="http://qants.files.wordpress.com/2011/09/osi-model.gif?w=600" alt="OSI Model - Seven layer architecture"   /></a><p class="wp-caption-text">OSI Model - Seven layer architecture</p></div>
<p>Image courtesy: Novell -<a title="OSI Model" href="http://www.novell.com/info/primer/prim05.html" target="_blank"> http://www.novell.com/info/primer/prim05.html</a></p>
<p>You can configure and limit GLASSFISH and APACHE resources, as long as you do not exceed the network layer settings. That is why we need to take that also into consideration, and tune them accordingly, so that we can plug in the Glassfish or Apache without exceeding any configured resources</p>
<h5>Apache Tuning &#8211; Backlog and Maximum Connections</h5>
<p>Change the following parameters when you prepare for a high rate of incoming connections. Keep in mind that this setting is shared between all Apache Servers, so that if you want to host several web servers, you need to be prepared to accommodate the connections for all servers:</p>
<ul>
<ul>
<li>Number of connections in backlog: <em> cat /proc/sys/net/core/netdev_max_backlog</em> <strong>Default is 1000</strong>, modify this according to the maximum expected number of connections that you want to accommodate in your backlog (keep them waiting for a connection)</li>
<li>Size of the listen queue, in bytes, for accepting new tcp connections: <em> cat /proc/sys/net/core/somaxconn</em> Default is 128, modify this according to the size of the backlog you would need for the maximum expected number of connections that you want to accommodate in your backlog</li>
</ul>
</ul>
<h5>Apache Tuning &#8211; Operating System &#8211; Keep Alive Settings</h5>
<p>Although Unix has built-in support for KeepAlive, this is not the default behavior in Linux. Programs must request keepalive control for their sockets using the <tt>setsockopt</tt>interface. <a title="TCP Keep Alive How TO" href="//tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html%29">http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html</a>There are three &#8220;tunable&#8221; parameters:</p>
<div>
<dl>
<dt><tt>tcp_keepalive_time</tt></dt>
<dd>the interval between the last data packet sent (simple ACKs are not considered data) and the first keepalive probe; after the connection is marked to need keepalive, this counter is not used any further</dd>
<dt><tt>tcp_keepalive_intvl</tt></dt>
<dd>the interval between subsequential keepalive probes, regardless of what the connection has exchanged in the meantime</dd>
<dt><tt>tcp_keepalive_probes</tt></dt>
<dd>the number of unacknowledged probes to send before considering the connection dead and notifying the application layer</dd>
</dl>
</div>
<p>As long as the keep alive is high enough (higher than your configured Apache Server) you should not worry, since Apache will take care of managing the connections. Just make sure that the settings are higher than the ones configured in your web and application server. You can check all three by issuing the following command (i have also listed the default values for SUSE Linux Enterprise Server 11 ):</p>
<ul>
<li><em>cat /proc/sys/net/ipv4/tcp_keepalive_intvl  : 75 </em></li>
<li><em>cat /proc/sys/net/ipv4/tcp_keepalive_probes: 9</em></li>
<li><em>cat /proc/sys/net/ipv4/tcp_keepalive_time: 7200 (seconds)</em></li>
</ul>
<h5><strong>Apache Tuning &#8211; KEEP ALIVE SETTINGS</strong></h5>
<p>As defined above, these are the three configuration parameters you&#8217;d have to take care of when configuring for keep-alive connections (repeated, see above, chapter 2):</p>
<ul>
<ul>
<li><strong>KeepAlive</strong> (do we allow persistent connections at all)</li>
<li><strong>KeepAliveTimeout</strong> (how long should we wait on the client sending an additional request over the connection before closing the connection and returning the thread to the thread pool)</li>
<li><strong>MaxKeepAliveRequests</strong> (how many requests is a client allowed to send over one persistent connection before the server closes the connection and returns the thread to the thread pool)</li>
</ul>
</ul>
<h5>Apache Tuning &#8211; Operating System &#8211; CONNECTION MANAGEMENT</h5>
<p><strong></strong><em><strong>tcp_fin_timeout</strong>: </em></p>
<p>This basically holds a connection in a <strong>  TIME_WAIT</strong> mode (after the keep alive timeout expired), waiting for the same client to reinitiate the communication. Basically it says that it is cheaper to reactivate a sleeping connection, than to build a new one. Maintaining a connection open, after the user has not sent any additional request in the <strong>KeepAliveTimeout</strong> timeout defined may be expensive, since other users may just well sit in the backlog, waiting for exactly that one connection to be freed. If this is the case, you should set this to a level as low as possible, so that after a small timeout, the connection can be finally destroyed, and rebuilt with another id, for another user. <em></em></p>
<p><em>&#8220;This determines the time that must elapse before TCP/IP can release a closed connection and reuse its resources. This interval between closure and release is known as the TIME_WAIT state or twice the maximum segment lifetime (2MSL) state. During this time, reopening the connection to the client and server cost less than establishing a new connection. By reducing the value of this entry, TCP/IP can release closed connections faster, providing more resources for new connections. Adjust this parameter if the running application requires rapid release, the creation of new connections, and a low throughput due to many connections sitting in the TIME_WAIT state.&#8221;</em></p>
<p>More on this here: <a title="IBM WebSphere Tuning" href="//publib.boulder.ibm.com/infocenter/wasinfo/v6r1/index.jsp?topic=%2Fcom.ibm.websphere.base.doc%2Finfo%2Faes%2Fae%2Ftprf_tunelinux.html%22%20title=%22IBM%20WebSphere%20Tuning%22%20target=%22_blank%22%3E%3C/a%3E">IBM WebSphere Tuning</a></p>
<p>A simple way to see how many connections you have in TIME_WAIT is using netstat:</p>
<ul>
<li><code>watch --interval=1 "netstat | grep -c TIME_WAIT"</code></li>
</ul>
<p>You can view and set this parameter as follows:</p>
<ul>
<li>View:<em> <code>cat /proc/sys/net/ipv4/tcp_fin_timeout </code>: 60 (default on SUSE Linux Enterprise Server 11) </em></li>
<li>Set: <em>echo 10 &gt; /proc/sys/net/ipv4/tcp_fin_timeout</em><strong> </strong></li>
</ul>
<h5>Apache Tuning &#8211; Compression</h5>
<p>Most modern browsers can handle compressed content, decompressing it upon receiving it. It is a great idea to compress content, which will save you a lot of bandwidth. Of course, this comes with a price &#8211; CPU is needed for compressing the files. Since you do not want your application server to use resources for compression, leave it to the web server. And since Apache has caching mechanisms, this should not be a problem, since the file will be zipped once, and then saved and served in/from cache</p>
<blockquote><p>Most compression algorithms, when applied to a plain-text file, can reduce its size by 70% or more, depending on the content in the file. When using compression algorithms, the difference between standard and maximum compression levels is small, especially when you consider the extra CPU time necessary to process these extra compression passes. This is quite important when dynamically compressing Web content. Most software content compression techniques use a compression level of 6 (out of 9 levels) to conserve CPU cycles. The file size difference between level 6 and level 9 is usually so small as to be not worth the extra time involved.</p></blockquote>
<p><a title="Compressing web content with mod_gzip and mod_deflate" href="http://www.linuxjournal.com/article/6802" target="_blank">http://www.linuxjournal.com/article/6802</a></p>
<p>There are two modules for using compression in Apache:</p>
<ul>
<ul>
<li>mod_gzip</li>
<li>mod_deflate</li>
</ul>
</ul>
<div>Just be aware of the compression directives:</div>
<div>
<ul>
<ul>
<li>type of files you need to compress (it does not make sense compressing already compressed files like pdf, jpg, etc.): <code>AddOutputFilterByType DEFLATE text/html text/plain text/xml</code></li>
</ul>
</ul>
</div>
</div>
<h5>Apache Tuning &#8211; Caching</h5>
<p>Related to the point above, you can benefit of both compressing and caching content. You can either use a disk based cache store manager or a faster, memory based store manager</p>
<blockquote>
<div><code><a href="http://httpd.apache.org/docs/2.2/mod/mod_cache.html">mod_cache</a></code> implements an <a href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</a> compliant HTTP content cache that can be used to cache either local or proxied content. <code><a href="http://httpd.apache.org/docs/2.2/mod/mod_cache.html">mod_cache</a></code> requires the services of one or more storage management modules. Two storage management modules are included in the base Apache distribution:</div>
</blockquote>
<div>
<dl>
<dt><code><a href="http://httpd.apache.org/docs/2.2/mod/mod_disk_cache.html">mod_disk_cache</a></code></dt>
<dd>
<blockquote><p>implements a disk based storage manager.</p></blockquote>
</dd>
</dl>
</div>
<p><code><a href="http://httpd.apache.org/docs/2.2/mod/mod_mem_cache.html">mod_mem_cache</a></code></p>
<blockquote><p>implements a memory based storage manager. <code>mod_mem_cache</code> can be configured to operate in two modes: caching open file descriptors or caching objects in heap storage. <code>mod_mem_cache</code> can be used to cache locally generated content or to cache backend server content for <code><a href="http://httpd.apache.org/docs/2.2/mod/mod_proxy.html">mod_proxy</a></code> when configured using <code><a href="http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxypass">ProxyPass</a></code> (aka reverse proxy)</p></blockquote>
<p>More on this here: <a title="Caching content in APACHE" href="http://httpd.apache.org/docs/2.2/mod/mod_cache.html" target="_blank">http://httpd.apache.org/docs/2.2/mod/mod_cache.html</a></p>
<h2><strong>4. Configuring and tuning the Glassfish Application Server to work with the Workers Model</strong></h2>
<p>One thing you need to understand is that in the worker model, APACHE controls the lifecycle of working threads in Glassfish. Therefore, we need to configure Glassfish knowing that APACHE takes care of things like:</p>
<ul>
<ul>
<li>thread removal</li>
<li>keep alive timeouts</li>
<li>maximum number of requests / connection</li>
<li>compression</li>
<li>etc</li>
</ul>
</ul>
<p>Most UNIX distributions come with an out of the box configuration, that is prepared for normal workload, but definitely not for performance. We need to be aware of network, memory and other system resource settings that we have to reconfigure in order to gain and prepare for performance.</p>
<h3>Glassfish Tuning</h3>
<h5>Glassfish Tuning &#8211; Max Open Files</h5>
<p>Once again, since every socket in Unix is actually a file, we need to tune the maximum allowed number of open files.</p>
<p>You can of course set it to unlimited, but since we spoke of a APACHE Thread Pool -&gt; Glassfish Thread Pool compression, i would set this to half the number of threads apache can spawn + extra 5000 for all other processes<br />
<code><br />
ulimit -n 10000</code></p>
<p>Yet, be aware that if you have multiple Glassfish Domains Application Server, they will all share the number of open files. Keep this in mind when calculating the number of possible open threads / server.</p>
<h5>Glassfish Tuning &#8211; Max Threads</h5>
<p>Since your system can perform up to about 600 transactions / second, you should configure your maximum thread pool according to this number. Allow about 50 % more threads for those extra spikes, even if that comes with longer response times.</p>
<p>I would therefore set the maximum thread pool size to about (rounded) 1000:</p>
<p><code>&lt;thread-pool max-thread-pool-size="1024" name="http-thread-pool" /&gt;</code></p>
<h5>Glassfish Tuning &#8211; TCP Settings</h5>
<p>Keep in mind the seven layer architecture (also known as OSI model) Both Glassfish and Apache control the <strong>transport layer,</strong> which sits further on the <strong>network layer</strong> (see above, in chapter 3, Apache Tuning &#8211; TCP Settings)</p>
<p>You can configure and limit GLASSFISH and APACHE resources, as long as you do not exceed the network layer settings. That is why we need to take that also into consideration, and tune them accordingly, so that we can plug in the Glassfish or Apache without exceeding any configured resources</p>
<h5>Glassfish Tuning &#8211; Backlog and Maximum Connections</h5>
<p>Change the following parameters when you prepare for a high rate of incoming connections. Keep in mind that this setting is shared between all Glassfish Servers respectively Apache Servers:</p>
<ul>
<li>Number of connections in backlog: <em><br />
/proc/sys/net/core/netdev_max_backlog</em><br />
Default is 1000, modify this according to the maximum expected number of connections that you want to accommodate in your backlog (keep them waiting for a connection). Remember that these connections are the ones opened by APACHE, so you may want to tune this according to the maximum number of threads you will allow Apache to start inside the application server</li>
<li>Size of the listen queue, in bytes, for accepting new tcp connections:<br />
<em> /proc/sys/net/core/somaxconn</em><br />
Default is 128, modify this according to the size of the backlog you would need for the maximum expected number of connections that you want to accommodate in your backlog</li>
</ul>
<h5>Glassfish Tuning &#8211; Operating System &#8211; Keep Alive Settings</h5>
<p>Although Unix has built-in support for KeepAlive, this is not the default behavior in Linux. Programs must request keepalive control for their sockets using the <tt>setsockopt</tt>interface.</p>
<p><a title="TCP Keep Alive How TO" href="//tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html%29">http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html</a></p>
<p>There are three &#8220;tunable&#8221; parameters:</p>
<div>
<dl>
<dt><tt>tcp_keepalive_time</tt></dt>
<dd>the interval between the last data packet sent (simple ACKs are not considered data) and the first keepalive probe; after the connection is marked to need keepalive, this counter is not used any further</dd>
<dt><tt>tcp_keepalive_intvl</tt></dt>
<dd>the interval between subsequential keepalive probes, regardless of what the connection has exchanged in the meantime</dd>
<dt><tt>tcp_keepalive_probes</tt></dt>
<dd>the number of unacknowledged probes to send before considering the connection dead and notifying the application layer</dd>
</dl>
</div>
<p>As long as the keep alive is high enough (higher than your configured Glassfish or Apache Server) you should not worry, since Apache or Glassfish will take care of managing the connections. Just make sure that the settings are higher than the ones configured in your web and application server.</p>
<p>You can check all three by issuing the following command:</p>
<ul>
<li><em>cat /proc/sys/net/ipv4/tcp_keepalive_intvl</em></li>
</ul>
<ul>
<li><em>cat /proc/sys/net/ipv4/tcp_keepalive_probes</em></li>
</ul>
<ul>
<li><em>cat /proc/sys/net/ipv4/tcp_keepalive_time</em></li>
</ul>
<h5><strong>Glassfish Tuning &#8211; KEEP ALIVE SETTINGS</strong></h5>
<p>As mentioned above, Apache and Glassfish regulates this and other options at the protocol level. Interesting at this point are:</p>
<ul>
<li><strong>timeout-seconds</strong>: this is the time that GLASSFISH waits for a new request, before closing the connection. Since the internal thread behavior will be controlled by APACHE (it is APACHE&#8217;s thread after all), you should set it to unlimited, &#8220;-1&#8243; (default ist 30)</li>
<li><strong>max-connections</strong>: this is the maximum number of requests a client can send over a connection before GLASSFISH closes the connection. Since the internal thread behavior will be controlled by APACHE (it is APACHE&#8217;s thread after all), you should set it to unlimited, &#8220;-1&#8243;, and let APACHE clean the opened  threads (the ones opened in Glassfish) and connections by itself (default is 256)</li>
</ul>
<blockquote>
<pre>&lt;protocol name="http-protocol"&gt;
&lt;http xpowered-by="false" timeout-seconds="-1" max-connections="-1"
default-virtual-server="server" compressable-mime-type="text/html,
text/xml,text/plain,text/javascript,text/css" compression="on"
server-name=""&gt;
&lt;file-cache enabled="false" /&gt;
&lt;/http&gt;
&lt;/protocol&gt;</pre>
</blockquote>
</div>
<h5><strong>Glassfish Tuning &#8211; Operating System &#8211; CONNECTION MANAGEMENT</strong></h5>
<p><em>tcp_fin_timeout: </em></p>
<p>If maintaining a connection for you is expensive, you should reconfigure this parameter. This basically holds a connection in a TIME_WAIT mode (after the keep alive timeout expired), waiting for the same client to reinitiate the communication. Basically it says that it is cheaper to reactivate a sleeping connection, than to build a new one.</p>
<p>A simple way to see how many connections you have in TIME_WAIT is using netstat:</p>
<p><em>watch &#8211;interval=1 &#8220;netstat | grep -c TIME_WAIT&#8221;</em></p>
<p><em>&#8220;This determinesthe time that must elapse before TCP/IP can release a closed connection and reuse its resources. This interval between closure and release is known as the TIME_WAIT state or twice the maximum segment lifetime (2MSL) state. During this time, reopening the connection to the client and server cost less than establishing a new connection. By reducing the value of this entry, TCP/IP can release closed connections faster, providing more resources for new connections. Adjust this parameter if the running application requires rapid release, the creation of new connections, and a low throughput due to many connections sitting in the TIME_WAIT state.&#8221;</em><br />
More on this here:</p>
<p><a title="IBM WebSphere Tuning" href="//publib.boulder.ibm.com/infocenter/wasinfo/v6r1/index.jsp?topic=%2Fcom.ibm.websphere.base.doc%2Finfo%2Faes%2Fae%2Ftprf_tunelinux.html%22%20title=%22IBM%20WebSphere%20Tuning%22%20target=%22_blank%22%3E%3C/a%3E">IBM WebSphere Tuning</a></p>
<p>You can view and set this parameter as follows:</p>
<p><span style="text-decoration:underline;">View</span>:<em> cat /proc/sys/net/ipv4/tcp_fin_timeout</em></p>
<p><span style="text-decoration:underline;"><span style="color:#000000;text-decoration:underline;">Set</span></span>: <em>echo 10 &gt; /proc/sys/net/ipv4/tcp_fin_timeout</em><strong><br />
</strong></p>
<h5>Glassfish Tuning &#8211; Compression</h5>
<p>Most modern browsers can handle compressed content, decompressing it upon receiving it. It is a great idea to compress content, which will save you a lot of bandwidth.</p>
<p>Of course, this comes with a price &#8211; CPU is needed for compressing the files. Since you do not want your application server to use resources for compression, leave it to the web server. I have detailed compression in the web server in chapter 3, Configuring Apache.</p>
<p>If you still think that compression is a good idea, or you just want to play with it, these are the parameters you can change</p>
<p><em>compression-min-size-bytes</em> &#8211; defines the minimum size of files where compression will be applied. Everything equal or greater than this will be compressed and sent compressed to the client.</p>
<p><em>compressable-mime-type</em> &#8211; defines which extensions will be taken into consideration for compressing</p>
<p><em>compression</em> &#8211; sets the compression on or off</p>
<pre>&lt;protocol name="http-protocol"&gt;
&lt;http ......compression-min-size-bytes="4096"compressable-mime-type="text/html,
text/xml,text/plain,text/javascript,text/css" compression="on" server-name=""&gt;
&lt;file-cache enabled="false" /&gt;
&lt;/http&gt;
&lt;/protocol&gt;</pre>
<h5>Glassfish Tuning &#8211; Chunking</h5>
<p>No point reinventing the wheel&#8230;:) I will just quote wiki on that :</p>
<p>&#8221; Chunked transfer encoding is a data transfer mechanism in version 1.1 of the <a title="Hypertext Transfer Protocol" href="http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol">Hypertext Transfer Protocol</a> (HTTP) in which a <a title="Web server" href="http://en.wikipedia.org/wiki/Web_server">web server</a> serves content in a series of chunks. It uses the <a title="List of HTTP header fields" href="http://en.wikipedia.org/wiki/List_of_HTTP_header_fields#transfer-encoding-response-header">Transfer-Encoding</a> HTTP response header in place of the <a class="mw-redirect" title="Content-Length" href="http://en.wikipedia.org/wiki/Content-Length">Content-Length</a> header, which the protocol would otherwise require. Because the Content-Length header is not used, the server does not need to know the length of the content before it starts transmitting a response to the <a title="Client (computing)" href="http://en.wikipedia.org/wiki/Client_%28computing%29">client</a> (usually a <a title="Web browser" href="http://en.wikipedia.org/wiki/Web_browser">web browser</a>). Web servers can begin transmitting responses with dynamically-generated content before knowing the total size of that content.</p>
<p>The size of each chunk is sent right before the chunk itself so that a client can tell when it has finished receiving data for that chunk. The data transfer is terminated by a final chunk of length zero.</p>
<p>The introduction of chunked encoding into HTTP 1.1 provided a number of benefits:</p>
<ol>
<ol>
<ol>
<ul>
<li>Chunked transfer encoding allows a server to maintain a <a title="HTTP persistent connection" href="http://en.wikipedia.org/wiki/HTTP_persistent_connection">HTTP persistent connection</a> for dynamically generated content. Normally, persistent connections require the server to send a <a class="mw-redirect" title="Content-Length" href="http://en.wikipedia.org/wiki/Content-Length">Content-Length</a> field in the header before starting to send the entity body, but for dynamically generated content this is usually not known before the content is created.<sup class="reference"><a href="http://en.wikipedia.org/wiki/Chunked_transfer_encoding#cite_note-0">[1]</a></sup></li>
<li>Chunked encoding allows the sender to send additional header fields after the message body. This is important in cases where values of a field cannot be known until the content has been produced such as when the content of the message must be digitally signed. Without chunked encoding, the sender would have to buffer the content until it was complete in order to calculate a field value and send it before the content.</li>
<li>HTTP servers sometimes use <a title="Data compression" href="http://en.wikipedia.org/wiki/Data_compression">compression</a> (<a title="Gzip" href="http://en.wikipedia.org/wiki/Gzip">gzip</a>) or <a class="mw-redirect" title="Deflate" href="http://en.wikipedia.org/wiki/Deflate">deflate</a> methods to optimize transmission. Chunked transfer encoding can be used to delimit parts of the compressed object. In this case the chunks are not individually compressed. Instead, the complete payload is compressed and the output of the compression process is chunk encoded. In the case of compression, chunked encoding has the benefit that the compression can be performed on the fly while the data is delivered, as opposed to completing the compression process beforehand to determine the final size.&#8221;</li>
</ul>
</ol>
</ol>
</ol>
<p>Why disable a great feature?  Chunking comes enabled with Glassfish. Leave it as is.</p>
<h5>Logical renaming of thread pools for better resource management and monitoring</h5>
<p>The default configuration of Glassfish comes with three configured listeners:</p>
<ul>
<li><em>http-listener-1 &#8211; for http requests</em></li>
<li><em>http-listener-2 &#8211; for https secure requests</em></li>
<li><em>admin-listener &#8211; for admin purposes (opening the web administration console)</em></li>
</ul>
<p>The problem is that all of these listeners are configured to work on a single thread pool, thread-pool-1:</p>
<pre> &lt;network-listener port="8080" protocol="http-listener-1" transport="tcp"
name="http-listener-1" thread-pool="http-thread-pool" /&gt;
 &lt;network-listener port="8181" protocol="http-listener-2" transport="tcp"
name="http-listener-2" thread-pool="http-thread-pool" /&gt;
 &lt;network-listener port="4848" protocol="admin-listener" transport="tcp"
name="admin-listener" thread-pool="http-thread-pool" /&gt;</pre>
<p>This is not that optimal&#8230; If you find yourselve in the position that all threads of a thread pool are busy, you cannot even log in to your administration console.I do not agree to this &#8220;shared thread pool&#8221; model, so i recommend the logical organization and splitting of listeners, thread pools and protocols. This enables also a better monitoring of the threads, since each of them will appear with it&#8217;s own name, as in the example below:</p>
<p>And this is how the configuration would look like in the domain.xml file:</p>
<blockquote><p>&lt;network-config&gt;<br />
&lt;protocols&gt;<br />
&lt;protocol name=&#8221;http-protocol&#8221;&gt;<br />
&lt;http xpowered-by=&#8221;false&#8221; max-connections=&#8221;-1&#8243; default-virtual-server=&#8221;server&#8221; compressable-mime-type=&#8221;text/html,text/xml,text/plain,text/javascript,text/css&#8221; server-name=&#8221;"&gt;</p>
<p>&lt;file-cache enabled=&#8221;false&#8221; /&gt;</p>
<div id=":1bb">&lt;/http&gt;<br />
&lt;/protocol&gt;<br />
&lt;protocol security-enabled=&#8221;true&#8221; name=&#8221;secure-protocol&#8221;&gt;<br />
&lt;http xpowered-by=&#8221;false&#8221; default-virtual-server=&#8221;server&#8221; compressable-mime-type=&#8221;text/html,text/xml,text/plain,text/javascript,text/css&#8221; server-name=&#8221;"&gt;<br />
&lt;file-cache enabled=&#8221;false&#8221; /&gt;<br />
&lt;/http&gt;<br />
&lt;ssl ssl3-enabled=&#8221;false&#8221; cert-nickname=&#8221;s1as&#8221; /&gt;<br />
&lt;/protocol&gt;<br />
&lt;protocol name=&#8221;admin-protocol&#8221;&gt;<br />
&lt;http default-virtual-server=&#8221;__asadmin&#8221; server-name=&#8221;"&gt;<br />
&lt;file-cache enabled=&#8221;false&#8221; /&gt;<br />
&lt;/http&gt;<br />
&lt;/protocol&gt;<br />
&lt;protocol name=&#8221;jk-protocol&#8221;&gt;<br />
&lt;http xpowered-by=&#8221;false&#8221; max-connections=&#8221;-1&#8243; default-virtual-server=&#8221;server&#8221; compressable-mime-type=&#8221;text/html,text/xml,text/plain,text/javascript,text/css&#8221; server-name=&#8221;"&gt;<br />
&lt;file-cache enabled=&#8221;false&#8221; /&gt;<br />
&lt;/http&gt;<br />
&lt;/protocol&gt;<br />
&lt;/protocols&gt;<br />
&lt;network-listeners&gt;<br />
&lt;network-listener port=&#8221;8080&#8243; protocol=&#8221;http-protocol&#8221; transport=&#8221;tcp&#8221; name=&#8221;http-listener&#8221; thread-pool=&#8221;http-thread-pool&#8221; /&gt;<br />
&lt;network-listener port=&#8221;8081&#8243; protocol=&#8221;secure-protocol&#8221; transport=&#8221;tcp&#8221; name=&#8221;secure-listener&#8221; thread-pool=&#8221;secure-thread-pool&#8221; /&gt;<br />
&lt;network-listener port=&#8221;4848&#8243; protocol=&#8221;admin-protocol&#8221; transport=&#8221;tcp&#8221; name=&#8221;admin-listener&#8221; thread-pool=&#8221;admin-thread-pool&#8221; /&gt;<br />
&lt;network-listener port=&#8221;8009&#8243; protocol=&#8221;jk-protocol&#8221; transport=&#8221;tcp&#8221; name=&#8221;jk-main-listener-1&#8243; jk-enabled=&#8221;true&#8221; thread-pool=&#8221;jk-main-thread-pool1&#8243; /&gt;<br />
&lt;/network-listeners&gt;<br />
&lt;transports&gt;<br />
&lt;transport name=&#8221;tcp&#8221; /&gt;<br />
&lt;/transports&gt;<br />
&lt;/network-config&gt;<br />
&lt;thread-pools&gt;<br />
&lt;thread-pool max-thread-pool-size=&#8221;10&#8243; name=&#8221;http-thread-pool&#8221; /&gt;<br />
&lt;thread-pool max-thread-pool-size=&#8221;10&#8243; name=&#8221;admin-thread-pool&#8221; /&gt;<br />
&lt;thread-pool max-thread-pool-size=&#8221;50&#8243; name=&#8221;secure-thread-pool&#8221; /&gt;<br />
&lt;thread-pool max-thread-pool-size=&#8221;1024&#8243; name=&#8221;jk-main-thread-pool-1&#8243; /&gt;<br />
&lt;thread-pool max-thread-pool-size=&#8221;200&#8243; name=&#8221;thread-pool-1&#8243; /&gt;<br />
&lt;/thread-pools&gt;</div>
</blockquote>
<h2>Conclusion</h2>
<p>There are of course a lot of other options and &#8220;tunable&#8221; parameters. I have not tried to cover all of them, since this would be out of my power, knowledge, and before of all, time. It is probably the blog post for which i have been working most, so i would be delighted if this will be used/tried/implemented by some of you.</p>
<p>I would be also amazingly happy to receive remarks/critics or comments, since this is the result of a lot of brainstorming and try/err experiments.</p>
<p>I will update this blog post as i go along and find new and interesting things that have to be taken care of when configuring Apache and Glassfish for performance.</p>
<p>Thanks to Niels and Mario for their creativity, flexibility and agility. Together we are strong! <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>All best,</p>
<p>Alex</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/qants.wordpress.com/603/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/qants.wordpress.com/603/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/qants.wordpress.com/603/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/qants.wordpress.com/603/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/qants.wordpress.com/603/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/qants.wordpress.com/603/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/qants.wordpress.com/603/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/qants.wordpress.com/603/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/qants.wordpress.com/603/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/qants.wordpress.com/603/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/qants.wordpress.com/603/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/qants.wordpress.com/603/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/qants.wordpress.com/603/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/qants.wordpress.com/603/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=alexandru-ersenie.com&amp;blog=9058370&amp;post=603&amp;subd=qants&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://alexandru-ersenie.com/2011/09/19/performance-tuning-for-apache-worker-model-with-glassfish-application-server/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/19315d494e10cf62a36e142aaf2177cf?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">skipper</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/09/apache-workflow1.png" medium="image">
			<media:title type="html">Apache Worker Model - Request Workflow</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/09/connections-timescale1.png" medium="image">
			<media:title type="html">Apache Connections and Keep Alive</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/09/connections-timescale-keep-alive.png" medium="image">
			<media:title type="html">Apache Connections Keep Alive</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/09/connection-tuning.png" medium="image">
			<media:title type="html">Tuning Apache Workers for Load - The connection and backlog model</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/09/threadcountmonitoring-24hours-app4.jpg" medium="image">
			<media:title type="html">Glassfish MOD JK Thread Pool Monitoring 24 hours</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/09/threadcountmonitoring-29-sep-04-oct-app2.jpg" medium="image">
			<media:title type="html">Glassfish Mod JK Thread Pool Monitoring - 5 days</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/09/osi-model.gif" medium="image">
			<media:title type="html">OSI Model - Seven layer architecture</media:title>
		</media:content>
	</item>
		<item>
		<title>Java EE – Load &amp; Performance – Testing and reporting using open source tools – Part 2 – Configuring Load Generators &#8211; Generating load with JMeter, storing, filtering and preparing results for importing</title>
		<link>http://alexandru-ersenie.com/2011/05/27/java-ee-load-and-performance-testing-and-reporting-using-open-source-tools-part-2-configuring-load-generators-generating-load-with-jmeter-storing-filtering-importing/</link>
		<comments>http://alexandru-ersenie.com/2011/05/27/java-ee-load-and-performance-testing-and-reporting-using-open-source-tools-part-2-configuring-load-generators-generating-load-with-jmeter-storing-filtering-importing/#comments</comments>
		<pubDate>Fri, 27 May 2011 11:53:53 +0000</pubDate>
		<dc:creator>Alexandru Ersenie</dc:creator>
				<category><![CDATA[Glassfish]]></category>
		<category><![CDATA[ireport]]></category>
		<category><![CDATA[jasper reports]]></category>
		<category><![CDATA[jasper server]]></category>
		<category><![CDATA[jmap]]></category>
		<category><![CDATA[JMeter]]></category>
		<category><![CDATA[JMeter Jasper Performance Reports]]></category>
		<category><![CDATA[Load and Performance Test Aspects]]></category>
		<category><![CDATA[Pentaho Data Integration]]></category>
		<category><![CDATA[performance metrics]]></category>
		<category><![CDATA[performance test strategies]]></category>
		<category><![CDATA[software performance testing]]></category>
		<category><![CDATA[unix]]></category>
		<category><![CDATA[continuous integration system]]></category>
		<category><![CDATA[etl]]></category>
		<category><![CDATA[hudson]]></category>
		<category><![CDATA[jmeter jasper report]]></category>
		<category><![CDATA[load and performance report]]></category>
		<category><![CDATA[open source load testing]]></category>
		<category><![CDATA[open source reporting tools]]></category>

		<guid isPermaLink="false">http://qants.wordpress.com/?p=462</guid>
		<description><![CDATA[CONFIGURING LOAD GENERATORS &#8211; JMETER . Load testing generators &#8211; Getting your application under load with distributed JMeter CONFIGURING JMETER DISTRIBUTED MODE JMeter is the number one open source tool for generating load. It simulates multiple virtual users, by running the test for each virtual user in a separate thread. It is built on Java Platform, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=alexandru-ersenie.com&amp;blog=9058370&amp;post=462&amp;subd=qants&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<div>
<h2>CONFIGURING LOAD GENERATORS &#8211; JMETER</h2>
<p style="text-align:center;">.</p>
<h4>Load testing generators &#8211; Getting your application under load with distributed JMeter</h4>
<ol>
<ol>
<ol>
<li><strong><strong><strong>CONFIGURING JMETER DISTRIBUTED MODE<br />
</strong></strong></strong>JMeter is the number one open source tool for generating load. It simulates multiple virtual users, by running the test for each virtual user in a separate thread. It is built on <strong>Java Platform</strong>, hence it provides high portability. It provides a straight-forward graphical interface for designing and running tests, which turns to be very helpful for debugging purposes. Additionally, it allows<strong> running testplans in command line interface</strong>, eliminating therefore the resource consumption overhead of the GUI.Configured in <strong>Distributed Mode, JMeter</strong> allows using <strong>multiple instances of JMeter as agents</strong> (slaves), using the <strong>RMI protocol</strong> and configurable ports. Thank to this, any new <strong>JMeter Agent can be &#8220;plugged in&#8221;</strong>at any time by simply starting the agent, and adding it to the list of slaves.It is of course best to keep your JMeter environment in a<strong> separate subnetwork</strong>, in order to avoid any outer factors like network delays due to traffic in the main network. I suggest using the <strong>JMeter Server</strong> as a gateway to the <strong>JMeter load subnetwork</strong>, so that the JMeter server has<strong> two network interfaces</strong>:</p>
<ul>
<li>One for communicating with the main network, where the <strong>database and reporting server</strong> will reside</li>
<li>One for communicating and controlling the load on the JMeter Agents residing in the JMeter load subnetworkA simple graphical representation of this structure looks like below:</li>
</ul>
<div style="text-align:center;">
<dl>
<dt><a href="http://qants.files.wordpress.com/2011/05/jmeter-distributed-structure.png"><img title="JMeter Distributed Testing Structure" src="http://qants.files.wordpress.com/2011/05/jmeter-distributed-structure.png?w=540&#038;h=327" alt="JMeter Distributed Testing Structure" width="540" height="327" /></a></dt>
<dd><strong>JMeter Distributed Testing Example</strong></dd>
<dt>.</dt>
</dl>
</div>
<p>Now, JMeter is a very flexible solution, and it is designed to get your tests up and running in no time. In order to run in in distributed mode, one of your servers has to be the controller. I suggest keeping this server as a controller only, and not using it also for generating load, but for collecting results, starting transformations, running scripts,etc. Think of it like a &#8220;<strong>Test Commander</strong>&#8220;</p>
<p>There are two steps that have to be performed in order to get your distributed environment running:</p>
<ul>
<ul>
<li><strong><strong>Configure the JMeter Master Controller</strong></strong></li>
</ul>
</ul>
<p>This is quite simple. You need to modify one single property file, residing in the <strong>bin folder of your JMeter installation folder</strong>. The file to be modified is &#8220;<strong>jmeter.properties</strong>&#8220;<br />
Look for the following block:<br />
<code><br />
<span style="color:#008000;">#---------------------------------------------------------------------------</span><br />
<span style="color:#008000;"> # Remote hosts and RMI configuration</span><br />
<span style="color:#008000;"> #---------------------------------------------------------------------------</span><br />
<span style="color:#008000;"> # Remote Hosts - comma delimited</span><br />
<span style="color:#008000;"> remote_hosts=127.0.0.1</span><br />
<span style="color:#008000;"> #remote_hosts:localhost:1099,localhost:2010This is where you have to add your JMeter servers, as remote_hosts, separated by comma, like this:remote_hosts=192.168.1.2,192.168.1.3,192.168.1.4</span><br />
</code><br />
I do suggest adding the JMeter agents as a list of IP&#8217;s instead of hostnames, to avoid any DNS problems due to faulty network configurations.</p>
<ul>
<ul>
<li><strong><strong>Configure the JMeter slaves</strong></strong></li>
</ul>
</ul>
<p>The only thing left to do is <strong>starting the JMeter agents</strong> in &#8220;server mode&#8221;. I suggest creating a service in your startup folder (etc/init.d or a windows service) so that the JMeter agent starts up at every server restart.<br />
In order to start JMeter in server mode you have to run the following file, residing in the same &#8220;bin&#8221; folder of the JMeter installation folder on the JMeter agents:<br />
bin/jmeter-server</li>
<li><strong><strong><strong>GENERATING LOAD AND STORING THE RESULTS</strong></strong></strong></li>
</ol>
</ol>
</ol>
<p>The solution to which this series or articles is referring to is using<strong> XML as test results output.</strong> There are two reasons behind choosing XML for output:</p>
<ul>
<ul>
<li><strong>Preparing the test results for data transformation</strong></li>
</ul>
</ul>
<p>XML is preferred because of the <strong>simple xpath extractor</strong>. It will get very handy when we want to group and export additional information like test date, build number, software version, etc.</p>
<ul>
<ul>
<li><strong>Preparing for the Hudson JMeter plugin which expects xml files for reporting</strong></li>
</ul>
</ul>
<p><a title="Hudson JMeter plugin" href="http://wiki.hudson-ci.org/display/HUDSON/Performance+Plugin" target="_blank"><strong>The Hudson plugin</strong> </a>comes very handy when analyzing trends between several runs over different software versions. It expects an xml file which it will parse and build the performance report and trend. The output looks like this:</p>
<div id="attachment_542" class="wp-caption aligncenter" style="width: 610px"><a href="http://qants.files.wordpress.com/2011/05/jmeter-hudson-response-times.jpg"><img class="size-full wp-image-542" title="JMeter Hudson Performance Plugin" src="http://qants.files.wordpress.com/2011/05/jmeter-hudson-response-times.jpg?w=600&#038;h=158" alt="JMeter Hudson Performance Plugin" width="600" height="158" /></a><p class="wp-caption-text">JMeter Hudson Performance Plugin</p></div>
<p style="text-align:center;"> .</p>
<hr />
<p style="text-align:center;">.</p>
<p>We will use one <strong>JMeter Master Controller called &#8220;master&#8221;</strong> and<strong> three slave agents</strong> that we will call <strong>&#8220;agent1&#8243;, &#8220;agent2&#8243;, &#8220;agent3&#8243;</strong>. The <strong>JMeter Master Controller</strong> is the server that we will use as test controller. It is the server <strong>where we store the test plans, test scenarios, function files, test results</strong>. It is the location which <strong>will hold the entire file structure</strong> needed for running a load test. It is the &#8220;Test commander&#8221;, and will only be used for generating load, exporting data, and running additional functions. What it will definitely not fulfill is the function of generating load, where the load will only be generated by the JMeter agents (slaves).<br />
Besides this, the<strong> JMeter agents</strong> only need to be<strong> started in &#8220;server mode&#8221;</strong>. The file structure (repository) of the JMeter Master Contoller does <strong>not need to be manually synchronized</strong> on the agents. When starting a test, the agent will retrieve a temporary copy of the test plan from the JMeter Master Contoller which it will hold onto for the time of running the test</p>
<ol>
<ol>
<ol>
<ul>
<li><strong>Starting a simple test in distributed mode and storing the results locally</strong></li>
</ul>
</ol>
</ol>
</ol>
<p>With JMeter properly set up and configured, we are now ready to <strong>start a simple test in distributed mode</strong>. Let us suppose we now have a testplan called &#8220;<strong>DemoDistributedTest.jmx</strong>&#8220;, stored in the <strong>/tmp/jmeter/testplans</strong> folder. Since we are only interested in<strong> running the test in command line</strong> , this is the command template needed:</p>
<p><code><br />
<span style="color:#008000;"> jmeter -n -t /tmp/jmeter/testplans/DemoDistributedTest.jmx -Jagent1,agent2,agent3 -l /tmp/jmeter/testresults/DemoDistributedTest.xml</span><br />
</code></p>
<p>This will <strong>start the test</strong> in non-gui mode (-n flag)<strong> indicating the location of the testplan</strong> in the Repository (the folder structure from above) (-t flag), <strong>choosing the JMeter agents to run</strong> the test with (-J flag) and <strong>storing the results</strong> into a selected file</p>
<ol>
<ol>
<ol>
<ul>
<li><strong>Adding a jmeter agent to the load configuration</strong></li>
</ul>
</ol>
</ol>
</ol>
<p>As mentioned above, you only need to set up JMeter on an additional agent server, which we will call <strong>agent4</strong>. After adding the new agent to the list of JMeter agents in the Master configuration file, we are ready to repeat the test with 4 JMeter agents:<br />
<code><br />
<span style="color:#008000;"> jmeter -n -t /tmp/jmeter/testplans/DemoDistributedTest.jmx -Jagent1,agent2,agent3,agent4 -l <em>/tmp/jmeter/testresults/DemoDistributedTest.xml</em></span><br />
</code></p>
<ol>
<ol>
<ul>
<li><strong><strong>Preparing for automation and dynamic parameters</strong></strong></li>
</ul>
</ol>
</ol>
<p>We have now run a test on multiple agents, by <strong>defining the testplan</strong>, <strong>the agents and the output file</strong> using the command line. Going on from here, we need to provide all this information in a dynamic way. We need to be able to run the command above by using some sort of <strong>controlling scripts</strong>. I will use some sort of pseudo codes for expressing what i want to achieve.</p>
<p><code><br />
<span style="color:#008000;"> <strong>PSEUDOCODE: </strong>RUN TESTPLAN testplan_name ON AGENTS agent_list STORE THE RESULTS IN result_file</span><br />
</code><br />
This translates into the following command line:<br />
<code><br />
<span style="color:#008000;"> jmeter -n -t ${TESTPLAN} -J${AGENT_LIST} -l ${RESULT_FILE}</span><br />
</code><br />
Additionally, we need to be able to specify not only test configuration parameters, but also application test parameters, like usernames, passwords, number of virtual users, pause times and so on:<br />
<code><br />
<span style="color:#008000;"> <strong>PSEUDOCODE</strong>:RUN TESTPLAN testplan_name ON AGENTS agent_list WITH THE FOLLOWING PARAMS runtime_parameters STORE THE RESULTS IN result_file</span><br />
</code><br />
This translates into:<br />
<code><br />
<span style="color:#008000;"> jmeter -n -t ${TESTPLAN} -J${AGENT_LIST} -l ${RESULT_FILE} - parameters</span><br />
</code></p>
<p>We are now ready to create our first test script. There are three sections that each and every test script will contain:</p>
<ol>
<ol>
<ol>
<ol>
<ol>
<ol>
<ul>
<ul>
<li><strong>header</strong> - this will contain <strong>test configuration information</strong>: location of the testplans, agent list as well as the file containing the functions for controlling the test. This information will be stored in variables in the header.</li>
<li><strong>body</strong> - this is the part where the<strong> functions controlling the run</strong> of the test will reside, together with other <strong>monitoring tasks</strong> that need to be running while the test is running</li>
<li><strong>footer</strong> - this is where we will <strong>end the testplan, and generate the reports. </strong>Since we want the test plans and test results to reside under a logical file structure, we can now build the structure of folders needed. This looks like:</li>
<ul>
<ul>
<li>
<ul>
<li><em>testplans</em></li>
<li><em>scripts</em></li>
<li><em>results</em></li>
<li><em>includes</em>  {contains files with functions and global variables needed by every test}</li>
<li><em>propfiles</em> {contains application test specific variables, will be discussed later}</li>
</ul>
</li>
</ul>
</ul>
</ul>
</ul>
</ol>
</ol>
</ol>
</ol>
</ol>
</ol>
<p>By now our template test script looks like this:<br />
<code><br />
<span style="color:#008000;"># <strong>META</strong></span><br />
<span style="color:#008000;"> # Created: 28 July 2009</span><br />
<span style="color:#008000;"> # Owner: Alexandru Ersenie</span><br />
<span style="color:#008000;"> # Description: Description of what the test does</span><br />
<span style="color:#008000;"> # <strong>HEADER</strong></span><br />
<span style="color:#008000;"> JMETER_TEST_FOLDER="/home/testing/jmeter/"</span><br />
<span style="color:#008000;"> . ${JMETER_TEST_FOLDER}includes/testconfiguration.properties</span><br />
<span style="color:#008000;"> TESTPLAN_SUBFOLDER="homepage/login/"</span><br />
<span style="color:#008000;"> TESTPLAN_FILE_NAME="Tplan_Login.jmx"</span><br />
<span style="color:#008000;"> JMETER_AGENTS="agent1,agent2,agent3"</span><br />
<span style="color:#008000;"> # <strong>BODY</strong></span><br />
<span style="color:#008000;"> jmeter -n -t ${JMETER_TESTPLANS}${TESTPLAN_SUBFOLDER}${TESTPLAN_FILE_NAME} -R ${JMETER_AGENTS} -l ${JMETER_RESULTS}${TESTPLAN_FILE_NAME}.xml</span><br />
</code></p>
<ul>
<li><strong>Function file and global variables</strong></li>
</ul>
<p>Running a test is not enough. We want to be able not only to pass runtime variables to the test, but also <strong>collect </strong>all kind of <strong>application server statistics</strong>, control if the test is going to <strong>store the results in the database</strong> and<strong> generate a report</strong>, if it uses a warm up or not,etc. We need to be able to clear the application server log files before starting the test, and moving them after running the test into a location where we can reactively analyse them, and so on.<br />
In order to achieve this, there is a need for some sort of functions controlling the <strong>set up, runtime, tear down</strong> and <strong>export</strong> phases.</p>
<p>It will then be very easy to create a script template which will call the functions that reside in this file. This is how a test script will look like in the end. The functions are explained below:</p>
<p><code><br />
<span style="color:#008000;"># <strong>META</strong></span><br />
<span style="color:#008000;"> # Created: 28 July 2009</span><br />
<span style="color:#008000;"> # Owner: Alexandru Ersenie</span><br />
<span style="color:#008000;"> # Description: Description of what the test does</span><br />
<span style="color:#008000;"> # <strong>HEADER</strong></span><br />
<span style="color:#008000;"> JMETER_TEST_FOLDER="/home/testing/jmeter/"</span><br />
<span style="color:#008000;"> . ${JMETER_TEST_FOLDER}includes/testconfiguration.properties</span><br />
<span style="color:#008000;"> TESTPLAN_SUBFOLDER="homepage/login/"</span><br />
<span style="color:#008000;"> TESTPLAN_FILE_NAME="Tplan_Login.jmx"</span><br />
<span style="color:#008000;"> JMETER_AGENTS="agent1,agent2,agent3"</span><br />
<span style="color:#008000;"> # <strong>BODY</strong></span><br />
<span style="color:#008000;"> log_test_config</span><br />
<span style="color:#008000;"> get_db_info</span><br />
<span style="color:#008000;"> empty_temp_files</span><br />
<span style="color:#008000;"> configure_appserver</span><br />
<span style="color:#008000;"> run_scenario_warmup</span><br />
<span style="color:#008000;"> trace_jms_usage &amp;</span><br />
<span style="color:#008000;"> trace_class_loading &amp;</span><br />
<span style="color:#008000;"> trace_gf_statistics</span><br />
<span style="color:#008000;"> run_scenario</span><br />
<span style="color:#008000;"> wait_for_user_input</span><br />
<span style="color:#008000;"> #FOOTER</span><br />
<span style="color:#008000;"> collect_logs</span><br />
<span style="color:#008000;"> write_testInfo</span><br />
<span style="color:#008000;"> log_heap_config</span><br />
<span style="color:#008000;"> check_reporting</span><br />
<span style="color:#008000;"> log_test_end</span><br />
<span style="color:#008000;"> exit</span><br />
</code></p>
<p><strong>SET UP PHASE</strong></p>
<p>The set up phase contains functions needed to get the test running. This includes: configuring the application server, removing server log files, removing temporary files, retrieving actual status of the database, etc.<strong><br />
</strong></p>
<ul>
<li><strong><em>function log_test_config</em>:</strong> logs information regarding the test run to the console and into a log file<br />
<span style="color:#008000;"><br />
<code><br />
function log_test_config<br />
{<br />
mkdir -p ${JMETER_RESULTS}<br />
echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Test Configuration: Test will be performed on deployed version: "$APPNAME" - Build Number: "$APP_VERSION" - Revision Number: "$REVISION_NUMBER"" | tee ${JMETER_RESULTS}/run.log<br />
echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Test Configuration: Test will be performed on server: "${HOST}" port "${PORT}" protocol "${PROTOCOL}""<br />
echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Test Configuration: "$VIRTUAL_USERS" virtual users starting in "$RAMP_TIME" seconds " | tee -a ${JMETER_RESULTS}/run.log<br />
echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Test Configuration: "$TRANSACTIONS" transactions will be generated, waiting between "$PAUSE_TIME" and "`expr $PAUSE_TIME + $PAUSE_TIME_DEV`" ms between requests" | tee -a ${JMETER_RESULTS}/run.log<br />
echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Test Configuration: Repeating the scenario "$REPETITIONS" times, increasing the load "$LOOPS" times with "$ADDEDVU" users / repetition" | tee -a ${JMETER_RESULTS}/run.log}<br />
</code><br />
</span></li>
<li><strong><em>function get_db_info</em></strong>: retrieves the number of specific records in the database at the start of the test by running a JMeter test containing a JDBC Select Request. The testplan will store the total number of records into an output file, which will be grepped after. The best part here is that you can add as many requests in the jmeter test plan, and then just extract them one by one from the output file and use them further on in your report.<br />
<span style="color:#008000;"><br />
<code><br />
function get_db_info<br />
{<br />
jmeter -n -t ${JMETER_TESTPLANS}extra/Tplan-DBInfo.jmx -JRESULT_FOLDER=${JMETER_RESULTS}<br />
DBINFO_RECORDSINDB=`grep -E '[0-9]' ${JMETER_RESULTS}/db_info*`<br />
echo "Number of records in Database:" ${DBINFO_RECORDSINDB}<br />
}<br />
</code><br />
</span></li>
<li><strong><em>function empty_log</em></strong>: connects via ssh to the application server and empties the log files. It will clear the application server log file, the garbage collection and java virtual machine log file.<br />
<span style="color:#008000;"><br />
<code><br />
function empty_log<br />
{<br />
echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Removing old Glassfish and JVM logs" | tee -a ${JMETER_RESULTS}/run.log<br />
ssh ${DOMAIN_SERVER} sudo -u glassfish /bin/bash -c "'rm ${GLASSFISH_PATH}/${DOMAIN_NAME}/logs/server.log_*'"<br />
ssh ${DOMAIN_SERVER} sudo -u glassfish /bin/bash -c "'cat /dev/null &gt; ${GLASSFISH_PATH}/${DOMAIN_NAME}/logs/jvm.log'"<br />
ssh ${DOMAIN_SERVER} sudo -u glassfish /bin/bash -c "'cat /dev/null &gt; ${GLASSFISH_PATH}/${DOMAIN_NAME}/logs/jgc.log'"<br />
}<br />
</code><br />
</span></li>
<li><strong><em>function empty_temp_files</em></strong>: clears the temporary files used by the monitoring and exporting functions (jms monitoring, glassfish statistics, etc.)<br />
<span style="color:#008000;"><br />
<code><br />
function empty_temp_files<br />
{<br />
cat /dev/null &gt; /tmp/running<br />
cat /dev/null &gt; /tmp/jms_monitoring<br />
cat /dev/null &gt; /tmp/jmap_objects.log<br />
cat /dev/null &gt; /tmp/glassfish_stats<br />
}<br />
</code><br />
</span></li>
<li><strong><em>function configure_appserver</em></strong>: configures the desired number of threads in JDBC and HTTP Thread pool. This is useful when you want to increase the number of threads in the thread pool by keeping the same load<br />
<span style="color:#008000;"><br />
<code><br />
function  configure_appserver<br />
{<br />
echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Server Configuration: Configuring server minimum and maximum number of threads" | tee -a ${JMETER_RESULTS}/run.log<br />
ssh ${APPSERVER} "sudo -u glassfish /bin/bash -c '/opt/glassfish/bin/asadmin --port '${DOMAIN_ADMIN_PORT}' -u admin --passwordfile /opt/glassfish/passwords set server.thread-pools.thread-pool.http-thread-pool.min-thread-pool-size=${GF_THREADS_MIN}'"<br />
ssh <code>${APPSERVER} </code>"sudo -u glassfish /bin/bash -c '/opt/glassfish/bin/asadmin --port '${DOMAIN_ADMIN_PORT}' -u admin --passwordfile /opt/glassfish/passwords set server.thread-pools.thread-pool.http-thread-pool.max-thread-pool-size=${GF_THREADS_MAX}'"<br />
echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Set up: Starting the test with a threadpool of minimum ${GF_THREADS_MIN} and maximum ${GF_THREADS_MAX} threads" | tee -a ${JMETER_RESULTS}/run.log<br />
#echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - This test runs with ${VIRTUAL_USERS} Virtual Users / Agent, on following agents: ${JMETER_AGENTS}"<br />
}</code></span></li>
</ul>
<p><strong>RUNTIME PHASE</strong></p>
</div>
<div>The runtime phase contains functions that control the run of the test: warming up, monitoring, memory tracing, etc.</div>
<div>
<ul>
<ul>
<li><em><strong>run_scenario_warmup: </strong></em>the function takes a command line input parameter which controls if the test is going to be run with a warm-up first or not. It will start a test with a reduced number of virtual users in order to warm up the application server. The test will output the results into a simple log file (not xml), so that the warm up results will not be taken into consideration when importing the test results generated by the load test.<br />
<code><br />
<span style="color:#008000;">function run_scenario_warmup</span><br />
<span style="color:#008000;"> {</span><br />
<span style="color:#008000;"> if [ "$WARMUP" != "yes" ];</span><br />
<span style="color:#008000;"> then</span><br />
<span style="color:#008000;"> echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Set up: No server warm up. Test will be started without warming up the server" | tee -a ${JMETER_RESULTS}/run.log</span><br />
<span style="color:#008000;"> else</span><br />
<span style="color:#008000;"> echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Set up: Warming up server by running the scenario with "${WARMUP_THREAD_USERS}" users on one agent executing exactly 50 payment transactions" | tee -a ${JMETER_RESULTS}/run.log</span><br />
<span style="color:#008000;"> echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Running: Warming up started" | tee -a ${JMETER_RESULTS}/run.log</span><br />
<span style="color:#008000;"> jmeter -n -t ${JMETER_TESTPLANS}${TESTPLAN_SUBFOLDER}${TESTPLAN_FILE_NAME} -R agent1 -l ${JMETER_RESULTS}${TESTPLAN_FILE_NAME}.log <code>-Ggroup1.hostname=${HOST} -Ggroup1.port=${PORT} -Ggroup1.protocol=${PROTOCOL} -Ggroup1.fullhost=${FULLHOST} -Ggroup2.threads=${threads_start} -Ggroup2.ramptime=${rampup_start} -Ggroup2.users=${THREAD_USERS} -Ggroup2.startid=${START_ID} -Ggroup2.synctimer=${SYNC_TIMER} -Ggroup3.pay_transactions=50-Ggroup4.pausetimeconst=${PAUSE_TIME} -Ggroup4.pausetimerandom=${PAUSE_TIME_DEV} -G ${JMETER_PROPFILES}${TESTPLAN_SUBFOLDER}${TESTPLAN_FILE_NAME}.properties &amp;</code></span><br />
<span style="color:#008000;"> wait_for_plan '${TESTPLAN_FILE_NAME}'</span><br />
<span style="color:#008000;"> echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Tear down: Warming up ended, sleeping for 10 seconds" | tee -a ${JMETER_RESULTS}/run.log</span><br />
<span style="color:#008000;"> sleep 10</span><br />
<span style="color:#008000;"> fi</span><br />
<span style="color:#008000;"> }</span><br />
</code></li>
<li><em><strong>trace_class_loading: </strong></em>this function will <strong>trace memory usage statistics</strong> every 10 seconds, using <strong>jmap</strong><em><strong>. </strong></em>It will connect to the application server and retrieve a map of objects periodically, which will be stored into an export file, that will be processed in the end. The type of objects can be extended by simply adding a regular expression. Currently it retrieves <strong>hashmaps,vectors, eclipse persistence objects, javascript objects</strong> etc. The function uses a temporary file called &#8220;<strong>running</strong>&#8221; which resides in the &#8220;/tmp&#8221; folder. While the file exists, the collection of statistics keeps going, and stops once the test stops. (when the test stops, the temporary file is removed, so that in the next check, the statistics function will not find the file and will exit). In the end, the file is processed and exported into a final jmap_objects file, which will be used for exporting memory information in the performance database<br />
<span style="color:#008000;"><code>function trace_class_loading<br />
{<br />
echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Tracing: Starting to collect Heap Usage statistics with a refresh of 10 seconds" | tee -a ${JMETER_RESULTS}/run.log<br />
glassfish_pid=`ssh ${DOMAIN_SERVER} sudo -u glassfish /bin/bash -c '/usr/java/jdk1.6.0_24/bin/jps -q | grep ASMain ' | awk '{print$1}'`<br />
echo "glassfih pid is " $glassfish_pid<br />
status=`ls /tmp | grep running`<br />
</code><code># As long as the script is running perform Jmap histogram on the server every x seconds, where x is defined in sleep command<br />
</code><br />
<code><br />
while [ "$status" != "" ];<br />
do<br />
JMAP_TIMESTAMP=`date +%H-%M-%S`<br />
ssh ${DOMAIN_SERVER} "sudo -u glassfish /bin/bash -c '${JAVA_BIN}jmap -histo ${glassfish_pid}'" | egrep -i -e '\[[I,B,C]+' -e 'myobjects' -e 'java.util.Tree' -e 'java.util.Hash' -e 'java.util.Vector' -e 'Klass' -e 'org.mozilla' -e 'com.sun.tools.javac.zip.ZipFileIndexEntry' -e 'java.lang' -e 'java.util.concurrent' -e 'org.eclipse.persistence' | sed -e '/[0-9]/s/$/',"${JMAP_TIMESTAMP}"'/' &gt;&gt; /tmp/jmap_objects.log<br />
sleep 10<br />
status=`ls /tmp | grep running`<br />
done<br />
</code></span><br />
<span style="color:#008000;"> <code>echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Tracing: Collection of Heap Usage Statistics ended" | tee -a ${JMETER_RESULTS}/run.log<br />
</code></span><br />
<span style="color:#008000;"> <code># After the script has ended perform a full garbage collector. Comment this line if you do not want a FULL GC<br />
</code><br />
<code>ssh ${DOMAIN_SERVER} "sudo -u glassfish /bin/bash -c '${JAVA_BIN}jmap -histo:live ${glassfish_pid}'" | egrep -i -e '\[[I,B,C]+' -e 'myobjects' -e 'java.util.Tree' -e 'java.util.Hash' -e 'java.util.Vector' -e 'Klass' &gt;&gt; /tmp/jmap_objects.log<br />
</code><br />
<code># Move the jmap log in the results folder for further processing<br />
</code><br />
<code>mv /tmp/jmap_objects.log ${JMETER_RESULTS}/jmap_objects.log<br />
</code><br />
<code>#Process jmap log for removing spaces - old and very slow<br />
</code><br />
<code>awk '{printf("%s,%s,%s,%s,%s\n",$1,$2,$3,$4,$5);}' ${JMETER_RESULTS}/jmap_objects.log | awk '{gsub(/:/,"");print}' &gt; ${JMETER_RESULTS}/processed_jmap_objects.log<br />
cp ${JMETER_RESULTS}/processed_jmap_objects.log ${JMETER_TRANSFORMATION}processed_jmap_objects.log}<br />
</code><br />
</span></li>
<li><em><strong>trace_app_statistics: </strong></em>this function uses <strong>glassfish&#8217;s rest monitoring interface</strong> and<strong> curl commands</strong> for retrieving information such as jdbc connections, http thread usage, number of specific beans in cache, etc. This function is very flexible, as all data is written in the database in the form of: test_id, timestamp, label, value. Thank to this, any new monitoring item is just a new label in the database, and can be retrieved in a separate report by building a simple query. I will post here a sample of this function, which collects information regarding JDBC Connection usage. It can be easily extended by simply adding a new monitoring item, for example <strong>HTTP_THREAD_POOL_THREAD_COUNT</strong><br />
<code><br />
<span style="color:#008000;">function trace_app_statistics</span><br />
<span style="color:#008000;"> {</span><br />
<span style="color:#008000;"> status=`ls /tmp | grep glassfish_stats`</span><br />
<span style="color:#008000;"> while [ "$status" != "" ];</span><br />
<span style="color:#008000;"> do</span><br />
<span style="color:#008000;"> MONITOR_TIMESTAMP=`date +%H-%M-%S`</span><br />
<span style="color:#008000;"> #JDBC Monitoring</span><br />
<span style="color:#008000;"> JDBC_CONN_USED=`curl -s -u user:password http://glassfish:4848/monitoring/domain/server/resources/EocPool | grep numconnused | grep -o -E '"current":[0-9]*' | sed 's/["]*[a-z]*["][:]*//'`</span><br />
</code><br />
<span style="color:#008000;"> <code>echo $MONITOR_TIMESTAMP":JDBC - Connections used:"$JDBC_CONN_USED &gt;&gt; ${JMETER_RESULTS}/glassfish_stats.log</code></span><br />
<code><br />
<span style="color:#008000;"> sleep $CMD_PARAM_INTERVAL</span><br />
<span style="color:#008000;"> status=`ls /tmp | grep glassfish_stats`</span><br />
<span style="color:#008000;"> done</span><br />
<span style="color:#008000;"> cp ${JMETER_RESULTS}/glassfish_stats.log ${JMETER_TRANSFORMATION}glassfish_stats.log</span><br />
<span style="color:#008000;"> }</span><br />
</code></li>
</ul>
</ul>
<ul>
<ul>
<li><em><strong>run_scenario: </strong></em>this is the main function controlling the run of the test. It takes several parameters as input, such as number of repetitions, number of virtual users, number of loops inside a repetition, number of virtual users to be increased in a loop, ramp up time, timers, etc. It sets the basis for running the test scenario in the following form:<br />
<code><br />
<span style="color:#008000;">./PAYMENT_SCENARIO 'users=150 ramptime=150 pausetime=2000 pausetimedev=200 pay_transactions=500 repeats=1 loopsinrepeat=1 waitforuserinput=no minthreads=150 maxthreads=200 generatereport=no warmup=no startid=100' 'hostname=myappserver port=8080 protocol=http'</span><br />
</code><br />
It will repeat the test for the desired number of times, increasing the number of users progressively by the defined number and so on.<br />
<code><br />
<span style="color:#008000;">function run_scenario</span><br />
<span style="color:#008000;"> {</span><br />
<span style="color:#008000;"> scenario_counter=$REPETITIONS</span><br />
<span style="color:#008000;"> cool_down=0</span><br />
<span style="color:#008000;"> while [ "$scenario_counter" != "0" ];</span><br />
<span style="color:#008000;"> do</span><br />
<span style="color:#008000;"> # Repeat test for a defined number of times (counter)</span><br />
<span style="color:#008000;"> counter_start=$LOOPS</span><br />
<span style="color:#008000;"> counter_end=$LOOPS</span><br />
<span style="color:#008000;"> echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Set up: Starting the load test" | tee -a ${JMETER_RESULTS}/run.log</span><br />
<span style="color:#008000;"> echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Set up: Starting iteration number " `expr $REPETITIONS - $scenario_counter + 1` "out of " $REPETITIONS "iterations" | tee -a ${JMETER_RESULTS}/run.log</span><br />
<span style="color:#008000;"> threads_start=${VIRTUAL_USERS}</span><br />
<span style="color:#008000;"> rampup_start=${RAMP_TIME}</span><br />
<span style="color:#008000;"> while [ "$counter_start" != "0" ];</span><br />
<span style="color:#008000;"> do</span><br />
<span style="color:#008000;"> echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Running: Running with a number of " ${threads_start} " virtual users / agent" | tee -a ${JMETER_RESULTS}/run.log</span><br />
<span style="color:#008000;"> counter_start=`expr $counter_start - 1`</span><br />
<span style="color:#008000;"> jmeter -n -t ${JMETER_TESTPLANS}${TESTPLAN_SUBFOLDER}${TESTPLAN_FILE_NAME} -R ${JMETER_AGENTS} -l ${JMETER_RESULTS}/${TESTPLAN_FILE_NAME}.xml -Ggroup1.hostname=${HOST} -Ggroup1.port=${PORT} -Ggroup1.protocol=${PROTOCOL} -Ggroup1.fullhost=${FULLHOST} -Ggroup2.threads=${threads_start} -Ggroup2.ramptime=${rampup_start} -Ggroup2.users=${THREAD_USERS} -Ggroup2.startid=${START_ID} -Ggroup2.synctimer=${SYNC_TIMER} -Ggroup3.pay_transactions=${TRANSACTIONS} -Ggroup4.pausetimeconst=${PAUSE_TIME} -Ggroup4.pausetimerandom=${PAUSE_TIME_DEV} -G ${JMETER_PROPFILES}${TESTPLAN_SUBFOLDER}${TESTPLAN_FILE_NAME}.properties &amp;</span><br />
<span style="color:#008000;"> wait_for_plan '${TESTPLAN_FILE_NAME}'</span><br />
<span style="color:#008000;"> threads_start=`expr $threads_start + $ADDEDVU`</span><br />
<span style="color:#008000;"> if [ "$counter_start" != "0" ];</span><br />
<span style="color:#008000;"> then echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Running: Increasing number of virtual users by " ${ADDEDVU} "users / agent" | tee -a ${JMETER_RESULTS}/run.log</span><br />
<span style="color:#008000;"> fi</span><br />
<span style="color:#008000;"> done</span><br />
<span style="color:#008000;"> # Cool Down</span><br />
<span style="color:#008000;"> scenario_counter=`expr $scenario_counter - 1`</span><br />
<span style="color:#008000;"> echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Teardown: Load test ended, sleeping for 30 seconds" | tee -a ${JMETER_RESULTS}/run.log</span><br />
<span style="color:#008000;"> sleep 10</span><br />
<span style="color:#008000;"> done</span><br />
<span style="color:#008000;"> }</span><br />
</code></li>
</ul>
</ul>
<ul>
<ul>
<li><em><strong>wait_for_user_input: </strong></em>this function waits for the users input in order to stop the test scenario, and to start importing the results. It is useful when you want to keep collecting memory statistics until the test is ended, and you want for example to do a full garbage collection, so that, before importing, you have a list of all objects that are left after the test run, and after a major collection. These will be good candidates for memory leaks. The function takes a command line parameter as input. Once the wait is over, all temporary files are erased, and all functions that run by checking the existence of such temporary files will exit, allowing the main scenario to end, and start the processing of test results and importing into the performance database<br />
<code><br />
<span style="color:#008000;">function wait_for_user_input</span><br />
<span style="color:#008000;"> {</span><br />
<span style="color:#008000;"> if [ "$USERINPUT" != "no" ];</span><br />
<span style="color:#008000;"> then</span><br />
<span style="color:#008000;"> while : ; do</span><br />
<span style="color:#008000;"> read -t 2 &amp;&amp; break</span><br />
<span style="color:#008000;"> done</span><br />
<span style="color:#008000;"> echo exited while loop</span><br />
<span style="color:#008000;"> rm -r /tmp/running</span><br />
<span style="color:#008000;"> rm -r /tmp/jms_monitoring</span><br />
<span style="color:#008000;"> rm -r /tmp/glassfish_stats</span><br />
<span style="color:#008000;"> else</span><br />
<span style="color:#008000;"> rm -r /tmp/running</span><br />
<span style="color:#008000;"> rm -r /tmp/jms_monitoring</span><br />
<span style="color:#008000;"> rm -r /tmp/glassfish_stats</span><br />
<span style="color:#008000;"> fi</span><br />
<span style="color:#008000;"> echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Analysis Services: Sleeping for 30 seconds to allow jms and performance monitor to stop gracefully" | tee -a ${JMETER_RESULTS}/run.log</span><br />
<span style="color:#008000;"> sleep 30</span><br />
<span style="color:#008000;"> }</span></code></li>
</ul>
</ul>
<p><strong>TEAR DOWN</strong></p>
<div>The tear down phase contains functions that control the analysis part of the test: collecting logs, writing test information in a test configuration file, logging heap configuration information, logging the end of the test.</div>
</div>
<div>
<ul>
<ul>
<li><em><strong>collect_logs</strong></em><br />
<code><br />
<span style="color:#008000;">function collect_logs</span><br />
<span style="color:#008000;"> {</span><br />
<span style="color:#008000;"> echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Analysis Services: Collecting and compressing application server logs (jvm,jgc,jms,server)" | tee -a ${JMETER_RESULTS}/run.log</span><br />
<span style="color:#008000;"> cd ${JMETER_RESULTS}</span><br />
<span style="color:#008000;"> # Collect Glassfish logs on Server</span><br />
<span style="color:#008000;"> scp ${DOMAIN_SERVER}:${GLASSFISH_PATH}/${DOMAIN_NAME}/logs/server.log* ${JMETER_RESULTS} || on_error "${LOG_TIMESTAMP}: ERROR - Could not perform Glassfish log collecting via SCP on server ${DOMAIN_SERVER} "</span><br />
<span style="color:#008000;"> zip -j ${JMETER_RESULTS}/${testrun_id}-server.zip ${JMETER_RESULTS}/server.log*</span><br />
<span style="color:#008000;"> rm server.log*</span><br />
<span style="color:#008000;"> # Collect JVM logs on server</span><br />
<span style="color:#008000;"> scp ${DOMAIN_SERVER}:${GLASSFISH_PATH}/${DOMAIN_NAME}/logs/jvm.log* ${JMETER_RESULTS}/${testrun_id}-jvm-original.log || on_error "${LOG_TIMESTAMP}: ERROR - Could not perform JVM log collecting via SCP on server ${DOMAIN_SERVER} "</span><br />
<span style="color:#008000;"> sed 's/\x0//g' ${JMETER_RESULTS}/${testrun_id}-jvm-original.log &gt; ${JMETER_RESULTS}/${testrun_id}-jvm.log</span><br />
<span style="color:#008000;"> rm ${JMETER_RESULTS}/${testrun_id}-jvm-original.log</span><br />
<span style="color:#008000;"> zip -j ${JMETER_RESULTS}/${testrun_id}-server.zip ${JMETER_RESULTS}/${testrun_id}-jvm.log*</span><br />
<span style="color:#008000;"> # Collect Java Garbage collection output on server</span><br />
<span style="color:#008000;"> scp ${DOMAIN_SERVER}:${GLASSFISH_PATH}/${DOMAIN_NAME}/logs/jgc.log* ${JMETER_RESULTS}/${testrun_id}-jgc-original.log || on_error "${LOG_TIMESTAMP}: ERROR - Could not perform JGC log collecting via SCP on server ${DOMAIN_SERVER} "</span><br />
<span style="color:#008000;"> sed 's/\x0//g' ${JMETER_RESULTS}/${testrun_id}-jgc-original.log &gt; ${JMETER_RESULTS}/${testrun_id}-jgc.log</span><br />
<span style="color:#008000;"> rm ${JMETER_RESULTS}/${testrun_id}-jgc-original.log</span><br />
<span style="color:#008000;"> zip -j ${JMETER_RESULTS}/${testrun_id}-server.zip ${JMETER_RESULTS}/${testrun_id}-jgc.log*</span><br />
<span style="color:#008000;"> # Collect Java Garbage collection output on server</span><br />
<span style="color:#008000;"> scp ${DOMAIN_SERVER}:${GLASSFISH_PATH}/${DOMAIN_NAME}/logs/jms.log* ${JMETER_RESULTS}/${testrun_id}-jms-original.log || on_error "${LOG_TIMESTAMP}: ERROR - Could not perform JGC log collecting via SCP on server ${DOMAIN_SERVER} "</span><br />
<span style="color:#008000;"> sed 's/\x0//g' ${JMETER_RESULTS}/${testrun_id}-jms-original.log &gt; ${JMETER_RESULTS}/${testrun_id}-jms.log</span><br />
<span style="color:#008000;"> rm ${JMETER_RESULTS}/${testrun_id}-jms-original.log</span><br />
<span style="color:#008000;"> # Calculate peak number of jms messages while test was running</span><br />
<span style="color:#008000;"> TOTAL_JMS_MSG=`sort -r -t ' ' +1 -n ${JMETER_RESULTS}/${testrun_id}-jms.log | awk '{print $1}' | sed q`</span><br />
<span style="color:#008000;"> TOTAL_JMS_BYTES=`sort -r -t ' ' +3 -n ${JMETER_RESULTS}/${testrun_id}-jms.log | awk '{print $3}' | sed q`</span><br />
<span style="color:#008000;"> PEAK_JMS_MSG=`sort -r -t ' ' +6 -n ${JMETER_RESULTS}/${testrun_id}-jms.log | awk '{print $6}' | sed q`</span><br />
<span style="color:#008000;"> PEAK_JMS_TOTAL_BYTES=`sort -r -t ' ' +9 -n ${JMETER_RESULTS}/${testrun_id}-jms.log | awk '{print $9}' | sed q`</span><br />
<span style="color:#008000;"> zip -j ${JMETER_RESULTS}/${testrun_id}-server.zip ${JMETER_RESULTS}/${testrun_id}-jms.log*</span></code><br />
<span style="color:#008000;"> return</span><br />
<span style="color:#008000;"> }</span></li>
</ul>
</ul>
<ul>
<ul>
<li><em><strong>write_test_info:</strong></em> this function writes the necessary test configuration information in an xml file<em><strong>. </strong></em>It generates an increasing unique id for the testrun_id, and writes the testinformation from multiple sources that were provided as command line parameters, or as results of other functions called in the set up or run time phase. It will write all information needed to identify the load configuration and the server configuration at the time of test run: number of users, ramp up, number of processing threads, garbage collection strategy, jvm heap configuration, jdbc pool configuration, etc.<em><strong><br />
</strong></em><br />
<code><br />
<span style="color:#008000;">function write_testInfo</span><br />
<span style="color:#008000;"> {</span><br />
<span style="color:#008000;"> echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Analysis Services: Writing Test Summary for importing in Test Results" | tee -a ${JMETER_RESULTS}/run.log</span></code><br />
<span style="color:#008000;"> # Get unique ID for the script,in order to store in DB. ID is formed of the last digits of IP address and an id that is incremented</span><br />
<span style="color:#008000;"> # Get last digits of IP address</span><br />
<span style="color:#008000;"> typeset -i test_id</span><br />
<span style="color:#008000;"> local_ip=`/sbin/ifconfig | grep &#8216;inet addr:&#8217;| grep -v &#8217;127.0.0.1&#8242; | grep -v &#8217;192.168&#8242; | cut -d: -f2 | cut -d. -f4 | awk &#8216;{ print $1}&#8217;`</span><br />
<span style="color:#008000;"> test_id=$(cat ${ID_FILE})</span><br />
<span style="color:#008000;"> new_id=`expr $test_id + 1`</span><br />
<span style="color:#008000;"> echo $new_id &gt;${ID_FILE}</span><br />
<span style="color:#008000;"> testrun_id=$local_ip$new_id</span><br />
<span style="color:#008000;"> # Getting testdescription and server configuration</span><br />
<span style="color:#008000;"> echo $threadnum</span><br />
<span style="color:#008000;"> echo $threadwarm</span><br />
<span style="color:#008000;"> # Copying the glassfish server logs to a path configured to be the logging path for the reporting server</span><br />
<span style="color:#008000;"> cp ${JMETER_RESULTS}/${testrun_id}-server.zip ${JMETER_SERVER_LOGS}${testrun_id}_server.zip</span><br />
<span style="color:#008000;"> # Writing xml test information</span><br />
<span style="color:#008000;"> CODE_500=`grep -c &#8216;rc=&#8221;5&#8242; ${JMETER_RESULTS}/*.xml`</span><br />
<span style="color:#008000;"> CODE_400=`grep -c &#8216;rc=&#8221;4&#8242; ${JMETER_RESULTS}/*.xml`</span><br />
<span style="color:#008000;"> CODE_200=`grep -c &#8216;rc=&#8221;2&#8242; ${JMETER_RESULTS}/*.xml`</span><br />
<span style="color:#008000;"><br />
<code><br />
</code></span><span style="color:#008000;"><code>echo '&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;testInfo build="'$REVISION_NUMBER'" test_id="'$testrun_id'" portal_version="'$PORTAL_VERSION'" revision_number="'$REVISION_NUMBER'" scenario_id="'${SCRIPT_NAME}'" architecture_id="'$ARCHITECTURE_ID'" test_date="'$LOG_RUNDATE $LOG_TIMESTAMP'" db_recordsindb="'$DBINFO_RECORDSINDB'"&gt;&lt;test-configuration threads="'$VIRTUAL_USERS'" rampup="'$RAMP_TIME'" payment_transactions="'$TRANSACTIONS'" waittime="'$PAUSE_TIME'" waitdeviation="'$PAUSE_TIME_DEV'"&gt;&lt;/test-configuration&gt;&lt;glassfish-configuration server_threads_min="'$GF_THREADS_MIN'" server_threads_max="'$GF_THREADS_MAX'" jdbc_thread_pool_min="'$JDBC_THREAD_POOL_MIN'" jdbc_thread_pool_max="'$JDBC_THREAD_POOL_MAX'" jdbc_statement_cache="'$JDBC_STATEMENT_CACHE'"&gt;&lt;/glassfish-configuration&gt;&lt;jvm-options gc_strategy_param1="'$GC_STRATEGY_PARAM1'" total_initial_heap="'$TOTAL_INITIAL_HEAP'" total_maximum_heap="'$TOTAL_MAXIMUM_HEAP'" newgen_initial_heap="'$NEWGEN_INITIAL_HEAP'" newgen_maximum_heap="'$NEWGEN_MAXIMUM_HEAP'" survivor_ratio="'$SURVIVOR_RATIO'" log_level="'$LOG_LEVEL'"&gt;&lt;/jvm-options&gt;&lt;jms-usage&gt;total_jms_msg="'$TOTAL_JMS_MSG'" total_jms_bytes="'$TOTAL_JMS_BYTES'" peak_jms_msg="'$PEAK_JMS_MSG'" peak_jms_total_bytes="'$PEAK_JMS_TOTAL_BYTES'"&lt;/jms-usage&gt;&lt;statusCodes&gt;code_500="'$CODE_500'" code_400="'$CODE_400'" code_200="'$CODE_200'" &lt;/statusCodes&gt;&lt;/testInfo&gt;' &gt; ${JMETER_RESULTS}/testInfo.xml</code><code><br />
</code><code> return</code></span><span style="color:#008000;"><code><br />
}</code></span></li>
</ul>
</ul>
<ul>
<ul>
<li><em><strong>log_heap_config: </strong></em>this function analysis the jvm configuration on the server by using &#8220;jmap&#8221; with &#8220;-heap&#8221; parameter<em><strong><br />
</strong></em><br />
<code><br />
<span style="color:#008000;">function log_heap_config</span><br />
<span style="color:#008000;"> {</span><br />
<span style="color:#008000;"> echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Analysis Services: Collecting Glassfish heap configuration" | tee -a ${JMETER_RESULTS}/run.log</span><br />
<span style="color:#008000;"> glassfish_pid=`ssh ${DOMAIN_SERVER} sudo -u glassfish /bin/bash -c '${JAVA_BIN}jps -q | grep ASMain ' | awk '{print$1}'`</span><br />
<span style="color:#008000;"> ssh ${DOMAIN_SERVER} "sudo -u glassfish /bin/bash -c '${JAVA_BIN}jmap -heap ${glassfish_pid}'" &gt; ${JMETER_RESULTS}/${testrun_id}-heapconfig.txt</span><br />
<span style="color:#008000;"> }</span><br />
</code></li>
</ul>
</ul>
<ul>
<ul>
<li><em><strong>check_reporting:</strong></em> this function checks if the import of testresults is wished after the test run. This is controlled by a command line parameter called &#8220;<strong>REPORTING</strong>&#8220;. If no reporting is wished, then just a small processing is performed, for hudson analysis. Otherwise, the &#8220;data_transformation&#8221; function will be called, which will start the exporting of data in the database.<br />
<code><br />
<span style="color:#008000;">function check_reporting</span><br />
<span style="color:#008000;"> {</span><br />
<span style="color:#008000;"> if [ "$REPORTING" == "yes" ];</span><br />
<span style="color:#008000;"> then</span><br />
<span style="color:#008000;"> echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Analysis Services: Sleeping for 30 seconds before starting data transformation services" | tee -a ${JMETER_RESULTS}/run.log</span><br />
<span style="color:#008000;"> data_transformation</span><br />
<span style="color:#008000;"> else</span><br />
<span style="color:#008000;"> hudson_transformation</span><br />
<span style="color:#008000;"> fi</span><br />
<span style="color:#008000;"> }</span><br />
</code></li>
</ul>
</ul>
<ul>
<ul>
<li><em><strong>log_test_end: </strong></em>this function signalises the end of the test by outputing a log message to the console and in the test run log file.<em><strong><br />
</strong></em><br />
<code><br />
<span style="color:#008000;">function log_test_end</span><br />
<span style="color:#008000;"> {</span><br />
<span style="color:#008000;"> echo "${PLACEHOLDER}`date +%H-%M-%S`: LOGGING - Test Finish: Test Scenario Ended" | tee -a ${JMETER_RESULTS}/run.log</span><br />
<span style="color:#008000;"> }</span></code></li>
</ul>
</ul>
</div>
<div style="text-align:center;">.</div>
<div style="text-align:center;">
<hr />
<p>.</p>
<p style="text-align:left;">In the second article i discussed how to build an integrated <strong>load solution with JMeter.</strong> I covered topics such as: <strong>dynamic test plans, test scripts, test repository, shell functions, monitoring functions, logging functions</strong>, etc. I talked about the <strong>structure of a test script template</strong>, and detailed the <strong>shell functions</strong> called in it. It is now time to dive into the third part, one of the most interesting maybe in this series of articles: <strong></strong></p>
<p style="text-align:left;"><strong>ETL &#8211; EXTRACT TRANSFORM AND LOAD &#8211; DATA PROCESSING AND IMPORTING INTO THE DATABASE</strong></p>
</div>
<div>This is it for now. Please let me know if you have any questions to be cleared up to this point, and if you find this article useful.</div>
<div>Alex</div>
<div style="text-align:center;">.</div>
<hr />
<div style="text-align:center;"><strong>End of part 2 &#8211; Load &amp; Performance – Testing and reporting using open source tools – Part 2 – Configuring Load Generators &#8211; Generating load with JMeter, storing, filtering and preparing results for importing </strong></div>
<hr />
<p style="text-align:center;">.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/qants.wordpress.com/462/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/qants.wordpress.com/462/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/qants.wordpress.com/462/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/qants.wordpress.com/462/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/qants.wordpress.com/462/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/qants.wordpress.com/462/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/qants.wordpress.com/462/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/qants.wordpress.com/462/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/qants.wordpress.com/462/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/qants.wordpress.com/462/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/qants.wordpress.com/462/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/qants.wordpress.com/462/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/qants.wordpress.com/462/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/qants.wordpress.com/462/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=alexandru-ersenie.com&amp;blog=9058370&amp;post=462&amp;subd=qants&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://alexandru-ersenie.com/2011/05/27/java-ee-load-and-performance-testing-and-reporting-using-open-source-tools-part-2-configuring-load-generators-generating-load-with-jmeter-storing-filtering-importing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/19315d494e10cf62a36e142aaf2177cf?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">skipper</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/05/jmeter-distributed-structure.png" medium="image">
			<media:title type="html">JMeter Distributed Testing Structure</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/05/jmeter-hudson-response-times.jpg" medium="image">
			<media:title type="html">JMeter Hudson Performance Plugin</media:title>
		</media:content>
	</item>
		<item>
		<title>Java EE &#8211; Load &amp; Performance &#8211; Testing and reporting using open source tools &#8211; Part 1 &#8211; Concept, examples and sample reports</title>
		<link>http://alexandru-ersenie.com/2011/05/12/java-ee-load-performance-testing-and-reporting-using-open-source-tools-part-1-concept-examples-and-sample-reports/</link>
		<comments>http://alexandru-ersenie.com/2011/05/12/java-ee-load-performance-testing-and-reporting-using-open-source-tools-part-1-concept-examples-and-sample-reports/#comments</comments>
		<pubDate>Thu, 12 May 2011 16:59:49 +0000</pubDate>
		<dc:creator>Alexandru Ersenie</dc:creator>
				<category><![CDATA[ireport]]></category>
		<category><![CDATA[jasper reports]]></category>
		<category><![CDATA[jasper server]]></category>
		<category><![CDATA[jmap]]></category>
		<category><![CDATA[JMeter]]></category>
		<category><![CDATA[JMeter Jasper Performance Reports]]></category>
		<category><![CDATA[Load and Performance Test Aspects]]></category>
		<category><![CDATA[MySql]]></category>
		<category><![CDATA[Pentaho Data Integration]]></category>
		<category><![CDATA[application server resource usage report]]></category>
		<category><![CDATA[automated load testing]]></category>
		<category><![CDATA[continuous integration system]]></category>
		<category><![CDATA[drill down reporting]]></category>
		<category><![CDATA[hudson]]></category>
		<category><![CDATA[jasper report]]></category>
		<category><![CDATA[load and performance report]]></category>
		<category><![CDATA[memory usage report]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[open source load testing]]></category>
		<category><![CDATA[open source reporting tools]]></category>

		<guid isPermaLink="false">http://qants.wordpress.com/?p=443</guid>
		<description><![CDATA[The purpose of this article is to present an alternative to commercial tools used for load testing and reporting. It is the reflection of the solution i have built by using open source tools such as: JMeter MySQL Pentaho Data Integration Jasper Reports &#8211; Jasper Server &#8211; IReport Shell Scripting Java native tools I will [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=alexandru-ersenie.com&amp;blog=9058370&amp;post=443&amp;subd=qants&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>The purpose of this article is to present an alternative to commercial tools used for load testing and reporting. It is the reflection of the solution i have built by using open source tools such as:</p>
<ul>
<li><strong>JMeter</strong></li>
<li><strong>MySQL</strong></li>
<li><strong>Pentaho Data Integration</strong></li>
<li><strong>Jasper Reports &#8211; Jasper Server &#8211; IReport</strong></li>
<li><strong>Shell Scripting</strong></li>
<li><strong>Java native tools</strong></li>
</ul>
<p>I will cover all topics from <strong>generating the load</strong>, <strong>storing the test results</strong> into a readable format,<strong> transforming and importing them into the database</strong>, generating the <strong>load and performance reports</strong> and <strong>integrating</strong> the load and performance tests into <strong>continuous integration systems</strong>.</p>
<p>In order to make it easier to read and understand, i will start this article by looking at the final output, the reports. Let&#8217;s have a look at the possible load and performance reports we might need.</p>
<p>I will split and describe the parts of the report before mixing them together again, and presenting the final report. Although i have tried to make the charts as readable as possible, most of the charts are too large to be reduced to a printable size, so that the charts presented here are a &#8220;zoomed out&#8221; version of the ones the solution uses.</p>
<p>The good part is that you can always build the same report with different sizes, a smalle one for BI and a larger one for debug purposes (where timestamps and chart information is clearly visible)</p>
<h2>Load and performance reports with Jasper Reports</h2>
<p>There are several types of information that we need to have in the report, so i will group them as follows (also grouped in the graphical representation)<br />
<strong>Test relevant information:</strong></p>
<p><strong><a href="http://qants.files.wordpress.com/2011/05/template1-test-information1.png"><img class="aligncenter size-full wp-image-418" title="Load &amp; Performance Report - Test Information" src="http://qants.files.wordpress.com/2011/05/template1-test-information1.png?w=600" alt="Load &amp; Performance Report - Test Information"   /></a><br />
</strong></p>
<ul>
<li>the major version of the software under test and the hudson build number of the software under test</li>
<li>the unique test run id and the date and time when the test was run</li>
<li>the name of the test scenario &#8211; what component is this test focusing on</li>
</ul>
<p><strong>Load configuration:</strong></p>
<ul>
<li>number of virtual users involved in the test scenario</li>
<li>ramp up time for the virtual users</li>
<li>generic waiting times between transactions called by the virtual users (constant and uniform delay)</li>
</ul>
<div>
<p><strong>Database specfic information:</strong></p>
<ul>
<li>number of records in the database before starting the test and after running the test (records of interest to the test)</li>
</ul>
</div>
<p><strong>Application server configuration:</strong></p>
<p><strong><a href="http://qants.files.wordpress.com/2011/05/template1-server-configuration.png"><img class="aligncenter size-full wp-image-419" title="Load &amp; Performance Report - Server configuration information" src="http://qants.files.wordpress.com/2011/05/template1-server-configuration.png?w=600&#038;h=148" alt="Load &amp; Performance Report - Server configuration information" width="600" height="148" /></a><br />
</strong></p>
<ul>
<li>garbage collection strategy</li>
<li>memory settings (initial, maximal, young, old, survivor ratio)</li>
<li>number of http threads that the application server is configured to use (minimum and maximum)</li>
<li>number of jdbc connections that the application server is configured to use (minimum and maximum)</li>
<li>other information as JDBC statement cache</li>
<li>detailed description of the server configuration (if needed)</li>
</ul>
<p><strong><br />
</strong></p>
<p><strong>Response times distribution for each of the requests involved in the test scenario:</strong></p>
<p><strong><a href="http://qants.files.wordpress.com/2011/05/template1-response-times.png"><img class="aligncenter size-full wp-image-420" title="Load &amp; Performance Report - Response times per transaction" src="http://qants.files.wordpress.com/2011/05/template1-response-times.png?w=600&#038;h=126" alt="Load &amp; Performance Report - Response times per transaction" width="600" height="126" /></a><br />
</strong></p>
<ul>
<li>name of transaction</li>
<li>total number of succesful transactions</li>
<li>minimum response time</li>
<li>maximum response time</li>
<li>average response time</li>
<li>standard deviation</li>
<li>50 to 90 percent line</li>
<li>average number of transactions / second</li>
</ul>
<p><strong>Dual axis graphical representation (transactions, response times):</strong></p>
<p><strong><a href="http://qants.files.wordpress.com/2011/05/template-1-chart.jpg"><img class="aligncenter size-full wp-image-421" title="Load &amp; Performance Report - Transactions vs Response Times" src="http://qants.files.wordpress.com/2011/05/template-1-chart.jpg?w=600&#038;h=188" alt="Load &amp; Performance Report - Transactions vs Response Times" width="600" height="188" /></a><br />
</strong></p>
<ul>
<li>the number of transactions over time ( represented in total number of transactions per second ) (left y axis)</li>
<li>the response times for the transactions ( each response time is represented as an average of all response times of all requests taking place in one second. There will be a line for each of the requests involved in the test scenario (if there are for example 5 different requests from different users in the same time, there will be 5 different lines represented in the chart) (right axis y)</li>
<li>the absolute maximum response time, measured per second, from all requests (if there are 5 requests in one second, the first one with 2 seconds response time, and the last one with 1 second response time, the response time for the first request will be represented. This is useful to detect spikes in response times) (most right axis y)</li>
<li>the requests involved in the test scenario (each transaction has it&#8217;s own unique color, and is represented with the use of bars in the chart)</li>
<li>timestamp (x)</li>
</ul>
<p><strong>Application server performance:</strong></p>
<p><strong><em>CPU USAGE</em></strong></p>
<p><strong><a href="http://qants.files.wordpress.com/2011/05/template1-resources-cpu-usage.png"><img class="aligncenter size-full wp-image-422" title="Jasper Report - Performance Report - CPU Usage" src="http://qants.files.wordpress.com/2011/05/template1-resources-cpu-usage.png?w=600" alt="Jasper Report - Performance Report - CPU Usage"   /></a><em>MEMORY USAGE<br />
</em></strong></p>
<p style="text-align:center;"><strong><em><a href="http://qants.files.wordpress.com/2011/05/template1-resources-memory-usage1.png"><img class="aligncenter size-full wp-image-424" title="Jasper Report - Performance Report - Heap Usage" src="http://qants.files.wordpress.com/2011/05/template1-resources-memory-usage1.png?w=600" alt="Jasper Report - Performance Report - Heap Usage"   /></a></em></strong></p>
<p><em><strong>HTTP THREAD POOL USAGE<br />
</strong></em></p>
<p><em><strong></strong></em><a href="http://qants.files.wordpress.com/2011/05/template1-resources-thread-usage.png"><img class="aligncenter size-full wp-image-425" title="Jasper Report - Performance Report - Thread Pool Usage" src="http://qants.files.wordpress.com/2011/05/template1-resources-thread-usage.png?w=600" alt="Jasper Report - Performance Report - Thread Pool Usage"   /></a></p>
<p><em><strong>JDBC THREAD POOL USAGE<br />
</strong></em></p>
<p style="text-align:left;"><em><strong></strong></em><a href="http://qants.files.wordpress.com/2011/05/monitor-jdbc-connections.jpg"><img class="aligncenter size-full wp-image-426" title="Jasper Report - Monitor JDBC Connections" src="http://qants.files.wordpress.com/2011/05/monitor-jdbc-connections.jpg?w=600&#038;h=201" alt="Jasper Report - Monitor JDBC Connections" width="600" height="201" /></a><br />
<em><strong>HTTP THREAD USAGE<br />
</strong></em></p>
<p style="text-align:left;"><a href="http://qants.files.wordpress.com/2011/05/monitor-http-thread-pool.jpg"><img class="aligncenter size-full wp-image-427" title="Jasper Report - Monitoring of Http Thread Pool" src="http://qants.files.wordpress.com/2011/05/monitor-http-thread-pool.jpg?w=600&#038;h=203" alt="Jasper Report - Monitoring of Http Thread Pool" width="600" height="203" /></a></p>
<p>We are now ready to combine all the information above into a single report. Normally, the application server monitoring charts would also be part of the report, but due to the size of the final report used in debugging, i cannot post it here. Normally, this would reside under the dual axis representation</p>
<p><em><strong>Jasper Report &#8211; Template 1 &#8211; Full Load and Performance Report</strong></em></p>
<div>
<p><a href="http://qants.files.wordpress.com/2011/05/template-1-report.jpg"><img class="aligncenter size-large wp-image-414" title="Load &amp; Performance Report - JMeter and Jasper Reports" src="http://qants.files.wordpress.com/2011/05/template-1-report.jpg?w=1024&#038;h=507" alt="Load &amp; Performance Report with Jasper Reports" width="1024" height="507" /></a></p>
<p>You can download the pdf (BI version) of this report from the following location:</p>
<p><em><br />
<a title="Performance Report - Business Intelligence version" href="http://qants.files.wordpress.com/2011/05/template-1-full-report.pdf">http://qants.files.wordpress.com/2011/05/template-1-full-report.pdf</a> </em></p>
<p><strong><em>Jasper Report &#8211; Template 2</em> <em>- Performance report / request &#8211; Drill down reporting</em></strong></p>
<p>If we wanted to see the behaviour of one request involved in the test, we would need to be able to select a single request from the main report, and drill down into it, analyzing the above information only for the selected request. The final report will look almost identical to the main report, the only difference being that all other requests will be filtered (not shown and not taken into consideration) This allows us to take an isolated look on the behaviour of a specific request with regard to the behaviour of the test in general</p>
<p>This is how the header will look like for the &#8220;Home&#8221; transaction, after drilling down from the report above. The drill down will select a transaction, and rebuild the report only for that transaction</p>
<p><em><strong>Drill down performance report</strong></em></p>
<p><a href="http://qants.files.wordpress.com/2011/05/template-2-filtered-header.jpg"><img class="aligncenter size-full wp-image-429" title="Template 2 - Filtered information" src="http://qants.files.wordpress.com/2011/05/template-2-filtered-header.jpg?w=600&#038;h=161" alt="Template 2 - Filtered information" width="600" height="161" /></a></p>
<p>Surely, the chart will also be filtered (this is only a sample of it, since it does not match the size of the image), and will follow exactly the same structure as Template 1, the main report</p>
<p><a href="http://qants.files.wordpress.com/2011/05/template-2-filtered-chart.jpg"><img class="aligncenter size-full wp-image-430" title="Template 2 - Filtered chart for one transaction" src="http://qants.files.wordpress.com/2011/05/template-2-filtered-chart.jpg?w=600&#038;h=148" alt="Template 2 - Filtered chart for one transaction" width="600" height="148" /></a></p>
<p><em><br />
</em></p>
<p><strong><em>Jasper Report &#8211; Template 3 &#8211; Performance report sampling &#8211; time filtering</em></strong></p>
<p>If we wanted to see the behaviour of the application under test at a specific point in time, we would need to be able to generate the report only for a <strong>selected timeframe</strong>. If for example we notice a sudden drop down in the throughput (number of transactions / second), we need to take a deeper look in the timeframe when this happened. The filtering of the timestamp will be reflected in all information, from response times, to the chart. (response times, average transactions, min and max times, etc.)</p>
<p>This is also very useful to see when the application is &#8220;on top&#8221;: all users have logged in, and the maximum number of transactions / second can be acchieved at this moment. You can therefore use such report to identify the &#8220;<strong>maximum number of transactions on top</strong>&#8221; and the <strong>corresponding response times</strong></p>
<p>This is how the chart will look like after filtering for one minute ( the selected timeframe) of the test. As one can see, the data is shown only for the selected timeframe.</p>
<p><a href="http://qants.files.wordpress.com/2011/05/template-3-time-sampling.jpg"><img class="aligncenter size-full wp-image-431" title="Template 3 - Time filtering load and performance report" src="http://qants.files.wordpress.com/2011/05/template-3-time-sampling.jpg?w=600&#038;h=189" alt="Template 3 - Time filtering load and performance report" width="600" height="189" /></a></p>
<p><strong><em>Jasper Report &#8211; Template 4 &#8211; Performance Report Memory usage<br />
</em></strong></p>
<h4 style="padding-left:30px;">Template 4.1 &#8211; Application specific &#8211; Application own objects</h4>
<p style="padding-left:30px;">We need to be able to monitor specific objects over time. We can have <strong>multiple reports</strong>, each representing <strong>different memory performance areas</strong>. The report below is a graphical representation of usage of<strong> objects belonging to the application under test</strong>, over time. Since the number of objects used in an application can be very high, the chart needs to be extended horizontally, therefore the sample below is a zoomed out version of the chart. As one can see, each object is represented with a different color, over time, so one can detect increases or decreases in number of objects over time.</p>
<p style="padding-left:30px;">The right side displays the legend, showing all object names and corresponding colors and forms used in representing in the chart.</p>
<p style="padding-left:30px;"><a href="http://qants.files.wordpress.com/2011/05/memory-usage-report-application-type.jpg"><img class="aligncenter size-full wp-image-435" title="Memory Usage Monitoring with JMap - Application own objects" src="http://qants.files.wordpress.com/2011/05/memory-usage-report-application-type.jpg?w=600&#038;h=76" alt="Memory Usage Monitoring with JMap - Application own objects" width="600" height="76" /></a></p>
<p style="padding-left:30px;">This is a sample of the report above, which demonstrates how the chart looks when zoomed in</p>
<p style="padding-left:30px;"><a href="http://qants.files.wordpress.com/2011/05/memory-usage-report-application-type-sample.jpg"><img class="aligncenter size-full wp-image-436" title="Memory Usage Monitoring with JMap - Application own objects" src="http://qants.files.wordpress.com/2011/05/memory-usage-report-application-type-sample.jpg?w=600&#038;h=220" alt="Memory Usage Monitoring with JMap - Application own objects" width="600" height="220" /></a></p>
<h4 style="padding-left:30px;">Template 4.2 &#8211; Application specific &#8211; Application own objects &#8211; Filtered object</h4>
<p style="padding-left:30px;">We need to drill down in the above report, by selecting the object for which we want a detailed report. This is how the report will look like. The upper part denotes the number of objects, the lower one the storage needed.</p>
<p style="padding-left:30px;"><a href="http://qants.files.wordpress.com/2011/05/memory-usage-report-application-type-filtered-on-class.jpg"><img class="aligncenter size-full wp-image-438" title="Memory usage with JMap - Focus on object" src="http://qants.files.wordpress.com/2011/05/memory-usage-report-application-type-filtered-on-class.jpg?w=600&#038;h=325" alt="Memory usage with JMap - Focus on object" width="600" height="325" /></a></p>
<h4 style="padding-left:30px;">Template 4.3 &#8211; Application specific &#8211; Java Base Type objects</h4>
<p style="padding-left:30px;">This report is using the same concept as the one above, but only the <strong>java base types</strong> are displayed (chars, integers, arrays, double arrays, etc.) The upper part displays the number of objects in memory at the time of sample, the one below displays the total number of bytes occupied in memory.</p>
<p style="padding-left:30px;">As in the chart above, the history is displayed on the right side</p>
<p style="padding-left:30px;"><a href="http://qants.files.wordpress.com/2011/05/memory-usage-report-java-base-types.jpg"><img class="aligncenter size-full wp-image-437" title="Memory Usage Monitoring with JMap - Primitives" src="http://qants.files.wordpress.com/2011/05/memory-usage-report-java-base-types.jpg?w=600&#038;h=359" alt="Memory Usage Monitoring with JMap - Primitives" width="600" height="359" /></a></p>
<p><em> </em><br />
Basically, as it will be explained in the details section, the memory analysis reporting can be extended to any pattern of objects by simply adding them to the function collecting the memory usage information. In the end it is a question of creating a separate query for each of the type of objects we need, and use it in a separate dataset or report. I have for example created different reports for eclipselink objects, javascript objects, vectors lists and arrays, etc.</p>
<hr />
<p>I discussed about the outputs, the performance reports. Now i will focus myself on how to build the integrated load testing solution, from generating the load to presenting it in graphical representations, and integrating them into continuous integration systems, or automating them as individual test suites.</p>
<p>The rest of the items following will be presented using the following structure:</p>
<h3><strong>CONFIGURING LOAD GENERATORS</strong></h3>
<ol>
<li><strong>Load testing generators &#8211; Getting your application under load with distributed JMeter</strong>
<ul>
<li>basic concept of jmeter in distributed mode and network architecturing</li>
<li>detail of the concept to which this white paper is referring</li>
<li>detail of the folder structure needed (results, temporary folders, transformation folders,classes, scripts and testplan folders,property files)</li>
<li>configuring the server and the agents</li>
</ul>
</li>
<li><strong>Test plan structure</strong>
<ul>
<li>configuring the testplan to use dynamic generated parameters (runtime parameters and property files)</li>
</ul>
</li>
<li><strong>Test script structure</strong>
<ul>
<li>name of the testplan</li>
<li>location of the testplan</li>
<li>jmeter agents to use in the load test</li>
<li>workflow controlling : defining what and the order of the functions called (starting the test, collecting memory information, collecting jms information, warming up, collecting logs data transformation, generating performance report, etc.) thereby controlling the run of the test</li>
<li>runtime parameters &#8211; virtual users, ramp up time, pause times, number of repetions, number of loops / repetition, application specific parameters, etc.)</li>
</ul>
</li>
<li><strong>Function file</strong>
<ul>
<li>detail of the file containing all functions needed for controlling the load test, and of the functions in the file</li>
</ul>
</li>
<li><strong>Storing and processing the test results</strong>
<ul>
<li>selecting what information to store</li>
<li>transforming the results file into a fully xml compliant file for further ETL processing &#8211; detail of processing functions</li>
</ul>
</li>
<li><strong>Storing and processing additional collected data</strong>
<ul>
<li>use of shell functions for collecting application server information such as memory, jms usage, ejb cache usage and so on</li>
<li>detailing of tools used to collect application server information:</li>
<ul>
<li>jmap for memory</li>
<li>imqcmd for jms</li>
<li>vmstat for cpu</li>
<li>glassfish rest monitoring for app server resources</li>
</ul>
</ul>
</li>
</ol>
<h3>ETL &#8211; EXTRACT TRANSFORM AND LOAD &#8211; DATA PROCESSING AND IMPORTING INTO THE DATABASE</h3>
<ol>
<li><strong>Database structure:</strong>
<ul>
<li>detail of the structure needed for performance reporting</li>
<li>ER Diagram</li>
</ul>
</li>
<li><strong>Importing test results into the database using Pentaho Data Integration Jobs</strong>
<ul>
<li>import job for response times and throughput</li>
<li>import job for memory footprinting</li>
</ul>
</li>
</ol>
<h3>REPORTING</h3>
<ol>
<li><strong><strong>Jasper Reports &#8211; Generating and storing the performance reports<br />
</strong></strong></p>
<ul>
<li>using Jasper Server for reporting server</li>
<li>using IReport for designing reports</li>
<li>detailing of reports based on real life examples</li>
</ul>
</li>
<li><strong>Continuous integration &#8211; Automating and Integrating the tests into CI Systems</strong>
<ul>
<li>integrating with hudson: concept, implementation</li>
<li>jmeter plugin description and configuration</li>
<li>automatically generating reports with use of JMeter testplans</li>
</ul>
</li>
</ol>
<div>This is it for now. In the next article i will discuss the first point, configuring the load generators, with the rest of the points to follow in the near future. Please let me know if you have any questions to be cleared up to this point, and if you find this article useful.</div>
<div>Alex</div>
<hr />
<div style="text-align:center;"><strong>End of part 1 &#8211; Load &amp; Performance testing and reporting with open source tools &#8211;  Concept, examples and sample reports</strong></div>
<hr />
</div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/qants.wordpress.com/443/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/qants.wordpress.com/443/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/qants.wordpress.com/443/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/qants.wordpress.com/443/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/qants.wordpress.com/443/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/qants.wordpress.com/443/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/qants.wordpress.com/443/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/qants.wordpress.com/443/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/qants.wordpress.com/443/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/qants.wordpress.com/443/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/qants.wordpress.com/443/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/qants.wordpress.com/443/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/qants.wordpress.com/443/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/qants.wordpress.com/443/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=alexandru-ersenie.com&amp;blog=9058370&amp;post=443&amp;subd=qants&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://alexandru-ersenie.com/2011/05/12/java-ee-load-performance-testing-and-reporting-using-open-source-tools-part-1-concept-examples-and-sample-reports/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/19315d494e10cf62a36e142aaf2177cf?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">skipper</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/05/template1-test-information1.png" medium="image">
			<media:title type="html">Load &#38; Performance Report - Test Information</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/05/template1-server-configuration.png" medium="image">
			<media:title type="html">Load &#38; Performance Report - Server configuration information</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/05/template1-response-times.png" medium="image">
			<media:title type="html">Load &#38; Performance Report - Response times per transaction</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/05/template-1-chart.jpg" medium="image">
			<media:title type="html">Load &#38; Performance Report - Transactions vs Response Times</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/05/template1-resources-cpu-usage.png" medium="image">
			<media:title type="html">Jasper Report - Performance Report - CPU Usage</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/05/template1-resources-memory-usage1.png" medium="image">
			<media:title type="html">Jasper Report - Performance Report - Heap Usage</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/05/template1-resources-thread-usage.png" medium="image">
			<media:title type="html">Jasper Report - Performance Report - Thread Pool Usage</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/05/monitor-jdbc-connections.jpg" medium="image">
			<media:title type="html">Jasper Report - Monitor JDBC Connections</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/05/monitor-http-thread-pool.jpg" medium="image">
			<media:title type="html">Jasper Report - Monitoring of Http Thread Pool</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/05/template-1-report.jpg?w=1024" medium="image">
			<media:title type="html">Load &#38; Performance Report - JMeter and Jasper Reports</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/05/template-2-filtered-header.jpg" medium="image">
			<media:title type="html">Template 2 - Filtered information</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/05/template-2-filtered-chart.jpg" medium="image">
			<media:title type="html">Template 2 - Filtered chart for one transaction</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/05/template-3-time-sampling.jpg" medium="image">
			<media:title type="html">Template 3 - Time filtering load and performance report</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/05/memory-usage-report-application-type.jpg" medium="image">
			<media:title type="html">Memory Usage Monitoring with JMap - Application own objects</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/05/memory-usage-report-application-type-sample.jpg" medium="image">
			<media:title type="html">Memory Usage Monitoring with JMap - Application own objects</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/05/memory-usage-report-application-type-filtered-on-class.jpg" medium="image">
			<media:title type="html">Memory usage with JMap - Focus on object</media:title>
		</media:content>

		<media:content url="http://qants.files.wordpress.com/2011/05/memory-usage-report-java-base-types.jpg" medium="image">
			<media:title type="html">Memory Usage Monitoring with JMap - Primitives</media:title>
		</media:content>
	</item>
	</channel>
</rss>
