{"id":101,"date":"2008-07-04T09:13:50","date_gmt":"2008-07-04T08:13:50","guid":{"rendered":"http:\/\/blog.guiguiabloc.fr\/index.php\/2008\/07\/04\/haute-disponibilite-de-fermes-apache-et-tomcat\/"},"modified":"2008-07-04T09:13:50","modified_gmt":"2008-07-04T08:13:50","slug":"haute-disponibilite-de-fermes-apache-et-tomcat","status":"publish","type":"post","link":"http:\/\/blog.guiguiabloc.fr\/index.php\/2008\/07\/04\/haute-disponibilite-de-fermes-apache-et-tomcat\/","title":{"rendered":"Haute-Disponibilit\u00e9 de fermes Apache et Tomcat"},"content":{"rendered":"<p>Trouver un titre court pour r\u00e9sumer ce billet n&rsquo;a pas \u00e9t\u00e9 facile.<\/p>\n<p>Pour d\u00e9tailler un peu plus, je vous propose de mettre un place un Load-balancing crois\u00e9 entre une ferme de serveurs <a href=\"http:\/\/fr.wikipedia.org\/wiki\/Apache_HTTP_Server\" title=\"Apache\" target=\"_blank\">Apache<\/a> et une ferme de serveurs <a href=\"http:\/\/fr.wikipedia.org\/wiki\/Apache_Tomcat\" title=\"Tomcat\" target=\"_blank\">Tomcat<\/a>, le tout bien s\u00fbr contr\u00f4l\u00e9 par un syst\u00e8me de r\u00e9partition de charges et d&rsquo;ip virtuelle.<\/p>\n<p>(nb. Le terme \u00ab\u00a0ferme\u00a0\u00bb d\u00e9signe un ensemble de serveurs (2 minimum \ud83d\ude09 ). Et puis, Apache&#8230; Indien, Plumes, Poule, Ferme, la boucle est boucl\u00e9e \ud83d\ude00 &#8230; Bon ok, je &#8211;&gt;[] )<\/p>\n<p>Un dessin valant mieux qu&rsquo;un long discours, voici ce que nous allons mettre en place<br \/>\n<br clear=\"none\" \/><\/p>\n<p><a href=\"http:\/\/blog.guiguiabloc.fr\/wp-content\/ha-ferme.png\" title=\"HA-Ferme\"><img src=\"http:\/\/blog.guiguiabloc.fr\/wp-content\/ha-ferme.thumbnail.png\" alt=\"HA-Ferme\" \/><\/a><br \/>\n<br clear=\"none\" \/><br \/>\nOui je sais, je suis un grand malade&#8230;<br \/>\nLe principe est le suivant : Nous avons une IP Virtuelle, affect\u00e9e par le protocole CARP sur un ensemble de 2 serveurs OpenBSD. Nous utilisons \u00ab\u00a0Hoststated\u00a0\u00bb qui est un \u00ab\u00a0v\u00e9rificateur d&rsquo;\u00e9tat\u00a0\u00bb pour Packet Filter qui nous permettra de load balancer nos frontaux Apache.<\/p>\n<p>Bien \u00e9videmment, j&rsquo;utilise ce moyen car nous n&rsquo;avons pas tous un <a href=\"http:\/\/en.wikipedia.org\/wiki\/Alteon_WebSystems\" title=\"Alteon\" target=\"_blank\">ALTEON<\/a> chez soi&#8230;<\/p>\n<p><a href=\"http:\/\/blog.guiguiabloc.fr\/wp-content\/alteon184.jpg\" title=\"alteon184\"><img src=\"http:\/\/blog.guiguiabloc.fr\/wp-content\/alteon184.thumbnail.jpg\" alt=\"alteon184\" \/><\/a><\/p>\n<p>En dessous nous aurons notre ferme Apache en mode proxy qui fera du load-balancing sur nos tomcats qui eux, ecouteront en http.<\/p>\n<p>(dans cette architecture, on laisse les Tomcats g\u00e9r\u00e9r les contenus dynamiques ET statiques).<\/p>\n<ul>\n<li><strong>Configuration des Tomcats<\/strong><\/li>\n<\/ul>\n<p>Que ce soit un tomcat 5 ou 6, la configuration du connecteur Coyote se fait tout simplement dans le fichier server.xml dans le r\u00e9pertoire conf.<\/p>\n<p>Exemple :<br \/>\n<code><br \/>\n&lt;<strong>Connector port=\"60001\"<\/strong><br \/>\nminProcessors=\"5\"<br \/>\nmaxProcessors=\"64\"<br \/>\nenableLookups=\"false\"<br \/>\nscheme=\"http\"<br \/>\nproxyName=\"monappli.blog.guiguiabloc.fr\"<br \/>\nproxyPort=\"80\"<br \/>\nacceptCount=\"100\" debug=\"0\" connectionTimeout=\"1000\"<br \/>\nuseURIValidationHack=\"false\" disableUploadTimeout=\"true\" \/&gt;<br \/>\n&lt;Engine name=\"Catalina\" defaultHost=\"localhost\" <strong>jvmRoute=\"guiguiabloc-a<\/strong>\"&gt;<br \/>\n&lt;Host name=\"localhost\" appBase=\"webapps\" unpackWARs=\"true\" autoDeploy=\"true\"<br \/>\nxmlValidation=\"false\" xmlNamespaceAware=\"false\"&gt;<br \/>\n&lt;Alias&gt;monappli.blog.guiguiabloc.fr&lt;\/Alias&gt;<br \/>\n&lt;Context path=\"\/guiguiabloc\"<br \/>\ndocBase=\"\/opt\/tomcat-guiguiabloc\/webapps\/guiguiabloc\"<br \/>\ndebug=\"0\" privileged=\"false\"&gt;<\/code><\/p>\n<p>A adapter bien s\u00fbr \u00e0 votre appli tomcat.<\/p>\n<p>Ce qui est important c&rsquo;est :<\/p>\n<ol>\n<li>Le \u00ab\u00a0Connector Port\u00a0\u00bb qui est le port http sur lequelle \u00e9coute le tomcat (identique sur le deuxi\u00e8me serveur tomcat), ici 60001.<\/li>\n<li> la JVMRoute qui nous servira pour le balancing (ici \u00ab\u00a0guiguiabloc-a\u00a0\u00bb pour le serveur Tomcat-A et \u00ab\u00a0guiguiabloc-b\u00a0\u00bb pour le serveur Tomcat-B).<\/li>\n<\/ol>\n<p>Le reste est a peu pr\u00e8s classique, il est bon de rajouter un \u00ab\u00a0proxyName\u00a0\u00bb qui nous aidera lorsque l&rsquo;appli est mal cod\u00e9e&#8230; (qui a dit, cela arrive souvent ???)<\/p>\n<p>Il faut cr\u00e9er une page des test dans notre webapp, qui servira au redirecteur principal a v\u00e9rifier que le Tomcat r\u00e9pond correctement :<\/p>\n<p>Exemple de page test.jsp :<\/p>\n<pre>\r\n&lt;!DOCTYPE HTML PUBLIC \"-\/\/W3C\/\/DTD HTML 4.01 Transitional\/\/EN\"&gt;\r\n&lt;%@ page session=\"false\" %&gt;\r\n&lt;HTML&gt;\r\n&lt;HEAD&gt;\r\n&lt;%\r\nresponse.setHeader(\"Pragma\",\"No-cache\");\r\nresponse.setDateHeader(\"Expires\",0);\r\nresponse.setHeader(\"Cache-Control\",\"no-cache\");\r\n%&gt;\r\n&lt;\/HEAD&gt;\r\n&lt;BODY&gt;\r\nCette page est utilis\u00e9e par le frontal pour tester si Tomcat est lanc\u00e9\r\n&lt;\/BODY&gt;\r\n&lt;\/HTML&gt;<\/pre>\n<p>V\u00e9rifier que cela fonctionne avec un navigateur :<\/p>\n<p>lynx http:\/\/monappli.blog.guiguiabloc.fr:60001\/guiguiabloc\/test.jsp<br \/>\n<br clear=\"none\" \/><\/p>\n<ul>\n<li><strong>Configuration des frontaux Apache<\/strong><\/li>\n<\/ul>\n<p>Pr\u00e9-requis, compiler les modules proxy (j&rsquo;utilise la version 2.2.8 d&rsquo;Apache).<\/p>\n<p>N&rsquo;oubliez pas de les inclure dans votre httpd.conf :<\/p>\n<p>LoadModule proxy_module modules\/mod_proxy.so<br \/>\nLoadModule proxy_connect_module modules\/mod_proxy_connect.so<br \/>\nLoadModule proxy_ftp_module modules\/mod_proxy_ftp.so<br \/>\nLoadModule proxy_http_module modules\/mod_proxy_http.so<br \/>\nLoadModule proxy_ajp_module modules\/mod_proxy_ajp.so<br \/>\nLoadModule proxy_balancer_module modules\/mod_proxy_balancer.so<br \/>\nEtc&#8230; (modules mod_rewrite, mod_unique_id, mod_setenvif, mod_logio, mod_log* et d&rsquo;autres sont n\u00e9cessaire et d\u00e9pendent de la fa\u00e7on dont vous travaillez avec Apache).<\/p>\n<p>Un petit peaufinage en fin de fichier :<\/p>\n<p>ProxyReceiveBufferSize 65536<br \/>\n# Capacity configuration<br \/>\nServerLimit 4096<br \/>\nMaxClients 4096<br \/>\nSetEnv force-proxy-request-1.0 1<br \/>\nSetEnv proxy-nokeepalive 1<\/p>\n<p>Ne reste qu&rsquo;a configurer vos <a href=\"http:\/\/httpd.apache.org\/docs\/2.0\/vhosts\/\" title=\"vhost\" target=\"_blank\">vhost<\/a> :<br \/>\n<br clear=\"none\" \/><br \/>\n&lt;VirtualHost 192.168.1.1:80&gt; <strong><em>l&rsquo;ip du web-a<\/em><\/strong><\/p>\n<p>ServerName    monappli.blog.guiguiabloc.fr<\/p>\n<p>&lt;Proxy balancer:\/\/lbguigui&gt; <em><strong>Un nom unique pour identifier le loadbalancer<\/strong><\/em><\/p>\n<p>BalancerMember http:\/\/<em><strong>l&rsquo;adresse ip du tomcat-a<\/strong><\/em>:60001 route=guiguiabloc-a retry=1<br \/>\nconnecttimeout=2000 timeout=30 loadfactor=100<br \/>\nBalancerMember http:\/\/<em><strong>l&rsquo;adresse ip du tomcat-b<\/strong><\/em>:60001 route=guiguiabloc-b retry=1<br \/>\nconnecttimeout=2000 timeout=30 loadfactor=100<br \/>\n&lt;\/Proxy&gt;<\/p>\n<p>ProxySet    balancer:\/\/lbguigui    stickysession=JSESSIONID|jsessionid    nofailover=on<br \/>\nmaxattempts=1<\/p>\n<p><em><strong>Pour des applis PHP, remplacer \u00ab\u00a0JSESSIONID\u00a0\u00bb par \u00ab\u00a0PHPSESSIONID\u00a0\u00bb (si vous g\u00e9rez les sessions) <\/strong><\/em><\/p>\n<p><em><strong>On positionne le \u00ab\u00a0nofailover=on\u00a0\u00bb car on ne fait pas de r\u00e9plication de session<\/strong><\/em><\/p>\n<p>Si vous voulez plus d&rsquo;informations, je vous invite \u00e0 consulter le site d&rsquo;Apache, surtout <a href=\"http:\/\/www.esslli2002.it\/mod\/mod_proxy.html#proxypass\" title=\"proxybalancer\" target=\"_blank\">LA<\/a> .<\/p>\n<p>Le Proxy via le module Rewrite :<\/p>\n<p>RewriteEngine    On<br \/>\nRewriteRule    ^(.*)$    $1    [E=request-uri:$1,C]<br \/>\nRewriteRule    ^(\/.*)$    balancer:\/\/lbguigui$1    [P,L]<br \/>\nRewriteRule    ^(.*)$    \/    [R=permanent,L]<\/p>\n<p><br clear=\"none\" \/><br \/>\nPS: Je vous conseille fortement de vous d\u00e9finir votre propre format de log afin de tracer au mieux vos sessions.<\/p>\n<p>Exemple de cr\u00e9ation de format de Log et de modification des en-t\u00eates :<\/p>\n<pre>\r\nLogFormat \"%h %l %u %t \\\"%r\\\" %&gt;s %B \\\"\r\n%{Referer}i\\\" \\\"%{User-Agent}i\\\" I=%I O=%O %{X-Guiguiabloc-Diag}o\r\nh=web-a r=%{BALANCER_SESSION_ROUTE}e w=%{BALANCER_WORKER_NAME}e D\r\nD=%D C=%X s=%{REDIRECT_STATUS}e\r\nXFF=\\\"%{X-Forwarded-For}i\\\"\" GuiguiablocLogFormat\r\n\r\nCustomLog logs\/monappli.blog.guiguiabloc.fr\/access.log GuiguiablocLogFormat\r\nErrorLog logs\/monappli.blog.guiguiabloc.fr\/error.log\r\n\r\nHeader set X-Guiguiabloc-Diag  \"%t %D\"\r\n\r\nHeader set X-Guiguiabloc-Route \"h=web-a\r\nr=%{BALANCER_SESSION_ROUTE}e w=%{BALANCER_WORKER_NAME}e\"\r\n\r\nHeader set X-Guiguiabloc-URI \"u=%{request-uri}e\"\r\n\r\nHeader append Vary User-Agent\r\nRequestHeader set Host monappli.blog.guiguiabloc.fr\r\nProxyPreserveHost On\r\nHeader set Server \"MA FERME H-A\"\r\nHeader set Cache-Control no-cache=\"Set-Cookie,Set-Cookie2\" env=cacheable-maxage\r\nHeader append Cache-Control private env=cacheable-private\r\nHeader append Cache-Control max-age=%{cacheable-maxage}e env=cacheable-maxage\r\nHeader set Cache-Control no-store env=!cacheable-maxage\r\nHeader append Cache-Control no-cache env=!cacheable-maxage\r\nHeader unset Set-Cookie env=cacheable-maxage\r\nHeader unset  Set-Cookie2 env=cacheable-maxage\r\nHeader unset   ETag<\/pre>\n<p>Lire <a href=\"http:\/\/www.esslli2002.it\/mod\/mod_proxy_balancer.html\" title=\"loadbalancer\" target=\"_blank\">cette partie<\/a> chez Apache.<\/p>\n<ul>\n<li> <strong>Configuration de la VIP et du load-balancer<\/strong><\/li>\n<\/ul>\n<p>J&rsquo;avais d\u00e9j\u00e0 expliquer dans un <a href=\"http:\/\/blog.guiguiabloc.fr\/index.php\/2008\/03\/21\/anatomie-dune-architecture-4\/\" title=\"CARP\" target=\"_blank\">billet pr\u00e9c\u00e9dent<\/a> la configuration d&rsquo;une VIP avec CARP sous OpenBSD, je ne reviendrais donc pas dessus.<\/p>\n<p>La configuration du Load Balancing avec PacketFilter est on ne peut plus simple (comme toujours avec ce bijou \ud83d\ude42 ) :<\/p>\n<pre>webA = \"192.168.1.1\"\r\nwebB = \"192.168.1.2\"\r\nrdr on $ext from any to $VIP port 80 -&gt; {$webA $webB}<\/pre>\n<pre>table &lt;serveursWeb&gt; persist\r\nrdr on $ext from any $VIP port 80 -&gt; &lt;serveursWeb&gt;<\/pre>\n<p>Ne reste qu&rsquo;a ajouter nos serveurs Apache dans la table \u00ab\u00a0serveursWeb\u00a0\u00bb :<\/p>\n<pre>pfctl -t serveursWeb -T a 192.168.1.1<\/pre>\n<pre>pfctl -t serveurWeb -T a 192.168.1.2<\/pre>\n<pre><\/pre>\n<pre><\/pre>\n<p>Afin de v\u00e9rifier l&rsquo;\u00e9tat de nos serveurs Web, nous allons utiliser \u00ab\u00a0<a href=\"http:\/\/www.openbsd.org\/cgi-bin\/man.cgi?query=hoststated\" title=\"hoststated\" target=\"_blank\">Hoststated<\/a>\u00ab\u00a0. (Sa mise en oeuvre est extr\u00e8mement simpliste).<\/p>\n<p>Une petite ancre bien plac\u00e9e dans notre pf.conf :<\/p>\n<pre>rdr-anchor \"hoststated\/*\"<\/pre>\n<pre><\/pre>\n<p>Puis on renseigne notre fichier \/etc\/hoststated.conf :<\/p>\n<pre>webA=\"192.168.1.1\"\r\nwebB=\"192.168.1.2\"\r\n\r\ninterval 5\t# v\u00e9rifiation toutes les 5 secondes\r\n\r\ntable serveursWeb {\r\n\tcheck http \"\/test.jsp\" code 200\r\n\ttimeout 300\r\n\treal port 80\r\n\thost $webA\r\n\thost $webB\r\n\t}\r\n\r\nservice www {\r\n\tvirtual ip $VIP port 80\r\n\ttable serveursWeb\r\n}<\/pre>\n<p>Vous pouvez v\u00e9rifier l&rsquo;\u00e9tat de vos serveurs Apache en temps r\u00e9el :<\/p>\n<pre># hoststatectl show\r\nType      Id    Name                            Status\r\nservice    0    www                             active\r\ntable      0    serveursWeb                     active (2 hosts up)\r\nhost       1    192.168.1.1                     down\r\nhost       0    192.168.1.2                     up<\/pre>\n<pre><\/pre>\n<p>Magique non ?<\/p>\n<p>Le sch\u00e9ma du d\u00e9but avec les IP utilis\u00e9es pour vous aider \u00e0 comprendre l&rsquo;architecture :<\/p>\n<p><a href=\"http:\/\/blog.guiguiabloc.fr\/wp-content\/ha-ferme2.png\" title=\"HA-Ferme2\"><img src=\"http:\/\/blog.guiguiabloc.fr\/wp-content\/ha-ferme2.thumbnail.png\" alt=\"HA-Ferme2\" \/><\/a><\/p>\n<p>J&rsquo;ai bien \u00e9videmment survoler toutes les possibilit\u00e9s que vous offre ce type d&rsquo;architecture. Je laisse votre esprit d\u00e9sormais en \u00e9bullition pour peaufiner le travail et vous plonger dans les MAN et fichiers de configuration des diff\u00e9rents outils utilis\u00e9s ici afin de l&rsquo;adapter \u00e0 vos besoins.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Trouver un titre court pour r\u00e9sumer ce billet n&rsquo;a pas \u00e9t\u00e9 facile. Pour d\u00e9tailler un peu plus, je vous propose de mettre un place un Load-balancing crois\u00e9 entre une ferme de serveurs Apache et une ferme de serveurs Tomcat, le &hellip; <a href=\"http:\/\/blog.guiguiabloc.fr\/index.php\/2008\/07\/04\/haute-disponibilite-de-fermes-apache-et-tomcat\/\">Read More <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[27,7,16],"tags":[28,34,30,31,32,33,29],"_links":{"self":[{"href":"http:\/\/blog.guiguiabloc.fr\/index.php\/wp-json\/wp\/v2\/posts\/101"}],"collection":[{"href":"http:\/\/blog.guiguiabloc.fr\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.guiguiabloc.fr\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.guiguiabloc.fr\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.guiguiabloc.fr\/index.php\/wp-json\/wp\/v2\/comments?post=101"}],"version-history":[{"count":0,"href":"http:\/\/blog.guiguiabloc.fr\/index.php\/wp-json\/wp\/v2\/posts\/101\/revisions"}],"wp:attachment":[{"href":"http:\/\/blog.guiguiabloc.fr\/index.php\/wp-json\/wp\/v2\/media?parent=101"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.guiguiabloc.fr\/index.php\/wp-json\/wp\/v2\/categories?post=101"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.guiguiabloc.fr\/index.php\/wp-json\/wp\/v2\/tags?post=101"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}