WildFly

Seit der Version 8 heisst Red Hats JBoss Enterprise Application Server (EAP) „WildFly“ (vorher „JBoss AS“). Im Oktober 2013 kündigte Oracle den Support für GlassFish 4, der Referenzimplementierung des Java-EE-7-Standards - seitdem ist JBoss/WildFly der einzige professionell einsetzbare Open Source-Applikationsserver. Oracle bietet in dem Bereich nur noch Support für den erheblich teureren WebLogic-Server.

WildFly/JBoss AS setzte bis Version 7 den Tomcat als Webcontainer ein, ab Version 8 dann „Undertow“. Die kommerzielle Variante heisst JBoss EAP. JBoss EAP ist ein WildFly mit zig Erweiterungen, die im Business-Umfeld Sinn machen, wie z.B. einem Messaging-Subsystem.

WildFly verhält sich zu JBoss EAP wie Fedora zu RHEL.

Begriffe:

  • AJP: Apache JServ Protocol, dient zur Kommunikation zwischen dem Apache-Webserver und einer JServ-Engine wie z.B. WildFly.

  • Container: Runtime Environment.

  • EJB: EJB-Anwendungen, die Java-Beans Class-Dateien sowie EJB-Deployment-Beschreibungen enthalten.

  • HornetQ: Ehemals „JBoss Messaging“. Ist ein Dienst für eine lose gekoppelte, asynchrone Kommunikation zwischen den Komponenten einer verteilten Anwendung.

  • JAAS: Java Authentication and Authorization Service

  • JAR: Java Archive, .jar-Datei. META-INF-Ordner. Für EJB-Anwendungen.

  • Java EE: Ein Java EE Application Server besitzt zwei Container: Web und EJB.

  • JCA: Java EE Connector Architecture Subsystem

  • JDR: JBoss Diagnostic Reporter Subsystem

  • JKS: Java KeyStore. Ein Repository für Autorisierungs- oder Public Key-Zertifikate. Das JDK verwaltet den Keystore für CAs unter /usr/java/default/lib/security/cacerts. Für die Verwaltung von Keystores wird das Tool keytool aus dem JDK verwendet.

  • POJO: Plain Old Java Objects

  • WAR: Web-Module, die Servlet-Class-Dateien, JSP-, HTML-, GIF und weitere Webdateien enthalten, werden als JAR-Datei gepackt und mit einer .war-Dateiendung versehen. Sie landen im Web-Container eines Java EE Application Servers.

Konzepte

  • Server Groups: eine logische Zusammenfassung von einzelnen JBoss-Servern, beispielsweise in die Gruppen „prod“ und „test“. Server Groups können sich über verschiedene physische Hosts erstrecken. Man beachte, dass in einer JBoss-Instanz mehrere Server laufen können.

  • Operation Modes: Standalone oder Domain.

  • Domain: eine Sammlung von Server Groups.

  • Domain Mode: ein EAP, der Mitglied einer Server Group in einer Domain ist oder sogar Domain Controller.

  • Domain Controller: maximal einer pro Domain; administriert Server Groups. Statt auf lokaler Server-Ebene werden beispielsweise Einstellungen für Netzwerk, JVM oder die Verteilung von Applikationen von diesem auf die Server Group angewendet.

  • Host Controller: Prozess, der auf der Server-Instanz läuft und mit dem Domain Controller spricht.

  • Application Server Node: ein einzelner EAP.

  • Standalone Mode: ein einzelner EAP.

Es gibt zwei Arten von Datenquellen:

  • (Non-XA) Datenquellen werden für Applikationen verwendet, die mit nur einer Datenbankverbindung oder ohne Transaktionen arbeiten.

  • XA-Datenquellen werden Applikationen bereitgestellt, die transaktionsbasiert und/oder über mehrere Datenbanken verteilt arbeiten.

Load Balancing wird mit vorgeschaltetem Apache httpd erreicht. Früher wurde im Apache mod_jk aus dem Tomcat-Projekt geladen, heute nimmt man mod_cluster.

Es gibt einige Möglichkeiten, Applikationen zu deployen:

  • Archivierte Applikation in den deployments-Ordner kopieren (nur im Standalone-Mode)

  • Über die Web-Management-Konsole: „Managed Deployments“ werden vom Client-Browser aus auf den Server hochgeladen. „Unmanaged Deployments“ setzen nur einen Link auf die bereits auf dem WildFly-Server vorhandene Applikation (letzteres nur im Standalone-Mode).

  • Mittels der Management-CLI: /path/to/bin/jboss-cli.sh, connect und anschliessend deploy myapp.war

Links

Installation und Konfiguration

Ohne geht es nicht: Vorher OpenJDK, Oracle JRE oder Oracle JDK installieren.

dnf -y install java tar

Installation nach /opt:

useradd --shell /sbin/nologin wildfly

VER=26.0.1.Final
wget https://github.com/wildfly/wildfly/releases/download/$VER/wildfly-$VER.tar.gz
tar xvzf wildfly-$VER.tar.gz
mv wildfly-$VER /opt
ln -s /opt/wildfly-$VER /opt/wildfly
chown -R wildfly:wildfly /opt/wildfly*

Standalone-Mode konfigurieren:

cp /opt/wildfly/standalone/configuration/standalone.xml /opt/wildfly/standalone/configuration/standalone.xml.orig
sed -i -e 's,inet-address value="${jboss.bind.address:127.0.0.1}",any-address,g' /opt/wildfly/standalone/configuration/standalone.xml
sed -i -e 's,inet-address value="${jboss.bind.address.management:127.0.0.1}",any-address,g' /opt/wildfly/standalone/configuration/standalone.xml

WildFly Management-Benutzer anlegen:

/opt/wildfly/bin/add-user.sh
What type of user do you wish to add?
 a) Management User (mgmt-users.properties)
 b) Application User (application-users.properties)
(a): a

Enter the details of the new user to add.
Using realm 'ManagementRealm' as discovered from the existing property files.
Username : admin
Password recommendations are listed below. To modify these restrictions edit the add-user.properties configuration file.
 - The password should be different from the username
 - The password should not be one of the following restricted values {root, admin, administrator}
 - The password should contain at least 8 characters, 1 alphabetic character(s), 1 digit(s), 1 non-alphanumeric symbol(s)
Password :
Re-enter Password :
What groups do you want this user to belong to? (Please enter a comma separated list, or leave blank for none)[  ]:
About to add user 'admin' for realm 'ManagementRealm'
Is this correct yes/no? yes
Added user 'admin' to file '/opt/wildfly-23.0.0.Final/standalone/configuration/mgmt-users.properties'
Added user 'admin' to file '/opt/wildfly-23.0.0.Final/domain/configuration/mgmt-users.properties'
Added user 'admin' with groups  to file '/opt/wildfly-23.0.0.Final/standalone/configuration/mgmt-groups.properties'
Added user 'admin' with groups  to file '/opt/wildfly-23.0.0.Final/domain/configuration/mgmt-groups.properties'
Is this new user going to be used for one AS process to connect to another AS process?
e.g. for a slave host controller connecting to the master or for a Remoting connection for server to server Jakarta Enterprise Beans calls.
yes/no? no

Der Benutzer wird in standalone/configuration/mgmt-users.properties abgelegt.

Firewall anpassen:

firewall-cmd --permanent --add-port=8080/tcp
firewall-cmd --permanent --add-port=9990/tcp
firewall-cmd --reload

Zum Test Wildfly-Server manuell starten:

/opt/wildfly/bin/standalone.sh

Systemd-Service:

cp /opt/wildfly/docs/contrib/scripts/systemd/wildfly.service /etc/systemd/system/wildfly.service
systemctl daemon-reload
systemctl enable --now wildfly

Das Unit-File sieht wie folgt aus:

/etc/systemd/system/wildfly.service
[Unit]
Description=The WildFly Application Server
After=syslog.target network.target
Before=httpd.service

[Service]
Environment=LAUNCH_JBOSS_IN_BACKGROUND=1
EnvironmentFile=-/etc/wildfly/wildfly.conf
User=wildfly
LimitNOFILE=102642
PIDFile=/var/run/wildfly/wildfly.pid
ExecStart=/opt/wildfly/bin/standalone.sh $WILDFLY_MODE $WILDFLY_CONFIG $WILDFLY_BIND
StandardOutput=null

[Install]
WantedBy=multi-user.target

Nach einer Standard-Installation im Standalone-Mode startet WildFly unter Java mit folgenden JAVA_OPTS (u.a. Memory-Settings):

bin/standalone.conf
# Java 8
JAVA_OPTS="-server -Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true"

Die Memory-Settings sind im produktiven Einsatz zu konservativ gesetzt. Eine schöne Erläuterung bietet beispielsweise https://julio-falbo.medium.com/understand-jvm-and-jit-compiler-part-4-9738194ad06e.heisst

Um z.B. CodeHeap_non-profiled (Java 9+) zu erhöhen:

bin/standalone.conf
# Standard: 122m
JAVA_OPTS="... -XX:NonProfiledCodeHeapSize=150m"

Zugriff:

CLI

./bin/jboss-cli.sh --connect

[standalone@wildfly:9990 /] /subsystem=logging/log-file=server.log:read-log-file
[standalone@wildfly:9990 /] quit

API

curl --digest \
    --header "Content-Type: application/json" \
    --user admin \
    http://wildfly:9990/management

curl --digest \
    --header "Content-Type: application/json" \
    --user admin \
    --data '{"operation": "read-attribute", "name": "server-state", "json.pretty": 1}' \
    http://wildfly:9990/management

# or "json" instead of "json.pretty"

Mapping CLI zum API:

# CLI
# /subsystem=undertow/server=default-server:read-resource(include-runtime=true,recursive=true)

# API
http://wildfly:9990/management/subsystem/undertow/server/default-server?operation=resource&recursive=true&json.pretty=1

Python-Code gegen das WildFly-API inkl. HTTP Digest Auth:

import urllib2
import json

url = 'http://wildfly:9990/management'

passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
passmgr.add_password(None, url, 'admin', 'password')

auth_handler = urllib2.HTTPDigestAuthHandler(passmgr)
opener = urllib2.build_opener(auth_handler)
urllib2.install_opener(opener)

data = json.dumps({'operation': 'read-attribute', 'name': 'server-state', 'json': 1})
request = urllib2.Request(url, data=data)

header = {'Content-Type': 'application/json'}
for key, value in header.items():
    request.add_header(key, value)
request.add_header('Connection', 'close')

response = urllib2.urlopen(request, timeout=7)
result = response.read()

Built on 2022-06-03