Czasami zachodzi potrzeba uruchomienia więcej niż jednej instancji serwera JBoss na jednym komputerze, czy to do celów testowych, deweloperskich czy nawet produkcyjnych. Aby było to możliwe, należy spełnić następujące warunki:

  • każda instancja serwera musi posiadać własny profil
  • należy skonfigurować odpowiednio serwer aplikacji oraz maszynę na której go uruchamiamy

W sumie największym problem jaki się pojawia w momencie uruchamiania kolejnych instancji serwera, jest konflikt wykorzystania tych samych portów na wybranej maszynie. Sposobów rozwiązania jest kilka, niektóre wymagają modyfikacji konfiguracji maszyny fizycznej, inne jedynie modyfikacji serwera JBoss AS.

Pierwszym krokiem będzie utworzenie dwóch profili w katalogu $JBOSS_HOME/server, które będą potem wykorzystywane do uruchomienia serwera. W dalszych części przyjmę, że profile te noszą nazwy profile1 oraz profile2 i są kopią profilu default.

Dodanie kolejnych aliasów IP do interfejsów sieciowych

Najprostszą metodą poradzenia sobie z konfliktem portów jest dodanie kolejnego (kolejnych) interfejsu sieciowego, będącego aliasem to już istniejącego. Czyli po prostu przyznanie sobie kolejnego numeru IP i przypięcie do niego konkretnej instancji serwera. Może to być spokojnie kolejny interfejs lokalny (loopback), jeżeli nie chcemy mieć dostępu do serwera z poza lokalnego komputera.

Jak utworzyć kolejne interfejsy? To zależy od używanego systemu operacyjnego:

I teraz nie pozostaje zrobić nic innego, jak uruchomić JBossa. Standardowo JBoss przypina się tylko interfejsu oznaczonego jako localhost (czyli adresu 127.0.0.1) oraz uruchamiania profil default. Aby to zmienić, należy użyć odpowiednich przełączników:

  • -c – nazwa konfiguracji do uruchomienia, a naszym przypadku profile1 lub profile2;
  • -b – nr IP, który ma wykorzystać JBoss do nasłuchiwania na połączenia;

Uruchomienie serwera z konfiguracją profile1 oraz nasłuchiwaniem na adresie 127.0.0.1:

$JBOSS_HOME/bin/run.sh -c profile1 -b 127.0.0.1

Uruchomienie serwera z konfiguracją profile2 oraz nasłuchiwaniem na adresie 127.0.0.2:

$JBOSS_HOME/bin/run.sh -c profile2 -b 127.0.0.2

Po tych operacjach powinniśmy otrzymać dwa uruchomione serwery JBoss, każdy nasłuchujący na innym adresie IP, w związku z czym nie wchodzących sobie w paradę. Sprawdzić można to przy użyciu polecenia netstat:

$ sudo netstat -tlpn | grep java
tcp        0      0 127.0.0.1:8083          0.0.0.0:*               LISTEN      12887/java      
tcp        0      0 127.0.0.2:8083          0.0.0.0:*               LISTEN      12789/java      
tcp        0      0 0.0.0.0:51415           0.0.0.0:*               LISTEN      12789/java      
tcp        0      0 127.0.0.1:51035         0.0.0.0:*               LISTEN      12887/java      
tcp        0      0 127.0.0.1:4444          0.0.0.0:*               LISTEN      12887/java      
tcp        0      0 0.0.0.0:60988           0.0.0.0:*               LISTEN      12887/java      
tcp        0      0 127.0.0.2:4444          0.0.0.0:*               LISTEN      12789/java      
tcp        0      0 127.0.0.1:58460         0.0.0.0:*               LISTEN      12789/java      
tcp        0      0 127.0.0.1:4445          0.0.0.0:*               LISTEN      12887/java      
tcp        0      0 127.0.0.2:4445          0.0.0.0:*               LISTEN      12789/java      
...

Zmiana portów (Service Binding Manger)

Drugim rozwiązaniem problemów konfliktu portów jest ich zmiana. Można to zrobić na albo przy użyciu specjalnej usługi zwanej Service Binding Manger lub też ręcznie

Od wersji 5.0 serwera aplikacji usługa ta jest domyślnie włączona i udostępnia 4 konfiguracje portów:

  • ports-default – domyślna konfiguracja portów
  • ports-01 – dodanie do każdego portu z domyślnej konfiguracji wartości 100
  • ports-02 – dodanie do każdego portu z domyślnej konfiguracji wartości 200
  • ports-03 – dodanie do każdego portu z domyślnej konfiguracji wartości 300

Jak widać konstrukcja jest całkiem prosta, definicja tych mapowań można znaleźć w pliku $JBOSS_HOME/server/PROFIL/conf/bindingservice.beans/META-INF/bindings-jboss-beans.xml. Tam znajduje się zarówno definicja wszystkich domyślnych portów, jak i definicje pozostałych konfiguracji (łącznie z offsetami).

Aby uruchomić JBossa z zadanym zestawem portów, należy ustawić w JVM zmienną jboss.service.binding.set na wartość odpowiadającej jednemu ze sposobów mapowań:

$JBOSS_HOME/bin/run.sh -c profile2 -Djboss.service.binding.set=ports-01

Można także zapisać zmiany w odpowiednim pliku konfiguracyjnym, nie będzie wtedy potrzeby konfigurowania zmiennej dla JVM. Plik, który należy edytować: $JBOSS_HOME/server/PROFIL/conf/bindingservice.beans/META-INF/bindings-jboss-beans.xml:

17
18
19
20
21
22
23
24
25
26
<!-- Provides management tools with a ProfileService ManagementView
interface to the SBM and its components -->
<bean name="ServiceBindingManagementObject"
class="org.jboss.services.binding.managed.ServiceBindingManagementObject">
 
<constructor>
 <!-- The name of the set of bindings to use for this server -->
 <parameter>${jboss.service.binding.set:ports-default}</parameter>
 
 <!--  The binding sets -->

W linii 24 znajduje się wpis wskazujący na domyślnie użyty zestaw portów. Wystarczy zmienić wpis ports-default na jedną z wartości: ports-01, ports-02 czy ports-03 i zrestartować serwer JBossa.

A oto jak wygląda mapowanie portów po uruchomieniu dwóch serwerów:

$ sudo netstat -tlpn | grep java
tcp        0      0 127.0.0.1:8083          0.0.0.0:*               LISTEN      12887/java
tcp        0      0 127.0.0.1:8180          0.0.0.0:*               LISTEN      15787/java
tcp        0      0 127.0.0.1:25460         0.0.0.0:*               LISTEN      15787/java
tcp        0      0 0.0.0.0:32885           0.0.0.0:*               LISTEN      15787/java
tcp        0      0 127.0.0.1:8183          0.0.0.0:*               LISTEN      15787/java
tcp        0      0 127.0.0.1:51035         0.0.0.0:*               LISTEN      12887/java
tcp        0      0 127.0.0.1:4444          0.0.0.0:*               LISTEN      12887/java
tcp        0      0 0.0.0.0:60988           0.0.0.0:*               LISTEN      12887/java
tcp        0      0 127.0.0.1:4445          0.0.0.0:*               LISTEN      12887/java
tcp        0      0 127.0.0.1:4446          0.0.0.0:*               LISTEN      12887/java
tcp        0      0 127.0.0.1:4544          0.0.0.0:*               LISTEN      15787/java
tcp        0      0 127.0.0.1:4545          0.0.0.0:*               LISTEN      15787/java
...

Jak widać, są uruchomione dwa procesy JVM i można zaobserwować podobne mapowania portów z różnicą 100 pomiędzy nimi.

Zmiana portów (admin-console)

W wersji 5.0 JBoss AS istnieje możliwość zmiany portów przy użyciu aplikacji admin-console. Umożliwia ona zarówno zmianę profilu, który będzie użyty podczas tworzenia konkretnych mapować, jak i modyfikację zarówno profili jak i poszczególnych portów dla różnych usług.

Binding Manager in the Admin Console

Binding Manager in the Admin Console

Czyli najprościej otworzyć Service Binding Manager, a następnie zmienić właściwość

Active Binding Set Name

. Pozostaje jeszcze tylko zrobić restart serwera i powinno działać.

Zmiana portów (ręczna)

Jeżeli z jakiś powodów nie można użyć usługi Service Binding Manager do zmiany domyślnych portów, pozostaje jeszcze możliwość ich recznej konfiguracji. W przypadku JBossa 5.1 należy otworzyć plik $JBOSS_HOME/server/PROFIL/conf/bindingservice.beans/META-INF/bindings-jboss-beans.xml oraz przyjrzeć się dokładnie w jaki sposób jest zdefiniowany domyślne mapowanie. W przypadku mojego pliku początek tej definicji wygląda następująco:

99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
!-- Base binding metadata that ServiceBindingStore uses to create bindings for each set -->
<bean name="StandardBindings" class="java.util.HashSet">
<constructor>
 <parameter class="java.util.Collection">
    <set elementClass="org.jboss.services.binding.ServiceBindingMetadata">
    <!-- ********************* conf/jboss-service.xml ****************** -->

    <!-- Naming Service -->
    <bean class="org.jboss.services.binding.ServiceBindingMetadata">
       <property name="serviceName">jboss:service=Naming</property>
       <property name="bindingName">Port</property>
       <property name="port">1099</property>
       <property name="description">The listening socket for the Naming service</property>
    </bean>

    <bean class="org.jboss.services.binding.ServiceBindingMetadata">
       <property name="serviceName">jboss:service=Naming</property>
       <property name="bindingName">RmiPort</property>
       <property name="port">1098</property>
       <property name="description">Socket Naming service uses to receive RMI requests from client proxies</property>
    </bean>

    <!-- Remote classloading service -->
    <bean class="org.jboss.services.binding.ServiceBindingMetadata">
       <property name="serviceName">jboss:service=WebService</property>
       <property name="port">8083</property>
       <property name="description">Socket for dynamic class and resource loading</property>
    </bean>

...

Jak widać, każda usługa posiada zdefiniowany jakiś port. Jeżeli mamy potrzebę, to możemy ten port zmienić, zrestartować serwer i powinno działać.

Podsumowanie

Wydaje mi się, że najlepszym sposobem uruchomienia kilku instancji serwera JBoss na jednej maszynie fizycznej jest użycie oddzielnych aliasów IP dla każdej z nich. Tylko jeżeli nie jest możliwe zastosowanie takiego sposobu, można zastanowić się nad zastosowaniem usługi Service Binding Manager. Jedynie ostatecznością powinna być ręczna modyfikacja portów, na jakich nasłuchują różne usługi uruchamiane przez serwera aplikacji:

Dlaczego warto używać oddzielnych adresów IP w zależności od instancji serwera:

  • łatwiej jest skojarzyć konkretną instancje JBossa z konkretnym numerem IP, niż pamiętać na jakie usługi na pracują na których niestandardowych portach
  • łatwiej jest skonfigurować zaporę ogniową
  • jeżeli istnieje na maszynie wiele usług, rośnie prawdopodobieństwo wystąpienia konfliktu portów nawet jeżeli używamy usługi SBM
  • łatwiejsza aktualizacja serwera aplikacji (brak problemów wynikających z nadpisaniem plików konfiguracyjnych, w szczególności w przypadku ręcznej edycji numerów portów)

Powyższe opisy działa w przypadku JBossa 5.1 i 5.0, w przypadku wcześniejszych wymagana jest trochę inna konfiguracja. Zmiana domyślnego adresu IP na którym nasłuchuje serwer jest taka sama, ale w przypadku JBossa 4.2 usługa SBM nie jest domyślnie włączona. Trzeba ją włączyć samodzielnie, co wymaga edycji odpowiednich plików. Podobnie inaczej się przypisuje ręcznie porty, na których nasłuchują poszczególne usługi (należy zmodyfikować pliki konfiguracyjne poszczególnych usług). Dokładniejszy opis można znaleźć w materiałach źródłowych.

Źródła