<?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/"
	>

<channel>
	<title>Java EE performance</title>
	<atom:link href="http://www.opensides.fr/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.opensides.fr</link>
	<description>- Arnault Jeanson&#039;s blog</description>
	<lastBuildDate>Mon, 14 Mar 2011 23:48:38 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Installer Hadoop en moins de 5 minutes</title>
		<link>http://www.opensides.fr/2011/03/14/installer-hadoop-en-moins-de-5-minutes/</link>
		<comments>http://www.opensides.fr/2011/03/14/installer-hadoop-en-moins-de-5-minutes/#comments</comments>
		<pubDate>Mon, 14 Mar 2011 23:45:47 +0000</pubDate>
		<dc:creator>ajeanson</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[MapReduce]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[Non classé]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://www.opensides.fr/?p=546</guid>
		<description><![CDATA[Dans un précédent post, nous avions vu les grands concepts d’Hadoop (cf. http://www.opensides.fr/2011/03/10/hadoop-en-moins-de-5-minutes).  Aujourd&#8217;hui nous allons consacrer 5 nouvelles minutes avec Hadoop pour passer à la pratique.
Les objectifs:

Monter un environnement opérationnel en moins de 2 minutes
Tour d&#8217;horizon de Cloudera en 1 minute
Tester quelques commandes HDFS en 1 minute
Tester un Map Reduce en 1 minute

Monter un [...]]]></description>
			<content:encoded><![CDATA[<p>Dans un précédent post, nous avions vu les grands concepts d’Hadoop (cf. <a href="http://www.opensides.fr/2011/03/10/hadoop-en-moins-de-5-minutes">http://www.opensides.fr/2011/03/10/hadoop-en-moins-de-5-minutes</a>).  Aujourd&#8217;hui nous allons consacrer 5 nouvelles minutes avec Hadoop pour passer à la pratique.</p>
<h1>Les objectifs:</h1>
<ol>
<li>Monter un environnement opérationnel en moins de 2 minutes</li>
<li>Tour d&#8217;horizon de Cloudera en 1 minute</li>
<li>Tester quelques commandes HDFS en 1 minute</li>
<li>Tester un Map Reduce en 1 minute</li>
</ol>
<h1>Monter un environnement opérationnel en 2 minutes</h1>
<h2>30 secondes pour parler de Cloudera</h2>
<p>Apache distribue une version packagée de l&#8217;écosystème complet Hadoop. Cette version s&#8217;appelle Cloudera: Cloudera’s Distribution for Apache Hadoop (CDH).<br />
Elle est basée sur les dernières versions stables de Hadoop, contient également des patchs additionels. La bonne nouvelle est que Cloudera fournie même une VM, il n&#8217;y a donc rien à installer&#8230;</p>
<p>Voici son contenu:</p>
<ul>
<li>HDFS – Le système de fichier distribué de Hadoop</li>
<li>MapReduce – Le framework de parallelisation des traitements</li>
<li>Hadoop Common – Un ensemble d&#8217;utilitaire qui supportent les sous projets de Hadoop</li>
<li>HBase – La base de donnée NoSQL de Hadoop</li>
<li>Hive – Une surcouche au MapReduce offrant un pseudo language SQL pour interagir avec le HDFS</li>
<li>Pig – Un language d&#8217;analyse des données</li>
<li>Oozie – Un système de workflow pour gérer les jobs interdépendant</li>
<li>Sqoop – Framework d&#8217;intégration des bases de données avec Hadoop</li>
<li>Flume – Un système de streaming très efficaces</li>
<li>Zookeeper – Un système de coordination des configigurations et des services en environnement distribué</li>
<li>Hue – Une interface utilisateur pour gérer les application Hadoop</li>
</ul>
<h2>1 minute 30 pour l’installation</h2>
<p>Télécharger  de la VM ici: <a href="http://cloudera-vm.s3.amazonaws.com/cloudera-training-0.3.3.tar.bz2?downloads">http://cloudera-vm.s3.amazonaws.com/cloudera-training-0.3.3.tar.bz2?downloads</a><br />
Detarrer le tout et lancer la VM avec le player VMWare (accessible ici si vous ne l’avez pas encore: <a href="http://downloads.vmware.com/d/info/desktop_downloads/vmware_player/3_0">http://downloads.vmware.com/d/info/desktop_downloads/vmware_player/3_0</a>)<br />
Attention: VMWare Fusion est payant sous Mac.</p>
<p>On démarre la VM et hop c’est magique nous avons un Ubuntu avec tout l’écosystème Hadoop prêt à l’emploi.</p>
<p><a href="http://www.opensides.fr/wp-content/uploads/2011/03/cloudera-welcome.png"><img class="aligncenter size-medium wp-image-554" title="cloudera-welcome" src="http://www.opensides.fr/wp-content/uploads/2011/03/cloudera-welcome-300x218.png" alt="" width="300" height="218" /></a></p>
<h2>Tour d&#8217;horizon de Cloudera en 1 minute</h2>
<p>Lorsque l&#8217;on démarre la VM, on peut voir le kit de base pour commencer avec Hadoop:</p>
<ul>
<li>un navigateur</li>
</ul>
<ul>
<li>un Eclipse</li>
</ul>
<ul>
<li>un terminal</li>
</ul>
<ul>
<li>un répertoire contenant des instructions</li>
</ul>
<p><strong>Navigateur</strong></p>
<p>Commençons par ouvrir le navigateur. On peut voir l&#8217;interface d&#8217;administration web de Hadoop. Cette interface va nous permettre:</p>
<p>- de surveiller les jobs (en cours, terminés, échoué, ..)</p>
<p>- de naviguer dans le système de fichier HDFS</p>
<p><a href="http://www.opensides.fr/wp-content/uploads/2011/03/navigateur.png"><img class="aligncenter size-medium wp-image-559" title="navigateur" src="http://www.opensides.fr/wp-content/uploads/2011/03/navigateur-300x267.png" alt="" width="300" height="267" /></a></p>
<p><strong>Eclipse</strong></p>
<p>En ouvrant Eclipse, on peut voir qu&#8217;un workspace est déja chargé avec un ensemble de projets exemples.</p>
<p><a href="http://www.opensides.fr/wp-content/uploads/2011/03/eclipse.png"><img class="aligncenter size-medium wp-image-561" title="eclipse" src="http://www.opensides.fr/wp-content/uploads/2011/03/eclipse-300x242.png" alt="" width="300" height="242" /></a></p>
<p><strong>Instructions</strong></p>
<p>Enfin nous pouvons ouvrir le répertoire qui se trouve sur le bureau. On voit que ce répertoire contient un ensemble de tutoriaux et d&#8217;exercices pour appréhender le framework.</p>
<p><a href="http://www.opensides.fr/wp-content/uploads/2011/03/instructions.png"><img class="aligncenter size-medium wp-image-562" title="instructions" src="http://www.opensides.fr/wp-content/uploads/2011/03/instructions-300x193.png" alt="" width="300" height="193" /></a></p>
<h2>Tester quelques commandes HDFS en 1 minute</h2>
<p>Il est temps de manipuler un peu le système de fichier HDFS. Pour cela, ouvrons un terminal. Commençons par taper  <em><strong>hadoop</strong></em> pour voir l&#8217;ensemble des commandes disponibles.</p>
<p><a href="http://www.opensides.fr/wp-content/uploads/2011/03/terminal.png"><img class="aligncenter size-medium wp-image-563" title="terminal" src="http://www.opensides.fr/wp-content/uploads/2011/03/terminal-300x230.png" alt="" width="300" height="230" /></a></p>
<p>Nous allons utiliser la commande fs qui permet de manipuler le file système: <strong>hadoop fs -&lt;commande&gt;</strong></p>
<p>Nous allons pousser un fichier dans le HDFS avec la commande: <strong>hadood fs -put README /README<br />
</strong></p>
<p>Vérifions maintenant que le fichier est bien présent avec la commande: <strong>hadoop fs -ls /</strong></p>
<p>Lisons le contenu du fichier : <strong>hadoop fs -tail /README</strong></p>
<p><strong>-&gt; les commandes fs reprennent la syntaxe des commandes shell et pour avoir un détail sur ces commandes, je vous invite à lire la très bonne page man ou d&#8217;aller sur la page </strong><a href="http://hadoop.apache.org/common/docs/r0.19.2/hdfs_shell.html">http://hadoop.apache.org/common/docs/r0.19.2/hdfs_shell.html</a></p>
<h2>Tester un Map Reduce en 1 minute</h2>
<p>Passons maintenant au Map Reduce. Pour ça direction Eclipse pour voir si nous trouvons un exemple de MapReduce à tester. Nous pouvons voir que Cloudera nous fourni un ensemble très complet d&#8217;exemples. Nous allons donc pouvoir exporter un jar pour le tester directement dans un terminal sur le fichier que nous avons poussé.</p>
<p>Petite note sous Eclipse. Il existe un bug lié à la librairie d&#8217;affichage d&#8217;Eclipse que les utilisateurs Ubuntu connaissent bien. La parade ? Il suffit de se créer un petit script de lancement:<strong><br />
</strong></p>
<blockquote><p><strong>export GDK_NATIVE_WINDOWS=true</strong></p>
<p><strong>./eclipse</strong></p></blockquote>
<p>Parmi les exemples exportons le fameux exemple <em><strong>WordCount</strong></em> sous forme de jar executable et lançons le en lui donnant en paramètre un fichier en entrée et une destination en sortie:</p>
<p>Avec la commande <em><strong>hadoop fs -put toto.txt /input/toto</strong></em>, poussons un fichier exemple <em><strong>toto.txt</strong></em> contenant<em><strong>:</strong></em></p>
<blockquote><p><em><strong> a b a </strong></em></p>
<p><em><strong>a b b</strong></em></p>
<p><em><strong>b c c c</strong></em></p></blockquote>
<p>Lançons ensuite notre job:</p>
<blockquote><p><strong>java -jar sample.jar /user/training/input/toto /output</strong></p></blockquote>
<p>Et nous obtenons le résultat suivant:</p>
<blockquote><p>a 3</p>
<p>b 3</p>
<p>c 3</p></blockquote>
<h2>Conclusion</h2>
<p>Dans ce post nous sommes passé un peu à la pratique. Nous avons pu faire ça très rapidement grâce à la distribution Cloudera qui permet de démarrer très vite. Pour aller plus loin, je vous conseille de lire les tutoriaux proposés et de regarder les exemples proposés. Dans un prochain post, nous verrons en détail implémentation d&#8217;un Map Reduce.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.opensides.fr/2011/03/14/installer-hadoop-en-moins-de-5-minutes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Comprendre Hadoop en moins de 5 minutes</title>
		<link>http://www.opensides.fr/2011/03/10/hadoop-en-moins-de-5-minutes/</link>
		<comments>http://www.opensides.fr/2011/03/10/hadoop-en-moins-de-5-minutes/#comments</comments>
		<pubDate>Thu, 10 Mar 2011 21:11:41 +0000</pubDate>
		<dc:creator>ajeanson</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[MapReduce]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[Non classé]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[hadoop]]></category>
		<category><![CDATA[hdfs]]></category>

		<guid isPermaLink="false">http://www.opensides.fr/?p=518</guid>
		<description><![CDATA[Dans ce tutorial, nous allons découvrir Hadoop au travers de son système de fichiers distribués et son mécanisme de Map/Reduce.
Objectifs

 Comprendre les grands concepts de Hadoop
 Comprendre le HDFS et le mécanisme de Map/Reduce

2 minutes 30 pour comprendre les grands concepts
Hadoop est un projet Open Source écrit en java, distribué par la fondation Apache. Ce [...]]]></description>
			<content:encoded><![CDATA[<p>Dans ce tutorial, nous allons découvrir Hadoop au travers de son système de fichiers distribués et son mécanisme de Map/Reduce.</p>
<h2><strong>Objectifs</strong></h2>
<ul>
<li> Comprendre les grands concepts de Hadoop</li>
<li> Comprendre le HDFS et le mécanisme de Map/Reduce</li>
</ul>
<h2><strong>2 minutes 30 pour comprendre les grands concepts</strong></h2>
<p>Hadoop est un projet Open Source écrit en java, distribué par la fondation Apache. Ce framework est adapté dans le stockage et le traitement par lots de très grandes quantités de données (à partir du pétaoctet). Il a été mis en avant par des grands noms du web comme Yahoo! ou Facebook.<br />
Son système de fichiers HDFS permet  de distribuer le stockage des données et de faire des analyses très performantes sur ces données grâce au modèle MapReduce permettant de distribuer une opération sur plusieurs nœuds dans le but de paralléliser leur exécution.</p>
<h3><strong>Le HDFS</strong></h3>
<p>Le HDFS est le système de fichiers utilisé par Hadoop. C&#8217;est un système de fichiers distribués où les blocs d&#8217;informations sont répartis et répliqués sur les différents nœuds du cluster. Cette réplication est configurable.<br />
Pour plus d&#8217;informations sur l&#8217;architecture et la configuration du HDFS vous pouvez consultez la très bonne documentation de Hadoop: <a href="http://hadoop.apache.org/hdfs/">http://hadoop.apache.org/hdfs/</a><br />
<a href="http://www.opensides.fr/wp-content/uploads/2011/03/hdfs.png"><img class="aligncenter size-medium wp-image-504" title="hdfs" src="http://www.opensides.fr/wp-content/uploads/2011/03/hdfs-300x180.png" alt="" width="357" height="214" /></a></p>
<p>Il est important de savoir qu&#8217;un ensemble de commandes est mis à disposition pour interagir avec ce système.</p>
<p>Il suffit d&#8217;invoquer la commande: <em><strong>hadoop fs  -&lt;commande&gt;</strong></em>. La syntaxe est très proche du shell et l&#8217;on retrouve les commandes standards( ls, cp, mv, rm, cat, tail ..)</p>
<p><span style="text-decoration: underline;">Voici quelques exemples de commandes utiles:</span></p>
<ul>
<li> <em>Upload un fichier dans le file système:</em> hadoop fs -put logs/ hdfs://localhost:8022/inpu<em>t</em></li>
<li><em> Download un fichier à partir du file système:</em> hadoop fs -get hdfs://localhost:8022/input logs/</li>
<li> <em>Parcourir le HDFS:</em> hadoop fs -ls hdfs://localhost:8022/input</li>
</ul>
<p>L&#8217;ensemble des commandes est documenté ici: <a href="http://hadoop.apache.org/common/docs/r0.18.3/hdfs_shell.html">http://hadoop.apache.org/common/docs/r0.18.3/hdfs_shell.html</a></p>
<h3><strong>Le Map Reduce</strong></h3>
<p>Ce fonctionnement consiste en deux étapes de traitement, chacune parallélisable sur un ensemble de nœuds : le <em><strong>Mapping</strong></em> et le <em><strong>Reducing</strong></em>.</p>
<p>Le <strong>Mapping</strong> est une fonction parallélisable dispatchée sur l&#8217;ensemble des noeuds d&#8217;un cluster. Elle s&#8217;applique à une liste fournie en entrée (input list fournie par le HDFS) et dont le résultat est mis à disposition dans une nouvelle liste (output list) stockée sur le HDFS.<br />
<a href="http://www.opensides.fr/wp-content/uploads/2011/03/mapping.png"><img class="aligncenter size-medium wp-image-501" title="mapping" src="http://www.opensides.fr/wp-content/uploads/2011/03/mapping-300x117.png" alt="" width="300" height="117" /></a><br />
Le <strong>Reducing</strong> est une fonction également dispatchable sur un ensemble de nœuds. Elle consiste à agréger les résulats sous forme clés/valeurs de la liste mise à disposition par la fonction de Mapping (output list).<br />
<a href="http://www.opensides.fr/wp-content/uploads/2011/03/reducing.png"><img class="aligncenter size-medium wp-image-502" title="reducing" src="http://www.opensides.fr/wp-content/uploads/2011/03/reducing-300x159.png" alt="" width="300" height="159" /></a></p>
<h2>2 minutes 30 pour comprendre un cas pratique</h2>
<p>Prenons un exemple pour illustrer ce mécanisme. Celui qui revient le plus souvent dans la littérature est le use case <em><strong>Word Count</strong></em> consistant à comptabiliser le nombre de mots contenus dans un fichier stocké dans le HDFS.</p>
<p>Etudions en détail les différentes étapes.</p>
<p><strong>1- Stockage du fichier dans le HDFS:</strong></p>
<p style="padding-left: 30px;">Nous décidons d&#8217;envoyer un livre <strong><em>monLivre.txt</em></strong> dans le HDFS à l&#8217;emplacement <em><strong>input/books</strong></em></p>
<p style="padding-left: 30px;">Voici la commande: <em><strong>hadoop fs -put monLivre.txt hdfs://localhost:8022/input/books</strong></em></p>
<p>&gt;On peut voir sur le schéma que le fichier est découpé en blocs contenant chacun une partie du fichier et réparti sur un ensemble de nœuds du cluster HDFS en fonction de la configuration.  <em><strong><a href="http://www.opensides.fr/wp-content/uploads/2011/03/Diapositive1.jpg"><br />
</a><a href="http://www.opensides.fr/wp-content/uploads/2011/03/Diapositive11.jpg"></a><a href="http://www.opensides.fr/wp-content/uploads/2011/03/Diapositive12.jpg"><img class="aligncenter size-full wp-image-530" title="Diapositive1" src="http://www.opensides.fr/wp-content/uploads/2011/03/Diapositive12.jpg" alt="" width="720" height="540" /></a><br />
</strong></em><strong>2- Comptage des mots en Map Reduce:</strong></p>
<p>L&#8217;opération de comptage des mots serait très longue si notre traitement se faisait directement sur le livre. L&#8217;interêt du Map Reduce est de paralleliser les traitement sur l&#8217;ensemble des noeuds du HDFS.</p>
<p>Dans le schéma ci-dessous, on peut voir les différentes étapes:</p>
<p style="padding-left: 30px;">1 le fichier est découpé en différents blocs répartir sur les différents noeuds comme nous l&#8217;avons vu précédemment</p>
<p style="padding-left: 30px;">2 le mapping consiste à envoyer le traitement de comptage sur chacun de ces blocs et d&#8217;effectuer le processing</p>
<p style="padding-left: 30px;">3 le shuffling consiste à trier ces informations</p>
<p style="padding-left: 30px;">4 le reducing est l&#8217;opération qui consiste à agréger les informations récupérée</p>
<p><a href="http://www.opensides.fr/wp-content/uploads/2011/03/Diapositive2.jpg"><img class="aligncenter size-full wp-image-528" title="Diapositive2" src="http://www.opensides.fr/wp-content/uploads/2011/03/Diapositive2.jpg" alt="" width="720" height="540" /></a></p>
<h2><strong><strong>Conclusion</strong></strong></h2>
<p>Ce post a permis de vous donner un aperçu rapide du système de fichier distribué HDFS  et du mécanisme de MapReduce.</p>
<p>Pour aller plus loin, je vous invite à jeter un oeil sur la documentation officielle de Hadoop:</p>
<p><strong>HDFS:</strong> http://hadoop.apache.org/hdfs/docs/r0.21.0/</p>
<p><strong>MapReduce:</strong> http://hadoop.apache.org/mapreduce/docs/r0.21.0/</p>
<p>Maintenant que vous maîtriser les concepts et s&#8217;il vous reste 5 minutes, rendez-vous ici pour pour voir comment monter monter un environnement en moins de 5 minutes: <a href="http://www.opensides.fr/2011/03/14/installer-hadoop-en-moins-de-5-minutes">http://www.opensides.fr/2011/03/14/installer-hadoop-en-moins-de-5-minutes</a></p>
<p><strong><br />
</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.opensides.fr/2011/03/10/hadoop-en-moins-de-5-minutes/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>NginX en moins de 5 minutes</title>
		<link>http://www.opensides.fr/2011/02/20/nginx-en-moins-de-5-minutes/</link>
		<comments>http://www.opensides.fr/2011/02/20/nginx-en-moins-de-5-minutes/#comments</comments>
		<pubDate>Sun, 20 Feb 2011 20:36:29 +0000</pubDate>
		<dc:creator>ajeanson</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[asynchrone]]></category>
		<category><![CDATA[nginx]]></category>

		<guid isPermaLink="false">http://www.opensides.fr/?p=474</guid>
		<description><![CDATA[Dans cet article nous allons faire la connaissance rapide des serveurs web asynchrones. Le but de ce post est de vous faire découvrir cette nouvelle génération de serveur en montrant comment installer et configurer de façon basique celui qui me semble le plus aboutit et le plus performant. Nous verrons plus tard tirer profit de [...]]]></description>
			<content:encoded><![CDATA[<p>Dans cet article nous allons faire la connaissance rapide des serveurs web asynchrones. Le but de ce post est de vous faire découvrir cette nouvelle génération de serveur en montrant comment installer et configurer de façon basique celui qui me semble le plus aboutit et le plus performant. Nous verrons plus tard tirer profit de ce type d&#8217;architecture pour servir de hautes volumétries.</p>
<h2>Quelques rappels</h2>
<p>Un serveur http a pour vocation de servir du contenu en fonction des requêtes clientes. Ce contenu est distribué via le protocole http et peut être statique (images, css, javascript, …) ou dynamique (php, java, .net, …).</p>
<p>Le plus connu de ces serveurs, est Apache. C’est un serveur web dit synchrone, il va affecter un <a href="http://fr.wikipedia.org/wiki/Processus_%28informatique%29">processus</a> fils à chaque requête. Il est stable, efficace, facile à installer et son initiale va bien entre le L et le M de la stack L<strong>A</strong>MP.</p>
<h2><strong>Limitations des serveurs web traditionnels<br />
</strong></h2>
<p>Le mécanisme d’attribution de processus à chaque requête se révèle très consommateur de RAM et confie le multiplexage temporel des tâches au système d&#8217;exploitation ce qui n’est pas toujours optimisé pour traiter le changement d’état des requêtes.</p>
<h2><strong>Une nouvelle génération de serveurs</strong></h2>
<p>Pour ces raisons une nouvelle génération de serveurs a vu le jour depuis quelques années, les serveurs web asynchrones. On peut en citer quelques uns <a href="http://mina.apache.org/">Mina</a>, <a href="http://www.lighttpd.net/">Lighthttp</a>,  <a href="http://wiki.nginx.org/Main">Nginx</a>. Ce dernier est selon moi le plus performant et le plus aboutit.  Son mécanisme consiste à diviser chaque requêtes en micros tâches qui seront multiplexées en même temps que traitées afin d’optimiser les ressources et les temps de latence cpu. Ce choix d’architecture offre des performances très élevées avec un consommation des ressources optimisée. Nginx fait ses preuves auprès de différentes</p>
<p>Il a été utilisé depuis plusieurs années sur des sites russes à fort trafic tel que <a href="http://www.rambler.ru/">Rambler</a>, avant d’être plus largement répandu aujourd’hui : <a title="WordPress.com" href="http://wordpress.com/">WordPress.com</a>, <a title="Hulu" href="http://www.hulu.com/">hulu</a>, <a title="Gravatar" href="http://www.gravatar.com/">Gravatar</a>, <a title="Kongregate" href="http://en.wikipedia.org/wiki/Kongregate">Kongregate</a>, <a title="Userscripts.org" href="http://userscripts.org/">userscripts.org</a> et même &#8230; <a href="http://www.youporn.com">YouPorn</a> ; )</p>
<p>Voici un petit bench comparatif des temps de réponses Apache v/s Nginx tiré du site <a href="http://www.joeandmotorboat.com/2008/02/28/apache-vs-nginx-web-server-performance-deathmatch/">http://www.joeandmotorboat.com/2008/02/28/apache-vs-nginx-web-server-performance-deathmatch/:</a></p>
<p style="text-align: center;"><a href="http://www.opensides.fr/wp-content/uploads/2011/02/response-time.jpg"><img class="size-medium wp-image-479  aligncenter" title="response-time" src="http://www.opensides.fr/wp-content/uploads/2011/02/response-time-300x198.jpg" alt="" width="390" height="257" /></a></p>
<h2><strong>Quelques benchs par ici :</strong></h2>
<p><a href="http://www.joeandmotorboat.com/2008/02/28/apache-vs-nginx-web-server-performance-deathmatch/">http://www.first-world.info/apache-vs-lighttpd-vs-nginx.html</a></p>
<p><a href="http://www.joeandmotorboat.com/2008/02/28/apache-vs-nginx-web-server-performance-deathmatch/">http://www.joeandmotorboat.com/2008/02/28/apache-vs-nginx-web-server-performance-deathmatch/</a></p>
<h2>Installation de Nginx sous Ubuntu</h2>
<p>Nginx est maintenant disponible sur les dépôts, un petit apt-get fera donc l&#8217;affaire&#8230;</p>
<blockquote><p>sudo apt-get install nginx</p></blockquote>
<h2>Configuration de Nginx</h2>
<p>Fichier de configuration: <strong><em>/etc/nginx/sites-available/default</em></strong></p>
<p>Une simple modification va consister à modifier le port d&#8217;écoute de 80 vers 81.<strong><em><br />
</em></strong></p>
<blockquote><p>ajeanson@www:/etc/nginx$ sudo vi sites-available/default</p>
<p># You may add here your<br />
# You may add here your<br />
# server {<br />
#       &#8230;<br />
# }<br />
# statements for each of your virtual hosts</p>
<p>server {<br />
<strong>listen   81;</strong><br />
server_name  localhost;</p>
<p>access_log  /var/log/nginx/localhost.access.log;</p>
<p>location / {<br />
root   /var/www/nginx-default;<br />
index  index.html index.htm;<br />
}</p>
<p>location /doc {<br />
root   /usr/share;<br />
autoindex on;<br />
allow 127.0.0.1;<br />
deny all;<br />
}</p>
<p>location /images {<br />
root   /usr/share;<br />
autoindex on;<br />
}</p>
<p>&#8230;</p></blockquote>
<h2>Démarrage de Nginx</h2>
<blockquote><p>sudo /etc/init.d/nginx start</p></blockquote>
<p>Le résultat est visible ici:</p>
<p><a href="http://www.opensides.fr:81/">http://www.opensides.fr:81/</a></p>
<h2>Conclusion</h2>
<p>Nous avons vu que l&#8217;installation de Nginx était très simple. Nous verrons dans de prochains articles comment utiliser au mieux les différents modules de Nginx pour doper les performances de votre site web.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.opensides.fr/2011/02/20/nginx-en-moins-de-5-minutes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Memcached en moins de 5 minutes &#8230;</title>
		<link>http://www.opensides.fr/2011/01/02/memcached-en-moins-de-5-minutes/</link>
		<comments>http://www.opensides.fr/2011/01/02/memcached-en-moins-de-5-minutes/#comments</comments>
		<pubDate>Sun, 02 Jan 2011 21:04:47 +0000</pubDate>
		<dc:creator>ajeanson</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Non classé]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[cache distribué]]></category>

		<guid isPermaLink="false">http://www.opensides.fr/?p=455</guid>
		<description><![CDATA[
Tout le monde connaît Memcached ? Non ?
Memcached est un cache Open Source distribué et non répliqué. Cela veut dire que que nous pouvons utiliser plusieurs instances de Memcached mais que chaque instance est autonome. Si l&#8217;une d&#8217;elle tombe, ses données seront donc perdues (pas de réplication entre instance).
Pour aller plus loin, je vous conseille [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.opensides.fr/wp-content/uploads/2011/01/memcached_banner75.jpg"><img class="size-medium wp-image-468 alignleft" title="memcached_banner75" src="http://www.opensides.fr/wp-content/uploads/2011/01/memcached_banner75-300x55.jpg" alt="MemCached" width="715" height="130" /></a></p>
<p>Tout le monde connaît Memcached ? Non ?</p>
<p>Memcached est un cache Open Source distribué et non répliqué. Cela veut dire que que nous pouvons utiliser plusieurs instances de Memcached mais que chaque instance est autonome. Si l&#8217;une d&#8217;elle tombe, ses données seront donc perdues (pas de réplication entre instance).</p>
<p>Pour aller plus loin, je vous conseille le wiki de Memcached: http://memcached.org/</p>
<p>Nous allons voir maintenant comment l&#8217;installer sur un unix:</p>
<h1>Installation de libEvent (une dépendance de Memcached)</h1>
<ol>
<li>Vérifier que libEvent ne soit pas déja installé en tapant la commande <strong><em>whereis libevent</em></strong> dons votre terminal</li>
<li>S&#8217;il n&#8217;est pas déja installé, vous pouvez le récupérer à l&#8217;adresse suivante: <a href="http://monkey.org/~provos/libevent/">http://monkey.org/~provos/libevent/</a></li>
<li>Décompresser l&#8217;archive sur votre disque</li>
<li>Dans un terminal taper les commandes suivantes:</li>
</ol>
<blockquote>
<pre>./configure
make
sudo make install</pre>
</blockquote>
<h1>Installation de Memcached</h1>
<ol>
<li>Vous pouvez le récupérer à l&#8217;adresse suivante: <a href="http://memcached.org/">http://memcached.org/</a><a href="http://monkey.org/%7Eprovos/libevent/"></a></li>
<li>Décompresser l&#8217;archive sur votre disque</li>
<li>Dans un terminal taper les commandes suivantes:</li>
</ol>
<blockquote>
<pre>./configure
make
sudo make install<em>
sudo ln -s /usr/local/lib/libevent-1.4.so.2 /usr/lib
</em></pre>
</blockquote>
<h1>Démarrer MemCached</h1>
<blockquote>
<pre>memcached -p <em>11111</em><em>
</em></pre>
</blockquote>
<h1>Tester MemCached avec telnet</h1>
<blockquote>
<pre>$ telnet localhost 11211
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
get foo
VALUE foo 0 2
hi
END
stats
STAT pid 8861
(etc)</pre>
</blockquote>
<h1>Tester MemCached en Java</h1>
<p>Il faut d&#8217;abord choisir un connecteur. A la lecture de ce benchmark (cf.<a href="http://xmemcached.googlecode.com/svn/trunk/benchmark/benchmark.html"> http://xmemcached.googlecode.com/svn/trunk/benchmark/benchmark.html</a>), il semble que <a href="http://code.google.com/p/spymemcached/">spyMemCached</a> soit le plus performant.</p>
<p>Crééer un projet Maven en configurant votre pom de la façon suivante:</p>
<blockquote>
<pre>&lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;
 &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
 &lt;groupId&gt;fr.opensides&lt;/groupId&gt;
 &lt;artifactId&gt;Memcached&lt;/artifactId&gt;
 &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;

 &lt;repositories&gt;
 &lt;repository&gt;
 &lt;id&gt;spy&lt;/id&gt;
 &lt;name&gt;Spy Repository&lt;/name&gt;
 &lt;layout&gt;default&lt;/layout&gt;
 &lt;url&gt;http://bleu.west.spy.net/~dustin/m2repo/&lt;/url&gt;
 &lt;snapshots&gt;
 &lt;enabled&gt;false&lt;/enabled&gt;
 &lt;/snapshots&gt;
 &lt;/repository&gt;
 &lt;/repositories&gt;

 &lt;dependencies&gt;
 &lt;dependency&gt;
 &lt;groupId&gt;spy&lt;/groupId&gt;
 &lt;artifactId&gt;memcached&lt;/artifactId&gt;
 &lt;version&gt;2.4rc1&lt;/version&gt;
 &lt;/dependency&gt;
 &lt;/dependencies&gt;

&lt;/project&gt;</pre>
</blockquote>
<p>Ensuite crééer une classe Main en codant un simple ajout / recupération de clé dans un serveur MemCached</p>
<blockquote>
<pre><!-- p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco} p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px} p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #7f0055} p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #3f5fbf} p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #3f7f5f} span.s1 {color: #7f0055} span.s2 {color: #000000} span.s3 {color: #0000c0} span.s4 {color: #2a00ff} span.s5 {color: #7f9fbf} span.s6 {text-decoration: underline} span.Apple-tab-span {white-space:pre} -->
package fr.opensides.memcached;

import java.io.IOException;

public class Main { 

private static final String hostName = "localhost";

private static final int portNum = 11111;

public static void main(String[] args) throws IOException {

// Get a memcached client connected to several servers

MemcachedClient cache = new MemcachedClient(AddrUtil.getAddresses(hostName+":"+portNum));

// Store a value (async) for one hour

cache.set("myKey", 3600, new String("myValue"));

// Retrieve a value (synchronously).

Object myObject = cache.get("myKey");

System.out.println(myObject);

}

}</pre>
</blockquote>
<p>Le tour est joué, nous avons maitnenant un serveur MemCached démarré en écoute sur le port 11111 avec un exemple de programme faisant une opération d&#8217;ajout / récupération de données dans le cache.</p>
<p>Je vous conseille de poursuivre votre lecture dans la doc de MemCached et de l&#8217;api SpyMemCached pour aller plus loin.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.opensides.fr/2011/01/02/memcached-en-moins-de-5-minutes/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>LoadBalancing et Failover avec HAProxy en moins de 5 minutes</title>
		<link>http://www.opensides.fr/2010/10/03/loadbalancing-et-failover-avec-haproxy/</link>
		<comments>http://www.opensides.fr/2010/10/03/loadbalancing-et-failover-avec-haproxy/#comments</comments>
		<pubDate>Sun, 03 Oct 2010 19:26:17 +0000</pubDate>
		<dc:creator>ajeanson</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[clustering]]></category>
		<category><![CDATA[failover]]></category>
		<category><![CDATA[haproxy]]></category>
		<category><![CDATA[haute disponibilité]]></category>
		<category><![CDATA[loadbalancing]]></category>

		<guid isPermaLink="false">http://www.opensides.fr/?p=432</guid>
		<description><![CDATA[Dans cet article nous allons voir comment apporter très facilement une solution de haute disponibilité à une application avec HAProxy.
Quelques définitions
Haute disponibilité (cf. wikipedia)
La haute disponibilité est un terme souvent utilisé en informatique, à propos d&#8217;architecture de système ou d&#8217;un service pour désigner le fait que cette architecture ou ce service a un taux de [...]]]></description>
			<content:encoded><![CDATA[<p>Dans cet article nous allons voir comment apporter très facilement une solution de haute disponibilité à une application avec HAProxy.</p>
<h1>Quelques définitions</h1>
<p><strong>Haute disponibilité (cf. wikipedia)</strong></p>
<p><em>La <strong>haute disponibilité</strong> est un terme souvent utilisé en <a title="Informatique" href="http://fr.wikipedia.org/wiki/Informatique">informatique</a>, à propos d&#8217;architecture de système ou d&#8217;un service pour désigner le fait que cette architecture ou ce service a un taux de disponibilité convenable.</em></p>
<p><em>La disponibilité est aujourd&#8217;hui un enjeu important des infrastructures informatiques. On estime aujourd&#8217;hui que la non-disponibilité d&#8217;un service informatique peut avoir des coûts se chiffrant en millions<sup><a title="Modèle:Référence souhaitée/Explication" href="http://fr.wikipedia.org/wiki/Mod%C3%A8le:R%C3%A9f%C3%A9rence_souhait%C3%A9e/Explication"><abbr title="référence"></abbr></a></sup>, particulièrement dans le domaine de l&#8217;industrie où l&#8217;arrêt d&#8217;une chaîne de production peut avoir un effet dévastateur.</em></p>
<p><strong>HAProxy (cf.wikipedia)</strong><em><br />
</em></p>
<p><em><strong>HAProxy</strong> est un logiciel libre de <a title="Répartition de charge" href="http://fr.wikipedia.org/wiki/R%C3%A9partition_de_charge">répartition de charge</a> écrit par Willy Tarreau. Il est disponible sous <a title="Unix" href="http://fr.wikipedia.org/wiki/Unix">Unix</a> (on trouve très facilement des binaires précompilés pour <a title="Linux" href="http://fr.wikipedia.org/wiki/Linux">Linux</a><a title="Solaris" href="http://fr.wikipedia.org/wiki/Solaris">Solaris</a>).</em> et</p>
<p><em>HAProxy peut aider à mettre en place des solutions de hautes disponibilités, de répartition de charge et de <a title="Proxy" href="http://fr.wikipedia.org/wiki/Proxy">proxy</a> pour tous les types de protocole (TCP ou HTTP). Il est particulièrement bien adapté pour la gestion des très fortes charges sur un <a title="Site Web" href="http://fr.wikipedia.org/wiki/Site_Web">site Web</a> tout en gérant la notion de persistance ou la manipulation des données de la couche 7 du <a title="Modèle OSI" href="http://fr.wikipedia.org/wiki/Mod%C3%A8le_OSI">Modèle OSI</a>.</em></p>
<h1>Description de l&#8217;application</h1>
<p>Pour l&#8217;exemple, nous allons developper le classique HelloWorld, un WS-* dont le rôle va être de saluer l&#8217;internaute qui aura indiqué son nom en paramètre.</p>
<p>Voici la PI:</p>
<table border="1" cellspacing="1" cellpadding="1" width="100%">
<tbody>
<tr>
<td>MyService</p>
<ul>
<li>sayOla</li>
<li>sayHallo</li>
<li>sayHi</li>
<li>sayPriviet</li>
</ul>
</td>
<td>Endpoint address: http://localhost:8080/backend/MyService<br />
WSDL : <a href="http://localhost:8080/backend/MyService?wsdl">{http://backend.opensides.fr/}MyServiceImplService</a><br />
Target namespace: http://backend.opensides.fr/</td>
</tr>
</tbody>
</table>
<p>-&gt; ajoutons une petite spécificité au service de façon à ce qu&#8217;il renvoie le port de l&#8217;instance qui va traiter la demande de façon à déterminer facilement quel serveur aura traité la requête lorsque nous ferons un déploiement sur plusieurs instances.</p>
<p>ex: &laquo;&nbsp;<strong>(8080) &#8211; Hello John</strong>&nbsp;&raquo;</p>
<h1>Mise en place de HAProxy</h1>
<p>Voila le service est maintenant opérationnel. A ce stade, il fonctionne mais si le serveur tombe le service ne fonctionne plus. C&#8217;est là que HAProxy va intervenir. Nous allons deployer ce service sur plusieurs serveur et le rôle de HAProxy va être de jouer un peu le chef d&#8217;orchestre en:</p>
<p>- assurant une distribution des requêtes sur les différents serveurs (LOADBALANCING)</p>
<p>- Évincer une instance DOWN en transférant la charge sur les serveurs UP (FAILOVER)</p>
<p style="text-align: center;"><a href="http://www.opensides.fr/wp-content/uploads/2010/10/HaProxy1.jpg"><img class="aligncenter size-medium wp-image-451" title="HaProxy" src="http://www.opensides.fr/wp-content/uploads/2010/10/HaProxy1-300x224.jpg" alt="" width="486" height="362" /></a></p>
<h2>Installation &amp; configuration</h2>
<p><strong>Installation sur Mac</strong></p>
<blockquote>
<pre>sudo port install haproxy<strong>
</strong></pre>
</blockquote>
<p><strong>Installation sur Ubuntu</strong></p>
<blockquote>
<pre>sudo apt-get install haproxy</pre>
</blockquote>
<p><strong>Récupérer un exemple de fichier de configuration basic</strong></p>
<blockquote>
<pre>wget http://layer1.rack911.com/haproxy/haproxy-standard.cfg haproxy.cfg</pre>
</blockquote>
<p><strong>Editer le fichier de config:</strong></p>
<blockquote>
<pre>global
 maxconn     4096 # Total Max Connections. This is dependent on ulimit
 daemon
 nbproc      4 # Number of processing cores. Dual Dual-core Opteron is 4 cores for example.
 defaults
 mode        http
 clitimeout  60000
 srvtimeout  30000
 contimeout  4000
 option      httpclose # Disable Keepalive</pre>
<pre>listen  http_proxy <strong>127.0.0.1:9999</strong>
 balance roundrobin # Load Balancing algorithm
 option httpchk
 option forwardfor # This sets X-Forwarded-For</pre>
<pre><strong>## Define your servers to balance
 server server1 127.0.0.1:8080 weight 1 maxconn 512 check
 server server2 127.0.0.1:8181 weight 1 maxconn 512 check</strong></pre>
</blockquote>
<p><strong>Démarrer HaProxy</strong></p>
<blockquote>
<pre>haproxy -f haproxy.cfg<strong>

</strong></pre>
</blockquote>
<h2>Valider que la solution fonctionne</h2>
<p>Maintenant HAProxy est démarré. Il écoute les requetes sur le port 9999 et les redirige sur les 2 instances Tomcat 8080 et 81818.</p>
<p>Il suffit maintenant de lancer des requêtes sur les le port 9999 et observons que HAProxy redispacth bien les requêtes sur les 2 instances:<strong><br />
</strong></p>
<blockquote>
<pre>(<strong>8080</strong>) - Hello John (#287)
 1 oct. 2010 10:28:33 org.apache.cxf.service.factory.ReflectionServiceFactoryBean buildServiceFromClass
 INFO: Creating Service {http://pi.opensides.fr/}MyServiceService from class fr.opensides.pi.MyService
 (<strong>8080</strong>) - Hello John (#288)
 1 oct. 2010 10:28:33 org.apache.cxf.service.factory.ReflectionServiceFactoryBean buildServiceFromClass
 INFO: Creating Service {http://pi.opensides.fr/}MyServiceService from class fr.opensides.pi.MyService
 (<strong>8181</strong>) - Hello John (#252)
 1 oct. 2010 10:28:33 org.apache.cxf.service.factory.ReflectionServiceFactoryBean buildServiceFromClass
 INFO: Creating Service {http://pi.opensides.fr/}MyServiceService from class fr.opensides.pi.MyService
 1 oct. 2010 10:28:33 org.apache.cxf.service.factory.ReflectionServiceFactoryBean buildServiceFromClass
 INFO: Creating Service {http://pi.opensides.fr/}MyServiceService from class fr.opensides.pi.MyService
 (<strong>8181</strong>) - Hello John (#253)
 (<strong>8181</strong>) - Hello John (#254)
 1 oct. 2010 10:28:33 org.apache.cxf.service.factory.ReflectionServiceFactoryBean buildServiceFromClass
 INFO: Creating Service {http://pi.opensides.fr/}MyServiceService from class fr.opensides.pi.MyService
 (<strong>8080</strong>) - Hello John (#289)
 1 oct. 2010 10:28:33 org.apache.cxf.service.factory.ReflectionServiceFactoryBean buildServiceFromClass
 INFO: Creating Service {http://pi.opensides.fr/}MyServiceService from class fr.opensides.pi.MyService
 (<strong>8181</strong>) - Hello John (#255)</pre>
</blockquote>
<p>Nous pouvons observer les stats de l&#8217;interface d&#8217;amin HAProxy:</p>
<p><a href="http://www.opensides.fr/wp-content/uploads/2010/10/HA-interface1.jpg"><img class="alignnone size-medium wp-image-447" title="HA-interface" src="http://www.opensides.fr/wp-content/uploads/2010/10/HA-interface1-300x66.jpg" alt="" width="466" height="102" /></a></p>
<h1>Conclusion</h1>
<p>Nous avons vu comment installer et configurer HAProxy pour assurer Loadbalacong et failover sur un WS-*. Nous pouvons observer la puissance et la simplicité de l&#8217;outil.</p>
<p>Pour plus d&#8217;informations rendez-vous sur le site de l&#8217;éditeur http://haproxy.1wt.eu/</p>
]]></content:encoded>
			<wfw:commentRss>http://www.opensides.fr/2010/10/03/loadbalancing-et-failover-avec-haproxy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Gagner en performance en parallelisant ses traitements &#8230;</title>
		<link>http://www.opensides.fr/2010/04/23/gagner-en-performance-en-parallelisant-ses-traitements/</link>
		<comments>http://www.opensides.fr/2010/04/23/gagner-en-performance-en-parallelisant-ses-traitements/#comments</comments>
		<pubDate>Fri, 23 Apr 2010 22:39:11 +0000</pubDate>
		<dc:creator>ajeanson</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://www.opensides.fr/?p=404</guid>
		<description><![CDATA[La théorie
Parlons un peu de SEDA&#8230;
Bon encore un vague acronyme&#8230;Ça veut dire quoi au fait ? Staged Event Driven Architecture.
OK, encore un nouveau paradigme dans la mouvance DDD, TDD, MDA  &#8230; ? Ben pas vraiment nouveau en fait, ça fait 10 ans que ça existe et c&#8217;est Matt Welsh qui lance le mouvement dans la [...]]]></description>
			<content:encoded><![CDATA[<h1>La théorie</h1>
<p>Parlons un peu de SEDA&#8230;</p>
<p>Bon encore un vague acronyme&#8230;Ça veut dire quoi au fait ? <strong>S</strong>taged <strong>E</strong>vent <strong>D</strong>riven <strong>A</strong>rchitecture.</p>
<p>OK, encore un nouveau paradigme dans la mouvance DDD, TDD, MDA  &#8230; ? Ben pas vraiment nouveau en fait, ça fait 10 ans que ça existe et c&#8217;est Matt Welsh qui lance le mouvement dans la année 2000 avec une publication (cf. <a href="http://www.eecs.harvard.edu/~mdw/papers/events.pdf">http://www.eecs.harvard.edu/~mdw/papers/events.pdf</a>).</p>
<p>Heu en 2 mots c&#8217;est quoi le principe ? Bon l&#8217;idée c&#8217;est de créer des architectures scalables. OK&#8230;comment ?</p>
<p>C&#8217;est la que ça devient intéressant &#8230;</p>
<p><strong>Le principe est distinguer des &laquo;&nbsp;étapes&nbsp;&raquo;. Basiquement, on peut imaginer ces étapes comme étant les couches de notre architectures&#8230; Le principe est de faire communiquer ces couches de façon non-bloquantes en les faisant communiquer par des canaux dans lesquelles on publie des messages. De cette façon celui qui publie le message n&#8217;attend pas le retour et peut continuer son travail il sera avertit lorsque la réponse sera prête. </strong></p>
<p><strong>Comment ça marche ?</strong></p>
<p>Dans les architectures en couches, chacune des couches délèguent aux couches inférieures un certain nombre de traitements. Dans une architectures synchrone le demandeur (stage 1) attend la réponse de l&#8217;exécuteur (stage 2) avant de continuer son travail. Ici les choses sont différentes, le demandeur envoie des demandes d&#8217;exécutions à l&#8217;exécuteur qui va les traiter à son rythme pendant que le demandeur poursuivra son travail en parallèle le temps d&#8217;obtenir d&#8217;obtenir la réponse demandée. C&#8217;est le concept présenté par le pattern request-reply des EAI (cf. <a href="http://www.eaipatterns.com/RequestReply.html">http://www.eaipatterns.com/RequestReply.html</a>).</p>
<p>Voyons cela en image:</p>
<p><strong>Architecture synchrone</strong></p>
<p><a href="http://www.opensides.fr/wp-content/uploads/2010/04/standard-architecture.png"><img class="alignnone size-medium wp-image-410" title="standard-architecture" src="http://www.opensides.fr/wp-content/uploads/2010/04/standard-architecture-300x161.png" alt="" width="300" height="161" /></a></p>
<p>Ici, lorsque la couche A fait un appel à la couche B,  celle-ce reste bloquée en attente de réponse.</p>
<p><strong>Architecture asynchrone</strong></p>
<p><a href="http://www.opensides.fr/wp-content/uploads/2010/04/seda1.png"><img title="seda1" src="http://www.opensides.fr/wp-content/uploads/2010/04/seda1-300x147.png" alt="" width="300" height="147" /></a></p>
<p>Ici, la couche A publie une requête dans une canal de requête (request) et continue son cycle de vie pendant que la couche B traite en parallèle la requête. Une fois le traitement terminé, la couche B va publier la réponse dans un canal de réponse (reply). Le canal peut être une file d&#8217;attente JMS, une queue, une base de donnée, etc&#8230;</p>
<p>Les principaux intérêt de ce pattern résident dans la possibilité d&#8217;exécuter des tâches en parallèle et d&#8217;adapter facilement les producteurs/consommateurs en fonction de l&#8217;état des files d&#8217;attentes ce qui rend ce type d&#8217;architecture hautement scalable:</p>
<p><a href="http://www.opensides.fr/wp-content/uploads/2010/04/seda-scalable.png"><img class="alignnone size-medium wp-image-409" title="seda-scalable" src="http://www.opensides.fr/wp-content/uploads/2010/04/seda-scalable-300x156.png" alt="" width="300" height="156" /></a></p>
<h1>La pratique</h1>
<p>Aujourd&#8217;hui de nombreux acteurs proposent des implémentations de ce concept (Mule, Spring Integration, service Mix, &#8230;).</p>
<p>Je propose une petite librairie qui utilise des bloquing queue pour établir ses canaux de communication. C&#8217;est une classe abstraite qu&#8217;il suffit d&#8217;étendre pour permettre de paralléliser de façon asynchrone un traitement synchrone.</p>
<p><strong>Exemple d&#8217;un appel synchrone</strong></p>
<p>Prenons l&#8217;exemple d&#8217;une classe <strong>SampleSynchone</strong> qui fait appel à un service <strong><strong>VeryLongLegacyProcess</strong></strong> donnant la météo en fonction du jour passé en paramètre. Le temps d&#8217;exécution du service est de 5 secondes.</p>
<p>La classe appelante choisi de prendre un parapluie ou une casquette en fonction du temps. Une première implémentation donnerait le code suivant:</p>
<p><span style="text-decoration: underline;">La classe SampleSynchone:</span></p>
<blockquote>
<pre>public class SampleSynchrone {

 <strong>VeryLongLegacyProcess</strong> veryLongProcess = new VeryLongLegacyProcess();

 public void howDoIDress(EDay day) throws InterruptedException{
 EWeather weather = <strong>veryLongProcess.whatTheWeather(day);</strong> //1 seconde
 String clothe = "";
 if (EWeather.RAINNY.equals(weather)){
 clothe = "umbrella";
 }else{
 clothe = "cap";
 }
 System.out.println(day+" I will take my "+clothe);
 }
}
</pre>
</blockquote>
<p><span style="text-decoration: underline;">La classe Main qui va appeler le traitement:</span></p>
<blockquote>
<pre>public class Main {

 public static void main (String[] args){
 System.out.println("current time:"+System.currentTimeMillis());

 LayerA layerA = new LayerA();
 layerA.howDoIDress(EDay.MONDAY);
 layerA.howDoIDress(EDay.TUESDAY);
 layerA.howDoIDress(EDay.WEDNESDAY);
 layerA.howDoIDress(EDay.THURSDAY);
 layerA.howDoIDress(EDay.FRIDAY);

}
</pre>
</blockquote>
<p><span style="text-decoration: underline;">Execution</span></p>
<blockquote>
<pre>current time:1272183941674
MONDAY I will take my umbrella(current time:1272183946682)
TUESDAY I will take my cap(current time:1272183951682)
WEDNESDAY I will take my umbrella(current time:1272183956683)
THURSDAY I will take my cap(current time:1272183961683)
FRIDAY I will take my umbrella(current time:1272183966683)

<strong>job execution: 25 009 ms</strong>
</pre>
</blockquote>
<p><strong>=&gt; L&#8217;exécution du traitement pour chacun des jours de la semaine prend 25 secondes (5 fois 5 secondes).</strong></p>
<p><strong>Exemple Asynchrone</strong></p>
<p>Nous allons maintenant essayer de réduire la fenêtre temporelle de la classe main en parallélisant les appels au service en étendant la classe <a href="https://sourceforge.net/projects/parallelizable/"><em><strong>Parallelizable</strong></em></a>.<strong> </strong></p>
<p><span style="text-decoration: underline;">La classe parallelisable:</span></p>
<blockquote>
<pre>public class Sample extends <strong>Parallelizable</strong>&lt;EDay, EWeather&gt;{

 <strong>VeryLongLegacyProcess</strong> veryLongLegacyProcess = new VeryLongLegacyProcess();

 public Sample(int <strong>nbExecutors</strong>) throws InstantiationException,
 IllegalAccessException, IllegalArgumentException,
 SecurityException, InvocationTargetException, NoSuchMethodException {
 super(nbExecutors);
 }

 <strong>@Override
 public void callback(Reply&lt;EDay, EWeather&gt; reply) </strong>{
 String clothe = "";
 if (EWeather.RAINNY.equals(reply.getOut())){//using results for next process
 clothe = "umbrella";
 }else{
 clothe = "cap";
 }
 System.out.println(reply.getIn()+" I will take my "+clothe);//using input parameters        
 }

 <strong>@Override
 public EWeather processRequest(EDay in) throws InterruptedException {</strong>
 return veryLongLegacyProcess.whatTheWeather((EDay)in);
 }

}
</pre>
</blockquote>
<p><span style="text-decoration: underline;">La classe Main qui va appeler le traitement:</span></p>
<blockquote>
<pre>public class Main {
 public static void main (String[] args){</pre>
<pre> System.out.println("current time:"+System.currentTimeMillis());</pre>
<pre> <strong>Sample sample = new Sample(5);</strong></pre>
<pre> sample.<strong>request</strong>(EDay.MONDAY);</pre>
<pre> sample.request(EDay.TUESDAY);</pre>
<pre> sample.request(EDay.WEDNESDAY);</pre>
<pre> sample.request(EDay.THURSDAY);</pre>
<pre> sample.request(EDay.FRIDAY);</pre>
<pre>
<pre>}}</pre>
</pre>
</blockquote>
<p><span style="text-decoration: underline;">Execution</span></p>
<blockquote>
<pre>current time:1272184056048
WEDNESDAY I will take my umbrella(current time:1272184061059)
FRIDAY I will take my umbrella(current time:1272184061059)
THURSDAY I will take my cap(current time:1272184061059)
TUESDAY I will take my cap(current time:1272184061059)
MONDAY I will take my umbrella(current time:1272184061059)
<pre><strong><strong>job execution: 5 011 ms
</strong></strong></pre>
</pre>
</blockquote>
<p>La classe <em><strong>Parallelizable </strong></em>va créer un pool de threads exécuteurs, donnée en paramètre au niveau du constructeur (<strong>Sample sample = new Sample(5);</strong><strong><strong>)</strong>. </strong>Ces threads seront mis en écoute à la première requête publiée dans le canal de requête (avec la méthode request (sample.<strong>request</strong>(EDay.MONDAY)). Chacun des thread va dépiler les messages envoyés et les traiter. La réponse sera ensuite publiée dans un canal de réponse, dépilée et envoyée dans la méthode callback qui permettra de terminer le traitement en choisissant le vêtement approprié.</p>
<p><strong>=&gt; L&#8217;exécution du traitement pour chacun des jours de la semaine prend cette fois 5 secondes du fait de leur exécution parallèle.</strong></p>
<p>L&#8217;exemple, la librairie et les sources sont publiés sous la licence Apache V2 sur Source Forge <a href="https://sourceforge.net/projects/parallelizable/">https://sourceforge.net/projects/parallelizable/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.opensides.fr/2010/04/23/gagner-en-performance-en-parallelisant-ses-traitements/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Thread analysis</title>
		<link>http://www.opensides.fr/2010/03/27/thread-analysis/</link>
		<comments>http://www.opensides.fr/2010/03/27/thread-analysis/#comments</comments>
		<pubDate>Sat, 27 Mar 2010 00:00:10 +0000</pubDate>
		<dc:creator>ajeanson</dc:creator>
				<category><![CDATA[Non classé]]></category>

		<guid isPermaLink="false">http://ks301089.kimsufi.com/wordpress/?p=364</guid>
		<description><![CDATA[The Thread Dump is a photograph taken at T time of all threads acyivity in the application server. They are displayed one after the other as a stack trace. This photograph of the JVM state allow us to analyze the deadlock between threads.

1/ Find java process (PID)
ps aux  &#124; grep java
or
ps auxwww &#124; grep java
or
jps -v [...]]]></description>
			<content:encoded><![CDATA[<p>The Thread Dump is a photograph taken at T time of all threads acyivity in the application server. They are displayed one after the other as a stack trace. This photograph of the JVM state allow us to analyze the deadlock between threads.</p>
<div>
<p><strong>1/ Find java process (PID)</strong></p>
<p>ps aux  | grep java</p>
<p>or</p>
<p>ps auxwww | grep java</p>
<p>or</p>
<p>jps -v | grep -iv jps</p>
<p><strong>2/ Trigger the thread dump</strong></p>
<p>kill -3 &lt;PID&gt;</p>
<p>(NB: The output is then led directly into the server logs)</p>
<p><strong>3/ Thread dump analysis</strong></p>
<p>Once your thread dump generated (in the server logs), 2 effective tools help you for the analysis phase:</p>
<ul>
<li>TDA: Thread Dump Analyzer (see https: / / tda.dev.java.net /)</li>
<li>Lockness Eclipse Plugin – Java Thread Dump Analyzer, an eclipse plugin that analyzes your thread dumps and this form of list. (Http://lockness.plugin.free.fr/home.php)</li>
</ul>
<p>For additional informations about thread dumps:<br />
An Introduction to Java Stack Traces (cf. http://java.sun.com/developer/technicalArticles/Programming/Stacktrace/)<br />
Thread Dump and Concurrency Locks jstack presentation tools and the jconsole jdk 5 (cf. http://weblogs.java.net/blog/mandychung/archive/2005/11/thread_dump_and_1.html/)</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.opensides.fr/2010/03/27/thread-analysis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PermGen out of memory errors &#8230;</title>
		<link>http://www.opensides.fr/2010/03/26/permgen-out-of-memory-errors/</link>
		<comments>http://www.opensides.fr/2010/03/26/permgen-out-of-memory-errors/#comments</comments>
		<pubDate>Fri, 26 Mar 2010 13:45:26 +0000</pubDate>
		<dc:creator>ajeanson</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[Memory]]></category>
		<category><![CDATA[outofmemory]]></category>
		<category><![CDATA[permgen]]></category>

		<guid isPermaLink="false">http://www.opensides.fr/?p=324</guid>
		<description><![CDATA[Dans un post précédent, nous avons vu le fonctionnement de la JVM (cf. http://www.opensides.fr/?p=271). Aujourd&#8217;hui nous allons voir à quoi sert la zone PermGen et surtout comment éviter les erreurs de type PermGen OutOfMemory..
C&#8217;est quoi la PermGen ?
La PermGen est un segment de mémoire dans laquelle sont stockés le bytecode et les type primitifs lors [...]]]></description>
			<content:encoded><![CDATA[<p>Dans un post précédent, nous avons vu le fonctionnement de la JVM (cf. <a href="http://www.opensides.fr/?p=271">http://www.opensides.fr/?p=271</a>). Aujourd&#8217;hui nous allons voir à quoi sert la zone PermGen et surtout comment éviter les erreurs de type PermGen OutOfMemory..</p>
<p><strong>C&#8217;est quoi la PermGen ?</strong></p>
<p>La PermGen est un segment de mémoire dans laquelle sont stockés le bytecode et les type primitifs lors chargement de l&#8217;application. Cette zone mémoire contient donc l&#8217;ensemble des classes permettant à la JVM de créer les instances à partir de ces classes. (la voici tout à gauche sur le schéma).</p>
<p><a href="http://www.opensides.fr/wp-content/uploads/2010/03/jvm4.png"><img class="alignnone size-medium wp-image-377" title="jvm" src="http://www.opensides.fr/wp-content/uploads/2010/03/jvm4-236x300.png" alt="" width="236" height="300" /></a></p>
<p>Cette zone est donc chargée une fois lors du déploiement de l&#8217;application, c&#8217;est ensuite la Heap (Young et Old) qui seront sollicité pendant le cycle de vie de l&#8217;application.</p>
<p><strong>C&#8217;est quoi un OutOfMemory error ?</strong></p>
<p>A chaque nouveau déploiement, les nouvelles classes sont chargées dans la PermGen et il arrive parfois (souvent ?) que cette zone mémoire sature en nous affichant alors le message bien connu:</p>
<blockquote><p>java.lang.OutOfMemoryError: PermGen space</p></blockquote>
<p><strong>Comment résoudre ce problème ?</strong></p>
<p>Une première optimisation consisterait à augmenter la taille de cette zone:</p>
<blockquote><p><strong>-XX:PermSize=128m</strong></p></blockquote>
<p>C&#8217;est très pratique mais ça ne fait que repousser le problème <img src='http://www.opensides.fr/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Nous avons vu que le garbage Collector n&#8217;intervient que sur le tas (la Heap) mais jamais sur la zone PermGen. Voici donc 2 options qui permettent d&#8217;activer le Garbage sur la heap en cas de saturation mémoire.</p>
<blockquote><p><strong>-XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled</strong></p></blockquote>
<p>Je n&#8217;ai rien trouvé dans la doc officielle de Sun sur l&#8217;explication précise de ces options,  juste des votes pour qu&#8217;elles soit intégrées par défaut dans les prochaines version de la JVM (peut être dans la Dolphin): http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6329603</p>
]]></content:encoded>
			<wfw:commentRss>http://www.opensides.fr/2010/03/26/permgen-out-of-memory-errors/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Optimisation des ressources dans une application SOA</title>
		<link>http://www.opensides.fr/2010/03/25/optimisation-des-ressources-dans-une-application-soa/</link>
		<comments>http://www.opensides.fr/2010/03/25/optimisation-des-ressources-dans-une-application-soa/#comments</comments>
		<pubDate>Thu, 25 Mar 2010 22:15:00 +0000</pubDate>
		<dc:creator>ajeanson</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[resources]]></category>
		<category><![CDATA[softreference]]></category>

		<guid isPermaLink="false">http://www.opensides.fr/?p=315</guid>
		<description><![CDATA[Introduction
Une architecture SOA a pour principe d’exposer un ensemble de services à destination des utilisateurs. Ces services peuvent éventuellement être relayés par ces mêmes utilisateurs qui peuvent les décorer de nouvelles fonctionnalités. Un des facteurs critique de ce genre d’architecture est la «scalabilité». C’est à dire que le système doit pouvoir répondre linéairement à une [...]]]></description>
			<content:encoded><![CDATA[<h1>Introduction</h1>
<p>Une architecture SOA a pour principe d’exposer un ensemble de services à destination des utilisateurs. Ces services peuvent éventuellement être relayés par ces mêmes utilisateurs qui peuvent les décorer de nouvelles fonctionnalités. Un des facteurs critique de ce genre d’architecture est la «scalabilité». C’est à dire que le système doit pouvoir répondre linéairement à une charge de requêtes croissante.</p>
<p>Pour garantir une bonne scalabilité, l’enjeu est d’optimiser les ressources matérielles (calcul, mémoire, i/o) de façon à servir toutes les requêtes.</p>
<p>Conséquence d’une mauvaise gestion des ressources:</p>
<ul>
<li>dégradation des temps de réponses</li>
<li>rejet des requêtes utilisateur</li>
<li>effondrement du serveur par manque de mémoire (il faudra 	alors l’intervention manuelle des nos amis les administrateurs IT 	pour les redémarrer).</li>
</ul>
<h1>Objectif</h1>
<p>Cet article a pour objectif de montrer comment optimiser les performances de notre service en donnant quelques pistes pour une bonne gestion des ressources au sein de notre architecture.</p>
<h1>Petite piqûre de rappel</h1>
<p>Rendez-vous aux pages suivantes pour un rappel sur les ressources matérielles: <a href="http://www.opensides.fr/?p=293">http://www.opensides.fr/?p=293</a></p>
<p>Et sur le fonctionnement d’une JVM (hotspot): <a href="http://www.opensides.fr/?p=271">http://www.opensides.fr/?p=271</a></p>
<p><!-- @page { margin: 2cm } 		P { margin-bottom: 0.21cm } 		A:link { so-language: zxx } -->Maintenant que nous maîtrisons ces bases, voyons comment ces ressources sont sollicitées aux travers d’un cas pratique.</p>
<h1>Cas pratique</h1>
<p>Pour illustrer la gestion des ressources, nous allons prendre l’exemple d’un musée. Ce musée représentera notre application. Des visiteurs formeront une file d’attente à l’entrée pour acheter leur ticket. Il représenteront les requêtes utilisateurs qui attendent d’acquérir une connexion au système. Lorsqu’un visiteur achètera son ticket, un agent lui préparera un casque d’écoute. Ce casque représentera l’accès à un service externe et la préparation par l’agent, l’acquisition de cette ressource. Le visiteur pourra alors faire sa visite avec son casque.</p>
<h2>Voici le déroulement de la séquence:</h2>
<ol>
<li>les visiteurs forment une file 	d’attente à l’entrée du musée (&gt; requête au système)</li>
<li>le visiteur  arrive au 	guichet, il achète son ticket (&gt; connexion au serveur, le 	processeur (guichet) est sollicité et le visiteur entre dans le 	musée donc la mémoire est consommée)</li>
<li>le guichet prend alors un casque 	dans un sac (&gt; récupération de la ressource à partir de la 	mémoire morte, le sac peut être une base de donnée par exemple)</li>
<li>le guichet initialise et le donne 	au visiteur (&gt; la processeur est sollicité pour initialise un 	Web Service et utilise les I/O pour l’acquisition de la connexion)</li>
<li>le client possède son casque et 	peut donc faire sa visite guidée pour une durée aléatoire (&gt; 	utilisation du service)</li>
<li>il interrompt ensuite sa visite mais ne sort pas du musée et 	ne rend pas son casque (pas bien…)</li>
</ol>
<h2>Précisions:</h2>
<ul>
<li>le musée ne possède qu’un seul 	guichet qui est en charge de délivrer les tickets et de distribuer 	les casques aux visiteurs (&gt; un thread gérant une fille 	d’attente)</li>
<li>la récupération du casque oblige 	le guichetier à fouiller dans un sac et représente donc une 	opération longue  (1 minute) (&gt;occupation du thread pour 	acquérir la connexion à la base de donnée)</li>
<li>l’initialisation du casque est 	aussi une opération longue (2 minute) pendant laquelle le guichet 	ne peut servir les autres visiteurs (&gt;occupation du thread pour 	acquérir la connexion au WS externe)</li>
<li>un casque coûte 10$ (&gt;  	empreinte mémoire de l’objet (1024*1024 byte))</li>
<li>chaque client ne rend pas 	systématiquement son casque à la sortie,  il le laisse dans 	une salle du musée  (&gt; non relâchement des objets,  	fuite mémoire)</li>
<li>le musée possède 1000 casques 	(&gt;taille de la zone Eden dans la JVM)</li>
<li>le musé à une capacité d’accueil de 1000 visiteurs 	simultanés (&gt;capacité mémoire du système)</li>
</ul>
<h2>Limites du système actuel</h2>
<ul>
<li>pour chaque visiteur le guichet 	doit prendre un casque dans un sac ce qui fait perdre 1 minute à 	l’ensemble des visiteurs</li>
<li>le guichet initialise ensuite le 	casque ce qui fait à nouveau perdre 2 minutes à l’ensemble de la 	file d’attente</li>
<li>les visteurs ne ressortent pas du 	musée (&gt;fuite mémoire potentielle)</li>
<li>les visteurs ne rendent ps leur casque (&gt;fuite mémoire 	potentielle)</li>
</ul>
<h2>Passons à la pratique</h2>
<p>Lançons l’application pour en observer le fonctionnement:</p>
<pre>[0 ms] Le visiteur #1  achète un ticket
[3 ms] Le guichetier récupère le casque #1 ...
<strong>[1000 ms] Le guichetier initialise le casque #1 ...</strong>
<strong>[2001 ms] Le visiteur #1  prend le casque le casque #1</strong>
[0 ms] Le visiteur #1 entre dans le musée
[1 ms] Le visiteur #2  achète un ticket
[0 ms] Le visiteur #1  commence sa visite ...
[3 ms] Le guichetier récupère le casque #2 ...
<strong>[1000 ms] Le guichetier initialise le casque #2 ...</strong>
<strong>[2000 ms] Le visiteur #2  prend le casque le casque #2</strong>
[0 ms] Le visiteur #2 entre dans le musée
[0 ms] Le visiteur #3  achète un ticket
[1 ms] Le visiteur #2  commence sa visite ...
[1 ms] Le guichetier récupère le casque #3 ...
<strong>[1000 ms] Le guichetier initialise le casque #3 ...</strong>
<strong>[2000 ms] Le visiteur #3  prend le casque le casque #3</strong>
[1 ms] Le visiteur #3 entre dans le musée
[0 ms] Le visiteur #3  commence sa visite ...
[0 ms] Le visiteur #4  achète un ticket
[707 ms] Le visiteur #2  arrête sa viste
...
[1001 ms] Le guichetier initialise le casque #79 ...
[1000 ms] Le visiteur #79  prend le casque le casque #79
[0 ms] Le visiteur #79 entre dans le musée
[0 ms] Le visiteur #79  commence sa visite ...
[0 ms] Le visiteur #80  achète un ticket
<strong>Exception in thread "main" java.lang.OutOfMemoryError: Java heap space</strong>
<strong> at fr.opensides.lab.musee1.Guichetier.accueilVisiteur(Guichetier.java:16)</strong>
<strong> at fr.opensides.lab.musee1.Main.main(Main.java:11)</strong>
[322 ms] Le visiteur #75  arrête sa viste
[3248 ms] Le visiteur #79  arrête sa viste
[3 ms] Le visiteur #77  arrête sa viste
[1527 ms] Le visiteur #78  arrête sa viste</pre>
<p>On remarque sans surprise que l’initialisation des casques est très coûteuse ( 1 seconde pour la récupération / 2 secondes pour l’initialisation) et surtout systématique. Elle pénalise donc l’ensemble de la file d’attente.</p>
<p>Penchons nous maintenant sur la mémoire. Pour cela, ouvrons un VisualVM et regardons la gestion de la heap. (cf. ci-dessous)</p>
<h2><a href="http://www.opensides.fr/wp-content/uploads/2010/03/musee0et1_memory_leak2.png"><img class="alignnone size-medium wp-image-343" title="musee0et1_memory_leak" src="http://www.opensides.fr/wp-content/uploads/2010/03/musee0et1_memory_leak2-300x159.png" alt="" width="300" height="159" /></a></h2>
<p>On observe que les Garbage Collector (GC) représenté sur le graph par des creux sont réguliers, ce qui est normal mais ne sont pas profond, ce qui l’est moins… Cela indique que le GC est inefficace car il ne parvient pas à récupérer de la mémoire.</p>
<p><strong>Conséquences</strong></p>
<pre><strong>&gt;Le musée est saturé à 80 visiteurs et nous renvoie l'erreur ci-dessous:</strong>
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
 at fr.opensides.lab.musee1.Guichetier.accueilVisiteur(Guichetier.java:16)
 at fr.opensides.lab.musee1.Main.main(Main.java:11)</pre>
<p><strong>Explication: qu’est ce qu’une fuite mémoire ?</strong></p>
<p>C’est le pattern typique d’une fuite mémoire, la JVM ne parvient pas à relâcher les objets car ils sont référencés (en référence forte) par les visiteurs. La mémoire va donc se remplir jusqu’à saturation( palier en haut de la courbe), ce qui se traduit par le message ci-dessus.</p>
<p>Dans notre exemple, le gardien du musée (la JVM) interrompt le travail du guichetier pour aller chercher les casques dans le musée (Garbage Collector).<br />
Le problème c’est que lorsqu’il trouve un casque il n’a aucun moyen de savoir si le casque est en cours d’utilisation par un visiteur. Dans le doute, il ne peut pas le récupérer car le casque appartient au visiteur (référence forte), il le laisse donc à sa place et les casques s’accumulent dans le musée.</p>
<h2>1 ère optimisation: relâcher les objets</h2>
<p>Quels sont les objet qui encombrent le musée ? Les casques et les visiteurs. Il faut donc les faire sortir pour corriger notre fuite mémoire.</p>
<p>Cela nous semble logique dans un cas de la vie réel mais étrangement cela parait beaucoup moins intuitif en programmation..</p>
<p><strong>Comment faire ?</strong></p>
<p>A la fin de la visite, nous allons simplement demander au visiteur de :</p>
<p>1/ rendre leur casque:</p>
<p>–&gt; en pratique on remet le casque à null</p>
<p>2/ de sortir du musée:</p>
<p>-&gt; en pratique ils se supprime de la map « Musée » au niveau de la méthode « interrupt » du thread visteur:</p>
<pre>getMusee().remove(this.getId());//le visiteur sort du musée</pre>
<p><strong>Conséquence:<br />
</strong>La fuite mémoire est corrigée, le musée ne sature plus.</p>
<p><a href="http://www.opensides.fr/wp-content/uploads/2010/03/muse1-solveLeakMemory.png"><img class="alignnone size-medium wp-image-329" title="muse1-solveLeakMemory" src="http://www.opensides.fr/wp-content/uploads/2010/03/muse1-solveLeakMemory-300x166.png" alt="" width="300" height="166" /></a></p>
<h2>2 ème optimisation: préparation des casques (mise en place d’un mécanisme de cache)</h2>
<p>Il reste un problème de lenteur au niveau de la récupération l’initialisation des casque. Pour réduire ce temps d’attente des visiteurs, l’agent peut sortir à l’avance un ensemble de casques de son sac, les initialiser et les disposer sur un présentoir de façon à les distribuer plus rapidement<strong>.</strong></p>
<ul>
<li>Utilisation d’un présentoir 	(cache en SoftReference)</li>
<li>Le visiteur remet son casque sur le présentoir (cache en 	SoftReference)</li>
</ul>
<p><strong>Conséquence:</strong></p>
<p>L’utilisation du présentoir permet de réduire considérablement les temps d’attentes des visteurs. Malgré le fait que les visteurs ne renden pas relement leur casque car ils sont référencés dans le cache, le cache en SoftRéférence permet de relâcher les objets lorsque la mémoire sature.</p>
<pre>Le guichetier prend un casque sur son présentoir [0 ms]
[0 ms] Le visiteur #244  prend le casque le casque #244
[0 ms] Le visiteur #243  commence sa visite ...
[0 ms] Le visiteur #244 entre dans le musée
[0 ms] Le visiteur #245  achète un ticket
Le guichetier prend un casque sur son présentoir [0 ms]
[1 ms] Le visiteur #245  prend le casque le casque #245
[0 ms] Le visiteur #244  commence sa visite ...
[1 ms] Le visiteur #245 entre dans le musée
[0 ms] Le visiteur #246  achète un ticket
Le guichetier prend un casque sur son présentoir [0 ms]
[1 ms] Le visiteur #246  prend le casque le casque #246
[0 ms] Le visiteur #245  commence sa visite ...
[1 ms] Le visiteur #246 entre dans le musée
[0 ms] Le visiteur #247  achète un ticket
Le guichetier prend un casque sur son présentoir [0 ms]
[2 ms] Le visiteur #247  prend le casque le casque #247
[1 ms] Le visiteur #246  commence sa visite ...
[3 ms] Le visiteur #247 entre dans le musée
[0 ms] Le visiteur #248  achète un ticket
[0 ms] Le visiteur #247  commence sa visite ...
[0 ms] Le visiteur #240  commence sa visite ...
[51 ms] Le visiteur #238  rend dépose le casque sur le présentoir
[64 ms] Le visiteur #198  rend dépose le casque sur le présentoir</pre>
<p>&gt;L’application tourne en continue sans saturation</p>
<p>Mémoire</p>
<p><a href="http://www.opensides.fr/wp-content/uploads/2010/03/musee2_memoire1.png"><img class="alignnone size-medium wp-image-328" title="musee2_memoire" src="http://www.opensides.fr/wp-content/uploads/2010/03/musee2_memoire1-300x155.png" alt="" width="300" height="155" /></a></p>
<p>On observe que la heap se remplie jusqu&#8217;à atteindre son seuil max. Proche du max, les SoftReference joue leur rôle en permettant à la JVM de libérer les objets au lieu d&#8217;atteindre le max (générant une OOME).</p>
<p>cpu</p>
<p><a href="http://www.opensides.fr/wp-content/uploads/2010/03/musee2_cpu.png"><img class="alignnone size-medium wp-image-253" title="musee2_cpu" src="http://www.opensides.fr/wp-content/uploads/2010/03/musee2_cpu-300x167.png" alt="" width="300" height="167" /></a></p>
<p>On voit que ce mécanisme à un coût en terme de GC (en bleu l&#8217;activité cpu liée au GC).</p>
<p>thread</p>
<p><a href="http://www.opensides.fr/wp-content/uploads/2010/03/musee2_thread.png"><img class="alignnone size-medium wp-image-254" title="musee2_thread" src="http://www.opensides.fr/wp-content/uploads/2010/03/musee2_thread-300x168.png" alt="" width="300" height="168" /></a></p>
<p>Au bout de 14 minutes, 10377 threads on pu être traités par l&#8217;application. Soit autant de visiteurs on pu visiter le musée.</p>
<p><strong>Remarques:</strong><br />
On remarque une augmentation de la heap jusqu’à se rapprocher du max. C’est la SoftReference qui fait bien son job en permettant de relacher les objets quand la mémoire sature.<br />
Il est important de noter que ce fonctionnement a un cout. Cette fois c’est la processeur<br />
qui travaille en déplaçant les objets de la heap vers la perm et en relaçhant les objets (cf. cpu)</p>
<p><strong>Explication</strong></p>
<p>Cette opération consiste à utiliser un <a href="http://fr.wikipedia.org/wiki/M%C3%A9moire_cache">pool</a> (ou <a href="http://fr.wikipedia.org/wiki/M%C3%A9moire_cache">cache</a>) représenté par le comptoir qui permet d’éviter de répéter les opérations coûteuses de connexion à la base de donnée. On parle dans ce cas de « cacher » les informations pour les rendre accessible plus rapidement lors des prochaines utilisations. Dans notre exemple, le présentoir aura une capacité limité à 100 casques. Ce qui implique que le guichetier devra nettoyer régulièrement son présentoir.</p>
<p>Il devra donc gérer les problématiques suivantes:</p>
<ul>
<li>lorsque les visteurs auront pris 	l’ensemble des casques il devra à nouveau récupérer les casques 	dans le sac et les initialiser</li>
<li>lorsque un visiteur quittera le 	musée rendra son casque sur la table il pourra le redistribuer à 	un autre visiteur</li>
<li>lorsque la table sera pleine de casque les anciens casques 	présents sur la table seront remis dans le sac</li>
</ul>
<p>La technique que nous utiliserons pour implémenter cet exemple est un <a href="http://fr.wikipedia.org/wiki/M%C3%A9moire_cache">pool</a> qui aura pour caractéristique de libérer les ressources les moins récemment utilisées. Ce type d’algorithme de relâchement des ressources est appellé <strong><a href="http://fr.wikipedia.org/wiki/Algorithmes_de_remplacement_des_lignes_de_cache#LRU_.28Least_Recently_Used.29">LRU</a></strong> pour <strong>Last Recently Used</strong> (cf. http://fr.wikipedia.org/wiki/Algorithmes_de_remplacement_des_lignes_de_cache#LRU_.28Least_Recently_Used.29).</p>
<h3><strong>Les références Java pour les nuls</strong></h3>
<p>Il existes différents types de références selon leur degrés d’attachement (ici classés du plus fort au moins fort) (cf. http://blog.developpez.com/adiguba/p2107/java/comprendre-les-references-en-java/):</p>
<ul>
<li><strong>les références fortes</strong> (strong reference): C’est la référence par défaut. L’objet 	est lié fortement à l’autre comme c’est le cas actuellement 	avec nos casques du fait que le visteur paye la location de son 	casque il ya une notion d’appartenance au moment de la visite. Le 	guichetier à ce titre ne peut pas décider de récupérer le casque 	qu’il trouve car il pénaliserait le visteur si celui-ci l’utilise 	encore</li>
<li><strong>les références</strong> <strong>douces</strong> (soft reference, cf. <strong><a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ref/SoftReference.html">SoftReference</a></strong>): 	une référence douce indique à la jvm que celle-ci peut supprimer 	l’objet si le besoin s’en fait sentir. Dans notre exemple cela 	s’apparenterait au fait de prêter le casque au lieu de le louer. 	Dans ce cas l’utilisation du casque n’est pas nominative, les 	casques sont laissés dans le musée (seulement) lorsque le 	guichetier n’a plus de casque disponible il peut récupérer sans 	remord l’ensemble des casques présents dans le musée partant du 	principe qu’ils n’appartienne pas aux viseurs.</li>
<li><strong>les références</strong> <strong>faible</strong> (weak reference, cf. <strong><a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ref/WeakReference.html">WeakReference</a></strong>): 	une référence faible permet de stocker une référence, mais ne 	permettent pas d’assurer a elle seule que l’objet stocké sera 	conservé en mémoire. Les références faibles permettent ainsi de 	faire dépendre la durée de vie d’un objet par rapport à la 	validité d’un autre objet. Dans notre exemple, lorsque le 	visiteur n’est plus présent, le casque est automatiquement 	récupéré par le guichetier.</li>
<li><strong>les références</strong> <strong>fantômes</strong> (phantom reference, cf. <strong><a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ref/PhantomReference.html">PhantomReference</a></strong>): 	<em>les références fantômes sont un peu particulières dans le 	sens où leur méthode </em><strong>get()</strong><em> renverra 	toujours </em><strong>null</strong><em>. En effet l’objectif des 	références fantômes est d’être avertis de la suppression 	complète d’un objet par le </em><strong>GC</strong><em>. En 	effet, contrairement aux </em><strong>WeakReference</strong><em> et </em><strong>SoftReference</strong><em> qui sont « invalidées » 	dès que commence le processus de libération les </em><strong>PhantomReferences</strong><em> ne sont ajoutées à la </em><strong>ReferenceQueue</strong><em> associée que lorsque l’objet référencé est complètement 	supprimé de la mémoire (cela permet d’éviter des 	« résurrections obscures » d’objets dans la méthode </em><strong>finalize()</strong><em>). </em>Bon il va falloir un peu 	d’imagination pour intégrer ce type de référence dans notre 	exemple mais pour le moment elle ne nous sera pas utile.</li>
</ul>
<p>Nous avons vu que le cache en SoftReference permettait de libérer les objets lorsque la mémoire sature. Cette solution est pratique car elle évite les OOME mais n&#8217;est pas optimale puisqu&#8217;elle génére une forte activité de Garbage Collection pour libérer les ressources.</p>
<h2>3 ème optimisation: rendre les casques à la fin de la visite (retour des objets dans le pool)</h2>
<p>Nous avons pu constater plus haut une ofrte activité du GC pour libérer les ressources du pool. Pour éviter ce problème il suffit de retourner les objets dans le pool en demandant aux visteurs de reposer leur casque sur le présentoir à la fin de la visite.</p>
<blockquote><p>//On remet le casque dans le pool pour éviter un overhead cpu lors de la libération des SoftReference au moment du garbage<br />
presentoire.returnObject(this.get(key).getCasque());</p></blockquote>
<p><strong>Conséquence</strong></p>
<p>Le résultat est assez spectaculaire</p>
<p><a href="http://www.opensides.fr/wp-content/uploads/2010/03/musee3-cpu1.png"><img class="alignnone size-medium wp-image-393" title="musee3-cpu" src="http://www.opensides.fr/wp-content/uploads/2010/03/musee3-cpu1-300x173.png" alt="" width="300" height="173" /></a></p>
<p>On remarque que l&#8217;activité du garbage a considérablement baissé. L&#8217;activité CPU est maintenant mobilisée sur l&#8217;application.</p>
<p><a href="http://www.opensides.fr/wp-content/uploads/2010/03/musee3-memory.png"><img class="alignnone size-medium wp-image-394" title="musee3-memory" src="http://www.opensides.fr/wp-content/uploads/2010/03/musee3-memory-300x172.png" alt="" width="300" height="172" /></a></p>
<p>Niveau mémoire, on remarque des GC réguliers sans saturation.</p>
<p><a href="http://www.opensides.fr/wp-content/uploads/2010/03/musee3_thread.png"><img class="alignnone size-medium wp-image-395" title="musee3_thread" src="http://www.opensides.fr/wp-content/uploads/2010/03/musee3_thread-300x174.png" alt="" width="300" height="174" /></a></p>
<p>Au bout de 10 minutes, l&#8217;application a pu gérer près de 100 000 threads (soit autant de visteurs) contre 10 000 en utilisant uniquement les SoftReference.</p>
<h2>4 ème optimisation: optimiser les options de la JVM</h2>
<p>Ajoutons quelques options à la JVM:</p>
<p>-Xms1024m -Xmx1024m -Xmn512m -XX:+AggressiveOpts -XX:+UseParallelGC -XX:ParallelGCThreads=16</p>
<p>Et observons le résultat:</p>
<p><a href="http://www.opensides.fr/wp-content/uploads/2010/03/musee3_jvm_optimise_cpu.png"><img class="alignnone size-medium wp-image-397" title="musee3_jvm_optimise_cpu" src="http://www.opensides.fr/wp-content/uploads/2010/03/musee3_jvm_optimise_cpu-300x173.png" alt="" width="300" height="173" /></a></p>
<p>Le GC occupe à peine 1% de l&#8217;activité CPU.</p>
<p><a href="http://www.opensides.fr/wp-content/uploads/2010/03/musee3_jvm_optimise_memory.png"><img class="alignnone size-medium wp-image-398" title="musee3_jvm_optimise_memory" src="http://www.opensides.fr/wp-content/uploads/2010/03/musee3_jvm_optimise_memory-300x176.png" alt="" width="300" height="176" /></a></p>
<p>Les minor GC sont très réguliers jusqu&#8217;à atteindre le seuil (ce qui declenchera un full GC)</p>
<p><a href="http://www.opensides.fr/wp-content/uploads/2010/03/musee3_jvm_optimise_thread.png"><img class="alignnone size-medium wp-image-399" title="musee3_jvm_optimise_thread" src="http://www.opensides.fr/wp-content/uploads/2010/03/musee3_jvm_optimise_thread-300x172.png" alt="" width="300" height="172" /></a></p>
<p>Le nombre de threads traité passe de 100 000 à 211 124. Nous avons doublé le nombre de visiteurs dans le musée  (throughput).</p>
<h1>Conclusion</h1>
<p>L&#8217;objectif de l&#8217;article était de donner quelques pistes pour améliorer les performances d&#8217;une application. Dans un premier temps, nous avons vu qu’il était important de libérer les ressources pour éviter, au mieux, les garbages coûteux, au pire, les fuites mémoires. Un mécanisme de cache s&#8217;est révélé utile pour éviter la (re)création d’objets coûteux mais pouvait potentiellement engendrer une fuite mémoire en marquant une référence à un objet. Cela peut être évité avec l&#8217;utilisation d&#8217;un cache en SoftReference qui garantit la libération des objets en cas de saturation mémoire. Nous avons vu ensuite que ce seul mécanisme n&#8217;était pas suffisant pour garantir de bonnes performance et qu&#8217;il fallait nécessairement relâcher les objets afin d&#8217;éviter un overhead cpu lié au Garbage collector. Enfin un petit tunning de la JVM permet d&#8217;améliorer nos performances (elle a permis de doublé le nombre de visiteurs dans le musée). Nous verrons dans un prochain article comment améliorer encore les performances de notre application en recrutant de nouveaux guichetiers et en ouvrant de nouveaux musées…</p>
<p><strong>Bibliographie</strong></p>
<ul>
<li>http://fr.wikipedia.org/wiki/Ressource_%28informatique%29</li>
<li>http://blog.developpez.com/adiguba/p2107/java/comprendre-les-references-en-java/</li>
<li>http://fr.wikipedia.org/wiki/Algorithmes_de_remplacement_des_lignes_de_cache#LRU_.28Least_Recently_Used.2</li>
</ul>
<p>﻿</p>
]]></content:encoded>
			<wfw:commentRss>http://www.opensides.fr/2010/03/25/optimisation-des-ressources-dans-une-application-soa/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Understand resources</title>
		<link>http://www.opensides.fr/2010/03/21/understand-resources/</link>
		<comments>http://www.opensides.fr/2010/03/21/understand-resources/#comments</comments>
		<pubDate>Sun, 21 Mar 2010 22:08:37 +0000</pubDate>
		<dc:creator>ajeanson</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[resources]]></category>

		<guid isPermaLink="false">http://opensides.wordpress.com/?p=309</guid>
		<description><![CDATA[
Software development is based on resources. This may be of different nature (processor, memory, I / o). One of the challenges of software development is to understand the management of these resources to optimize the performance of our applications.
Here is a small synthetical post on hardware resources of a system microprocessor.

* The processor (CPU) is [...]]]></description>
			<content:encoded><![CDATA[<div>
<div>Software development is based on resources. This may be of different nature (processor, memory, I / o). One of the challenges of software development is to understand the management of these resources to optimize the performance of our applications.</p>
<p>Here is a small synthetical post on hardware resources of a system microprocessor.<br />
<a href="http://www.opensides.fr/wp-content/uploads/2010/03/ressources3.png"><img class="alignnone size-medium wp-image-350" title="ressources" src="http://www.opensides.fr/wp-content/uploads/2010/03/ressources3-300x137.png" alt="" width="393" height="179" /></a></p>
<p>* <strong>The processor (CPU)</strong> is the heart of the system. It&#8217;s like a bandmaster,  he make the calculations, take decisions in terms of addressing and allocation of resources within the system.<br />
* <strong>The ROM (read only memory) </strong>is the persistence support data such as database, LDAP, filesystem, etc &#8230; Access to such data is expensive, we must limit it<br />
* <strong>The RAM (memory)</strong> is volatile memory. Access is very fast and can therefore &laquo;&nbsp;hide&nbsp;&raquo; the information for which we need quick access. This resource is limited and as we shall see, it can rapidly be saturated with mismanagement.<br />
* <strong>Ports (I / O)</strong>: is access to peripherals and network. Acquisitions connections are expensive, so they should be limited.</p>
<p>These system components are connected by 3 bus:</p>
<p>* <strong>The data bus</strong> allows, as its name suggests, the movement of data, but also instructions to the 4 blocks.<br />
* <strong>The address bus</strong> allows the processor to show every time the memory cell or device which he wants to appeal.<br />
* <strong>The control bus</strong> is also operated by the processor and indicates, for example, if one wants to write or read in a memory cell, or an entry / exit to or from a device, also found in the bus control one or several lines that allow peripheral circuitry to make requests to the processor, these lines are called hardware interrupts (IRQ).</p>
<p>We shall see in the next sections how these resources are requested in an application and give us some ideas to optimize.</p>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.opensides.fr/2010/03/21/understand-resources/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

