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:
- systemów wywodzących się z Debiana: Dodanie kolejnego lokalnego interfejsu sieciowego w Ubuntu/Debianie
- systemy wywodzące się z RedHata: Bind Multiple IP Addresses to a Single Network Interface Card (NIC)
- Windows XP: Set up multiple network interfaces in Windows XP
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
lubprofile2
; - -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
:
Uruchomienie serwera z konfiguracją profile2
oraz nasłuchiwaniem na adresie 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
:
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ń:
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:
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.
Czyli najprościej otworzyć Service Binding Manager, a następnie zmienić właściwość
. 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.