Set up Apache HTTP Server with mod_cluster module to create an intelligent load balancing cluster with JBoss EAP application servers, featuring automatic node discovery, session clustering, and health monitoring.
Prerequisites
- Root or sudo access
- At least 4GB RAM
- Java 11 or higher
- Basic understanding of enterprise Java applications
- Network connectivity between cluster nodes
What this solves
This tutorial shows how to configure Apache HTTP Server with the mod_cluster module to create an intelligent load balancing solution for JBoss EAP application servers. Unlike traditional load balancers, mod_cluster provides dynamic configuration, automatic node discovery, and context-aware routing based on real-time server metrics.
You'll learn to set up a complete clustering environment with session replication, automatic failover, and comprehensive health monitoring for enterprise Java applications.
Step-by-step installation
Update system packages
Start by updating your system to ensure you have the latest packages and security updates.
sudo apt update && sudo apt upgrade -yInstall Apache HTTP Server and development tools
Install Apache web server along with development tools needed for compiling mod_cluster from source.
sudo apt install -y apache2 apache2-dev gcc make curl wget unzip
sudo a2enmod ssl
sudo a2enmod headers
sudo a2enmod rewriteDownload and compile mod_cluster
Download the latest mod_cluster source code and compile it for your Apache installation.
cd /tmp
wget https://github.com/modcluster/mod_cluster/releases/download/2.0.6.Final/mod_cluster-2.0.6.Final-linux-x86_64-ssl.tar.gz
tar -xzf mod_cluster-2.0.6.Final-linux-x86_64-ssl.tar.gz
cd mod_cluster-2.0.6.FinalInstall mod_cluster modules
Copy the compiled mod_cluster modules to Apache's modules directory and set proper permissions.
sudo cp so/mod_proxy_cluster.so /usr/lib/apache2/modules/
sudo cp so/mod_cluster_slotmem.so /usr/lib/apache2/modules/
sudo cp so/mod_manager.so /usr/lib/apache2/modules/
sudo cp so/mod_advertise.so /usr/lib/apache2/modules/
sudo chown root:root /usr/lib/apache2/modules/mod_*.so
sudo chmod 644 /usr/lib/apache2/modules/mod_*.soConfigure mod_cluster in Apache
Create the mod_cluster configuration file to define cluster behavior and load balancing parameters.
LoadModule cluster_slotmem_module modules/mod_cluster_slotmem.so
LoadModule manager_module modules/mod_manager.so
LoadModule proxy_cluster_module modules/mod_proxy_cluster.so
LoadModule advertise_module modules/mod_advertise.sosudo a2enmod clusterCreate mod_cluster virtual host configuration
Configure a dedicated virtual host for mod_cluster management and load balancing operations.
ServerName cluster-manager.example.com
# Enable mod_cluster manager
SetHandler mod_cluster-manager
Require ip 127.0.0.1
Require ip 10.0.0.0/24
# Configure mod_cluster parameters
CreateBalancers 1
ProxyPreserveHost On
ManagerBalancerName mycluster
# Health checking
PingMode 1
PingTimeout 10
# Session stickiness
UseAlias 1
# Advertising configuration
ServerAdvertise On
AdvertiseFrequency 5
AdvertiseBindAddress 224.0.1.105:23364
# Allow connections from JBoss nodes
Require ip 127.0.0.1
Require ip 10.0.0.0/24
# Error and access logs
ErrorLog ${APACHE_LOG_DIR}/mod_cluster_error.log
CustomLog ${APACHE_LOG_DIR}/mod_cluster_access.log combined
sudo a2ensite mod-cluster
sudo a2dissite 000-defaultInstall JBoss EAP
Download and install JBoss EAP application server which will serve as cluster nodes.
cd /opt
sudo wget https://developers.redhat.com/download-manager/file/jboss-eap-8.0.0.zip
sudo unzip jboss-eap-8.0.0.zip
sudo mv jboss-eap-8.0 jboss-eap
sudo chown -R jboss:jboss /opt/jboss-eapCreate JBoss user and group
Create a dedicated system user for running JBoss EAP securely without root privileges.
sudo groupadd -r jboss
sudo useradd -r -g jboss -d /opt/jboss-eap -s /bin/bash jboss
sudo chown -R jboss:jboss /opt/jboss-eapConfigure JBoss EAP for clustering
Create a clustered configuration for JBoss EAP with mod_cluster connector enabled.
Create systemd service for JBoss EAP cluster nodes
Create systemd service files for running multiple JBoss EAP instances as cluster nodes.
[Unit]
Description=JBoss EAP Node 1
After=network.target
[Service]
Type=simple
User=jboss
Group=jboss
ExecStart=/opt/jboss-eap/bin/standalone.sh -c standalone-ha-mod-cluster.xml -Djboss.bind.address=0.0.0.0 -Djboss.bind.address.management=0.0.0.0 -Djboss.node.name=node1 -Djboss.socket.binding.port-offset=0
ExecStop=/bin/kill -TERM $MAINPID
Restart=always
RestartSec=10
Environment=JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
Environment=JBOSS_HOME=/opt/jboss-eap
WorkingDirectory=/opt/jboss-eap
[Install]
WantedBy=multi-user.target[Unit]
Description=JBoss EAP Node 2
After=network.target
[Service]
Type=simple
User=jboss
Group=jboss
ExecStart=/opt/jboss-eap/bin/standalone.sh -c standalone-ha-mod-cluster.xml -Djboss.bind.address=0.0.0.0 -Djboss.bind.address.management=0.0.0.0 -Djboss.node.name=node2 -Djboss.socket.binding.port-offset=100
ExecStop=/bin/kill -TERM $MAINPID
Restart=always
RestartSec=10
Environment=JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
Environment=JBOSS_HOME=/opt/jboss-eap
WorkingDirectory=/opt/jboss-eap
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reloadInstall Java Development Kit
Install OpenJDK which is required for running JBoss EAP application server.
sudo apt install -y openjdk-11-jdk
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
echo 'export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64' | sudo tee -a /etc/environmentConfigure firewall rules
Open necessary ports for cluster communication, web traffic, and management interfaces.
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 8080/tcp
sudo ufw allow 8180/tcp
sudo ufw allow 8009/tcp
sudo ufw allow 8109/tcp
sudo ufw allow 9990/tcp
sudo ufw allow 10090/tcp
sudo ufw allow 7600/tcp
sudo ufw allow 7700/tcp
sudo ufw allow 55200/udp
sudo ufw allow 55300/udp
sudo ufw allow 45688/udp
sudo ufw allow 45788/udp
sudo ufw allow 23364/udp
sudo ufw --force enableStart all services
Enable and start Apache HTTP Server and both JBoss EAP cluster nodes.
sudo systemctl enable apache2
sudo systemctl start apache2
sudo systemctl enable jboss-node1
sudo systemctl start jboss-node1
sudo systemctl enable jboss-node2
sudo systemctl start jboss-node2Create a sample clustered application
Deploy a simple web application that demonstrates session clustering and failover capabilities.
Cluster Test Application
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.util.Date" %>
<%@ page import="java.net.InetAddress" %>
Cluster Test Application
JBoss EAP Cluster Test
Server Information
Server: <%= InetAddress.getLocalHost().getHostName() %>
Node Name: <%= System.getProperty("jboss.node.name") %>
Current Time: <%= new Date() %>
Session ID: <%= session.getId() %>
<%
String visitCount = (String) session.getAttribute("visitCount");
if (visitCount == null) {
visitCount = "1";
} else {
visitCount = String.valueOf(Integer.parseInt(visitCount) + 1);
}
session.setAttribute("visitCount", visitCount);
session.setAttribute("lastVisit", new Date().toString());
%>
Session Information
Visit Count: <%= visitCount %>
Last Visit: <%= session.getAttribute("lastVisit") %>
Session Created: <%= new Date(session.getCreationTime()) %>
Max Inactive Interval: <%= session.getMaxInactiveInterval() %> seconds
Refresh Page
Invalidate Session
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
Session Invalidated
Session Invalidated
<%
session.invalidate();
%>
Start New Session
sudo mkdir -p /opt/jboss-eap/standalone/deployments/cluster-test.war/WEB-INF
sudo chown -R jboss:jboss /opt/jboss-eap/standalone/deployments/cluster-test.warConfigure session clustering and failover
Enable session replication
Configure both JBoss nodes to replicate session data for seamless failover between cluster nodes.
SESSION
SET_AND_NON_PRIMITIVE_GET
Configure health monitoring
Set up comprehensive health checks and monitoring for the cluster nodes and load balancer.
<%@ page language="java" contentType="text/plain; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.sql.*" %>
<%@ page import="javax.naming.*" %>
<%
response.setContentType("text/plain");
try {
// Basic health check
String nodeName = System.getProperty("jboss.node.name", "unknown");
long freeMemory = Runtime.getRuntime().freeMemory();
long totalMemory = Runtime.getRuntime().totalMemory();
long usedMemory = totalMemory - freeMemory;
double memoryUsage = (double) usedMemory / totalMemory * 100;
if (memoryUsage < 90) {
response.setStatus(200);
out.println("OK - Node: " + nodeName + ", Memory Usage: " + String.format("%.2f", memoryUsage) + "%");
} else {
response.setStatus(503);
out.println("ERROR - High memory usage: " + String.format("%.2f", memoryUsage) + "%");
}
} catch (Exception e) {
response.setStatus(503);
out.println("ERROR - " + e.getMessage());
}
%>Configure automatic node discovery
Enable multicast advertising
Configure automatic node discovery using multicast advertising so new nodes automatically join the cluster.
# Enable IP forwarding for multicast
net.ipv4.ip_forward = 1
Increase multicast buffer sizes
net.core.rmem_default = 262144
net.core.rmem_max = 16777216
net.core.wmem_default = 262144
net.core.wmem_max = 16777216
Allow multicast
net.ipv4.conf.all.mc_forwarding = 1sudo sysctl -p /etc/sysctl.d/99-multicast.confRestart services and test discovery
Restart all services to apply configuration changes and verify automatic node discovery is working.
sudo systemctl restart apache2
sudo systemctl restart jboss-node1
sudo systemctl restart jboss-node2Performance optimization and monitoring
Optimize Apache for clustering
Configure Apache performance settings specifically optimized for cluster traffic and high availability.
# Add these lines to optimize for clustering
Increase worker limits for cluster traffic
ServerLimit 16
MaxRequestWorkers 400
ThreadsPerChild 25
Connection pooling for backend servers
ProxyIOBufferSize 65536
ProxyReceiveBufferSize 262144
Enable persistent connections
ProxyPreserveHost On
ProxyAddHeaders On
Timeout settings for cluster health
ProxyTimeout 30
ProxyConnectTimeout 5
Enable status monitoring
ExtendedStatus OnConfigure monitoring endpoints
Set up monitoring endpoints to track cluster health, performance metrics, and node status.
ServerName monitoring.example.com
# Apache server status
SetHandler server-status
Require ip 127.0.0.1
Require ip 10.0.0.0/24
# Apache server info
SetHandler server-info
Require ip 127.0.0.1
Require ip 10.0.0.0/24
# Mod_cluster status
ProxyPass http://localhost/mod_cluster_manager
ProxyPassReverse http://localhost/mod_cluster_manager
Require ip 127.0.0.1
Require ip 10.0.0.0/24
ErrorLog ${APACHE_LOG_DIR}/monitoring_error.log
CustomLog ${APACHE_LOG_DIR}/monitoring_access.log combined
Listen on port 8081 for monitoring
Listen 8081sudo a2ensite monitoring
sudo a2enmod status
sudo a2enmod infoFinal service restart
Restart Apache to apply all configuration changes and complete the cluster setup.
sudo systemctl reload apache2Verify your setup
# Check Apache status
sudo systemctl status apache2 # or httpd on RHEL-based systems
Check JBoss cluster nodes
sudo systemctl status jboss-node1
sudo systemctl status jboss-node2
Test mod_cluster manager interface
curl -s http://localhost/mod_cluster_manager
Test cluster application
curl -s http://localhost:8080/cluster-test/ | grep "Visit Count"
Check cluster node registration
curl -s http://localhost/mod_cluster_manager | grep -A 5 "Balancer"
Test session stickiness
curl -c cookies.txt -b cookies.txt http://localhost:8080/cluster-test/
curl -c cookies.txt -b cookies.txt http://localhost:8080/cluster-test/
Check health endpoints
curl -s http://localhost:8080/cluster-test/health.jsp
curl -s http://localhost:8180/cluster-test/health.jsp
Monitor Apache server status
curl -s http://localhost:8081/server-status?auto
Check cluster member discovery
grep -i "cluster" /opt/jboss-eap/standalone/log/server.log | tail -10Testing session failover
To test session clustering and failover capabilities, you can simulate node failures and verify that sessions are preserved across cluster nodes. This is essential for ensuring high availability in production environments.
# Start a session on node 1
curl -c session.txt http://localhost:8080/cluster-test/
Stop node 1 to simulate failure
sudo systemctl stop jboss-node1
Continue session on node 2 (should preserve session data)
curl -b session.txt http://localhost:8080/cluster-test/
Restart node 1
sudo systemctl start jboss-node1
Verify node rejoins cluster
curl -s http://localhost/mod_cluster_manager | grep node1Load balancing verification
Test that mod_cluster properly distributes requests across available nodes based on server metrics and health status.
# Create test script for load distribution
cat > test_load_balancing.sh << 'EOF'
#!/bin/bash
echo "Testing load distribution across cluster nodes..."
for i in {1..20}; do
response=$(curl -s http://localhost:8080/cluster-test/ | grep "Node Name")
echo "Request $i: $response"
sleep 1
done
EOF
chmod +x test_load_balancing.sh
./test_load_balancing.shCommon issues
| Symptom | Cause | Fix |
|---|---|---|
| Nodes not registering with mod_cluster | Multicast not working or firewall blocking | Check sudo netstat -tulpn | grep 23364 and verify firewall rules |
| Session data not replicating | Missing <distributable/> in web.xml | Add distributable element to web application descriptor |
| High memory usage on cluster nodes | Session replication overhead | Tune JVM heap size: -Xmx2g -Xms1g in service file |
| Load balancer not detecting failed nodes | Health check timeout too long | Reduce PingTimeout in mod_cluster configuration |
| Apache returns 503 Service Unavailable | No healthy backend nodes available | Check JBoss logs: tail -f /opt/jboss-eap/standalone/log/server.log |
| Cluster nodes can't communicate | JGroups configuration issues | Verify multicast connectivity: sudo tcpdump -i any host 230.0.0.4 |
Next steps
- Configure Apache HTTP/2 with performance optimization for modern protocol support
- Setup nginx reverse proxy with SSL certificates for alternative load balancing approaches
- Configure Linux system performance monitoring for comprehensive cluster monitoring
- Implement HAProxy SSL termination with Let's Encrypt certificates for SSL offloading
- Configure JBoss EAP SSL certificates and security hardening for production security
Running this in production?
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Apache mod_cluster installation and configuration script
# Supports Ubuntu, Debian, AlmaLinux, Rocky Linux, CentOS, RHEL
# Color definitions
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Configuration variables
CLUSTER_DOMAIN="${1:-cluster-manager.example.com}"
MOD_CLUSTER_VERSION="2.0.6.Final"
TEMP_DIR="/tmp/mod_cluster_install"
# Print colored output
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# Usage function
usage() {
echo "Usage: $0 [cluster-domain]"
echo "Example: $0 cluster-manager.example.com"
exit 1
}
# Cleanup function
cleanup() {
log_warn "Cleaning up temporary files..."
rm -rf "$TEMP_DIR"
}
# Error handler
error_handler() {
log_error "Script failed on line $1"
cleanup
exit 1
}
trap 'error_handler $LINENO' ERR
trap cleanup EXIT
# Check if running as root
if [[ $EUID -ne 0 ]]; then
log_error "This script must be run as root or with sudo"
exit 1
fi
# Auto-detect distribution
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_INSTALL="apt install -y"
PKG_UPDATE="apt update && apt upgrade -y"
APACHE_SERVICE="apache2"
APACHE_MODULES_DIR="/usr/lib/apache2/modules"
APACHE_CONFIG_DIR="/etc/apache2"
APACHE_SITES_DIR="/etc/apache2/sites-available"
APACHE_LOG_VAR="\${APACHE_LOG_DIR}"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
PKG_UPDATE="dnf update -y"
APACHE_SERVICE="httpd"
APACHE_MODULES_DIR="/usr/lib64/httpd/modules"
APACHE_CONFIG_DIR="/etc/httpd"
APACHE_SITES_DIR="/etc/httpd/conf.d"
APACHE_LOG_VAR="logs"
;;
amzn)
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
PKG_UPDATE="yum update -y"
APACHE_SERVICE="httpd"
APACHE_MODULES_DIR="/usr/lib64/httpd/modules"
APACHE_CONFIG_DIR="/etc/httpd"
APACHE_SITES_DIR="/etc/httpd/conf.d"
APACHE_LOG_VAR="logs"
;;
*)
log_error "Unsupported distribution: $ID"
exit 1
;;
esac
else
log_error "Cannot detect distribution (/etc/os-release not found)"
exit 1
fi
log_info "Detected distribution: $PRETTY_NAME"
log_info "Installing Apache mod_cluster for domain: $CLUSTER_DOMAIN"
echo "[1/8] Updating system packages..."
$PKG_UPDATE
echo "[2/8] Installing Apache and development tools..."
case "$PKG_MGR" in
apt)
$PKG_INSTALL apache2 apache2-dev gcc make curl wget unzip
a2enmod ssl
a2enmod headers
a2enmod rewrite
;;
dnf|yum)
$PKG_INSTALL httpd httpd-devel gcc make curl wget unzip
systemctl enable httpd
;;
esac
echo "[3/8] Creating temporary directory and downloading mod_cluster..."
mkdir -p "$TEMP_DIR"
cd "$TEMP_DIR"
wget "https://github.com/modcluster/mod_cluster/releases/download/${MOD_CLUSTER_VERSION}/mod_cluster-${MOD_CLUSTER_VERSION}-linux-x86_64-ssl.tar.gz"
tar -xzf "mod_cluster-${MOD_CLUSTER_VERSION}-linux-x86_64-ssl.tar.gz"
cd "mod_cluster-${MOD_CLUSTER_VERSION}"
echo "[4/8] Installing mod_cluster modules..."
cp so/mod_proxy_cluster.so "$APACHE_MODULES_DIR/"
cp so/mod_cluster_slotmem.so "$APACHE_MODULES_DIR/"
cp so/mod_manager.so "$APACHE_MODULES_DIR/"
cp so/mod_advertise.so "$APACHE_MODULES_DIR/"
chown root:root "$APACHE_MODULES_DIR"/mod_*.so
chmod 644 "$APACHE_MODULES_DIR"/mod_*.so
echo "[5/8] Configuring mod_cluster modules..."
case "$PKG_MGR" in
apt)
cat > "$APACHE_CONFIG_DIR/mods-available/cluster.load" << 'EOF'
LoadModule cluster_slotmem_module modules/mod_cluster_slotmem.so
LoadModule manager_module modules/mod_manager.so
LoadModule proxy_cluster_module modules/mod_proxy_cluster.so
LoadModule advertise_module modules/mod_advertise.so
EOF
a2enmod cluster
;;
dnf|yum)
cat >> "$APACHE_CONFIG_DIR/conf.modules.d/00-cluster.conf" << 'EOF'
LoadModule cluster_slotmem_module modules/mod_cluster_slotmem.so
LoadModule manager_module modules/mod_manager.so
LoadModule proxy_cluster_module modules/mod_proxy_cluster.so
LoadModule advertise_module modules/mod_advertise.so
EOF
;;
esac
echo "[6/8] Creating mod_cluster virtual host configuration..."
case "$PKG_MGR" in
apt)
CONFIG_FILE="$APACHE_SITES_DIR/mod-cluster.conf"
;;
dnf|yum)
CONFIG_FILE="$APACHE_SITES_DIR/mod-cluster.conf"
;;
esac
cat > "$CONFIG_FILE" << EOF
<VirtualHost *:80>
ServerName $CLUSTER_DOMAIN
# Enable mod_cluster manager
<Location /mod_cluster_manager>
SetHandler mod_cluster-manager
Require ip 127.0.0.1
Require ip 10.0.0.0/24
</Location>
# Configure mod_cluster parameters
CreateBalancers 1
ProxyPreserveHost On
ManagerBalancerName mycluster
# Health checking
PingMode 1
PingTimeout 10
# Session stickiness
UseAlias 1
# Advertising configuration
ServerAdvertise On
AdvertiseFrequency 5
AdvertiseBindAddress 224.0.1.105:23364
# Allow connections from JBoss nodes
<Location />
Require ip 127.0.0.1
Require ip 10.0.0.0/24
</Location>
# Error and access logs
ErrorLog $APACHE_LOG_VAR/mod_cluster_error.log
CustomLog $APACHE_LOG_VAR/mod_cluster_access.log combined
</VirtualHost>
EOF
chmod 644 "$CONFIG_FILE"
case "$PKG_MGR" in
apt)
a2ensite mod-cluster
a2dissite 000-default || true
;;
esac
echo "[7/8] Configuring firewall and starting services..."
case "$PKG_MGR" in
apt)
if command -v ufw >/dev/null 2>&1; then
ufw --force enable
ufw allow 80/tcp
ufw allow 23364/udp
fi
systemctl restart apache2
systemctl enable apache2
;;
dnf|yum)
if command -v firewall-cmd >/dev/null 2>&1; then
systemctl enable --now firewalld
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-port=23364/udp
firewall-cmd --reload
fi
systemctl restart httpd
systemctl enable httpd
;;
esac
# SELinux configuration for RHEL-based systems
if command -v setsebool >/dev/null 2>&1; then
setsebool -P httpd_can_network_connect 1
fi
echo "[8/8] Verifying installation..."
sleep 3
if systemctl is-active --quiet "$APACHE_SERVICE"; then
log_info "Apache service is running"
else
log_error "Apache service failed to start"
exit 1
fi
if curl -sf "http://localhost/mod_cluster_manager" >/dev/null 2>&1; then
log_info "mod_cluster manager is accessible"
else
log_warn "mod_cluster manager may not be accessible (this is normal if not accessing from allowed IPs)"
fi
log_info "Installation completed successfully!"
log_info "Access mod_cluster manager at: http://$CLUSTER_DOMAIN/mod_cluster_manager"
log_info "Configure your JBoss EAP instances to connect to this cluster manager"
log_info "Remember to update IP restrictions in $CONFIG_FILE as needed"
Review the script before running. Execute with: bash install.sh