Multiples instances Tomcat

De EjnTricks

Dans l'article de l'installation sous Windows, les variables CATALINA_HOME et CATALINA_BASE ont été évoquées mais sans être explicitées. Cet article se propose de montrer un moyen simple et élégant de mettre en place plusieurs instances de Tomcat sous Windows sans dupliquer les binaires.


Hand-icon.png Votre avis

Nobody voted on this yet

 You need to enable JavaScript to vote


Viewer icon.png Objectif

L'objectif de cette installation est de mettre en place quatre instances de Tomcat avec des versions de Java différentes sous Windows:

  • 1 instance Tomcat 6.0.37 sur une jdk 1.6.0.33
  • 1 instance Tomcat 6.0.37 sur une jdk 1.7.0.17
  • 1 instance Tomcat 7.0.47 sur une jdk 1.6.0.33
  • 1 instance Tomcat 7.0.47 sur une jdk 1.7.0.17

Comme indiqué dans l'article d'installation sous Windows, les répertoires d'installation reflète la version de Tomcat, mais également celle de Java ainsi que le port d'écoute:


Study icon.png Etude scripts arrêt et démarrage

Lors de l'installation, le script catalina.bat a été étudié et cela a permit de mettre en évidence l'utilisation des variables d'environnement CATALINA_HOME et CATALINA_BASE dans différentes sections.

Si CATALINA_BASE n'est pas rensignée, celle-ci est initialisée avec la valeur de CATALINA_HOME.

rem Copy CATALINA_BASE from CATALINA_HOME if not defined
if not "%CATALINA_BASE%" == "" goto gotBase
set "CATALINA_BASE=%CATALINA_HOME%"
:gotBase

Puis, le fichier setenv.bat est exécuté avec une préférence pour celui se trouvant dans le répertoire bin de l'emplacement défini dans CATALINA_BASE.

rem Get standard environment variables
if not exist "%CATALINA_BASE%\bin\setenv.bat" goto checkSetenvHome
call "%CATALINA_BASE%\bin\setenv.bat"
goto setenvDone
:checkSetenvHome
if exist "%CATALINA_HOME%\bin\setenv.bat" call "%CATALINA_HOME%\bin\setenv.bat"
:setenvDone

De la même façon, le fichier setclasspath.bat est exécuté.

rem Get standard Java environment variables
if exist "%CATALINA_HOME%\bin\setclasspath.bat" goto okSetclasspath
echo Cannot find "%CATALINA_HOME%\bin\setclasspath.bat"
echo This file is needed to run this program
goto end
:okSetclasspath
call "%CATALINA_HOME%\bin\setclasspath.bat" %1
if errorlevel 1 goto end

Enfin, ce même principe de recherche est appliqué pour différents fichiers utiles au démarrage de Tomcat.

rem Add tomcat-juli.jar to classpath
rem tomcat-juli.jar can be over-ridden per instance
if not exist "%CATALINA_BASE%\bin\tomcat-juli.jar" goto juliClasspathHome
set "CLASSPATH=%CLASSPATH%;%CATALINA_BASE%\bin\tomcat-juli.jar"
goto juliClasspathDone
:juliClasspathHome
set "CLASSPATH=%CLASSPATH%;%CATALINA_HOME%\bin\tomcat-juli.jar"
:juliClasspathDone

if not "%LOGGING_CONFIG%" == "" goto noJuliConfig
set LOGGING_CONFIG=-Dnop
if not exist "%CATALINA_BASE%\conf\logging.properties" goto noJuliConfig
set LOGGING_CONFIG=-Djava.util.logging.config.file="%CATALINA_BASE%\conf\logging.properties"
:noJuliConfig
set JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG%


En conclusion, la variable CATALINA_HOME doit contenir l'emplacement racine des binaires de Tomcat, et CATALINA_BASE, optionelle, l'emplacement du répertoire racine avec uniquement les fichiers de configuration spécifiques à l'instance.


Unzip-icon.png Mise en place

Dans le cadre de cet article, les "configurations" suivantes vont être mises en place:

Version Tomcat Port écoute Version Java Emplacement
6.0.37 N/A N/A c:\Apps\Tomcat\6.0.37_x64

Contient les binaires de la version 6.0.37. Sera la valeur de CATALINA_HOME.

6.0.37 9082 1.6.0_33 c:\Apps\Tomcat\6.0.37_x64_jdk_6.0_33_9082
6.0.37 9083 1.7.0_17 c:\Apps\Tomcat\6.0.37_x64_jdk_7.0_17_9083
7.0.47 N/A N/A c:\Apps\Tomcat\7.0.47_x64

Contient les binaires de la version 7.0.47. Sera la valeur de CATALINA_HOME.

7.0.47 9080 1.6.0_33 c:\Apps\Tomcat\6.0.37_x64_jdk_6.0_33_9080
7.0.47 9081 1.6.0_33 c:\Apps\Tomcat\6.0.37_x64_jdk_7.0_47_9081


Pour chacune des instances, l'arborescence doit contenir les répertoires suivants:

Répertoire Utilisation
bin Contient les deux scripts arrêts et démarrage, plus setenv.bat spécifiques.
conf Contient les fichiers, copie des originaux, de configuration de l'instance.
logs Les logs de l'instance y seront écrites.
temp Les fichiers temporaires de l'instance y seront écrites.
webapps Contient les applications déployées, si non déclarées dans le répertoire conf/Catalina/localhost.
work Contient les fichiers compilés des applications déployées de l'instance.

Le plus simple pour mettre en place une telle organisation, est de faire une copie de l'installation originale et de supprimer:

  • Les fichiers inutiles à la racine, ce qui est aussi vrai pour l'installation originale.
  • Le contenu du répertoire bin, il ne contiendra que les scripts spécifiques.
  • Le répertoire lib.
  • Le contenu des répertoires conf\Catalina\localhost, logs, temp, webapps (garder potentiellement ROOT) et work.

Run-icon.png Scripts spécifiques

Maintenant que l'organisation cible est décrite, il reste à écrire trois scripts dans le répertoire bin de chacune des installations:

script Utilisation
setenv.bat Permet de spécifier des variables d'environnement propre à l'instance, et donc la valeur de JAVA_HOME.
shutdown.bat Permet de spécifier la valeur de CATALINA_HOME et CATALINA_BASE pour chacune des instances, puis appeler le script shutdown.bat original.
startup.bat Permet de spécifier la valeur de CATALINA_HOME et CATALINA_BASE pour chacune des instances, puis appeler le script startup.bat original.

Bien entendu, il est inutile de ré-inventer la roue, donc les deux derniers scripts vont s'inspirer des originaux. Comme évoqué dans le tableau, le but est de spécifier des valeurs sur CATALINA_HOME et CATALINA_BASE avant d'exécuter les scripts originaux, et leur contenu va être très simple.

Le contenu du Script startup.bat, pour les instances basées sur la version 6.0.37:

@echo off

if "%OS%" == "Windows_NT" setlocal

cd ..
set "CATALINA_BASE=%cd%"
set "CATALINA_HOME=C:\Apps\Tomcat\6.0.37_x64"

set "EXECUTABLE=%CATALINA_HOME%\bin\startup.bat"

call "%EXECUTABLE%" %*

Pour les instances basées sur la version 7.0.47:

@echo off

if "%OS%" == "Windows_NT" setlocal

cd ..
set "CATALINA_BASE=%cd%"
set "CATALINA_HOME=C:\Apps\Tomcat\7.0.47_x64"

set "EXECUTABLE=%CATALINA_HOME%\bin\startup.bat"

call "%EXECUTABLE%" %*

Seule la valeur de CATALINA_HOME est spécifiée explicitement. La valeur de CATALINA_BASE est renseignée en fonction du contexte d'exécution. IL a également été pris soin de renvoyer les arguments de la ligne de commande au script original, à l'aide de l'instruction %*.

Le contenu du script shutdown.bat est tout aussi simple et suit la même logique. Pour la version 6.0.37:

@echo off

if "%OS%" == "Windows_NT" setlocal

cd ..
set "CATALINA_BASE=%cd%"
set "CATALINA_HOME=C:\Apps\Tomcat\6.0.37_x64"

set "EXECUTABLE=%CATALINA_HOME%\bin\shutdown.bat"

call "%EXECUTABLE%" %*

Pour la version 7.0.47:

@echo off

if "%OS%" == "Windows_NT" setlocal

cd ..
set "CATALINA_BASE=%cd%"
set "CATALINA_HOME=C:\Apps\Tomcat\7.0.47_x64"

set "EXECUTABLE=%CATALINA_HOME%\bin\shutdown.bat"

call "%EXECUTABLE%" %*


Enfin, le script setenv.bat va permettre de spécifier la version de Java utilisée. Pour les versions utilisant 6.0_33, le contenu est:

set JAVA_HOME=C:\Apps\Java\jdk1.6.0_33_x64

Pour l'utilisation de la version 7.0_17, l'emplacement spécifié est modifié:

set JAVA_HOME=C:\Apps\Java\jdk1.7.0_17

Malgré une première lecture souvent complexe, cette mise en place est très simple. Cependant, il faut bien avouer que cela ne fait gagner que quelques Mo... mais pour la beauté du geste...

Icon-Configuration-Settings.png Configurations

Maintenant que l'architecture est mise en place, il est nécessaire de modifier les paramétrages de chacune des instances, si il est souhaité de pouvoir les faire tourner toute en même temps. Pour cela, il suffit de modifier le fichier conf/server.xml dans chacune des instances mises en place en spécifiant des ports différents pour:

  • Sever.
  • Connecteur du protocol HTTP.
  • Connecteur de AJP.

Dans le principe, il est rajouté 1000, pour la première instance, à tous les ports définis dans le fichier original. Puis pour les instances suivantes la valeur ajoutée est 1001, 1002, 1003...

Pour l'instance 7.0.47_x64_jdk_6.0_33_9080:

<?xml version='1.0' encoding='utf-8'?>
<Server port="9005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <Listener className="org.apache.catalina.core.JasperListener" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <GlobalNamingResources>
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>

  <Service name="Catalina">

    <Connector port="9080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="9443" />

    <Connector port="9009" protocol="AJP/1.3" redirectPort="9443" />

    <Engine name="Catalina" defaultHost="localhost">

      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">

        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log." suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />

      </Host>
    </Engine>
  </Service>
</Server>

Pour l'instance 7.0.47_x64_jdk_7.0_17_9081:

<?xml version='1.0' encoding='utf-8'?>
<Server port="9006" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <Listener className="org.apache.catalina.core.JasperListener" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <GlobalNamingResources>
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>

  <Service name="Catalina">

    <Connector port="9081" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="9444" />

    <Connector port="9010" protocol="AJP/1.3" redirectPort="9444" />

    <Engine name="Catalina" defaultHost="localhost">

      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">

        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log." suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />

      </Host>
    </Engine>
  </Service>
</Server>

Pour l'instance 6.0.37_x64_jdk_6.0_33_9082:

<?xml version='1.0' encoding='utf-8'?>
<Server port="9007" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <Listener className="org.apache.catalina.core.JasperListener" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <GlobalNamingResources>
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>

  <Service name="Catalina">

    <Connector port="9082" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="9445" />

    <Connector port="9011" protocol="AJP/1.3" redirectPort="9445" />

    <Engine name="Catalina" defaultHost="localhost">

      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">

        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log." suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />

      </Host>
    </Engine>
  </Service>
</Server>

Pour l'instance 6.0.37_x64_jdk_7.0_17_9083:

<?xml version='1.0' encoding='utf-8'?>
<Server port="9008" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <Listener className="org.apache.catalina.core.JasperListener" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <GlobalNamingResources>
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>

  <Service name="Catalina">

    <Connector port="9083" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="9446" />

    <Connector port="9012" protocol="AJP/1.3" redirectPort="9446" />

    <Engine name="Catalina" defaultHost="localhost">

      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">

        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log." suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />

      </Host>
    </Engine>
  </Service>
</Server>