Skip to main content

Apache mod_proxy_balancer Load Balancing

Apache HTTPD provides powerful load balancing through the mod_proxy_balancer module. Define upstream groups with the balancer:// scheme and distribute requests using various algorithms (lbmethod).


Enabling Required Modules​

The following modules must be enabled for load balancing in Apache.

# Ubuntu/Debian
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_balancer
sudo a2enmod lbmethod_byrequests # Round Robin
sudo a2enmod lbmethod_bytraffic # Traffic-based
sudo a2enmod lbmethod_bybusyness # Least connections
sudo a2enmod slotmem_shm # Shared memory (required for balancer)
sudo systemctl restart apache2

# CentOS/RHEL (uncomment in httpd.conf)
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so
LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so
LoadModule slotmem_shm_module modules/mod_slotmem_shm.so

Basic Load Balancer Configuration​

Simplest Setup (byrequests)​

# /etc/apache2/sites-available/load-balancer.conf

<VirtualHost *:80>
ServerName example.com

ProxyRequests Off
ProxyPreserveHost On

# Define upstream group
<Proxy "balancer://mycluster">
BalancerMember "http://10.0.0.1:8080"
BalancerMember "http://10.0.0.2:8080"
BalancerMember "http://10.0.0.3:8080"

ProxySet lbmethod=byrequests # Round Robin
</Proxy>

# Forward all requests to the load balancer
ProxyPass "/" "balancer://mycluster/"
ProxyPassReverse "/" "balancer://mycluster/"
</VirtualHost>

lbmethod Algorithms​

byrequests (Request Count Based, Round Robin)​

Distributes based on the number of requests processed by each server, weighted by loadfactor. Behaves like Round Robin by default.

<Proxy "balancer://mycluster">
BalancerMember "http://10.0.0.1:8080" loadfactor=3
BalancerMember "http://10.0.0.2:8080" loadfactor=1
ProxySet lbmethod=byrequests
</Proxy>

loadfactor works like Nginx's weight. App1 handles 75%, App2 handles 25%.

bytraffic (Traffic Byte Based)​

Distributes based on processed traffic (bytes). Useful when response sizes vary widely, like file downloads.

<Proxy "balancer://mycluster">
BalancerMember "http://10.0.0.1:8080"
BalancerMember "http://10.0.0.2:8080"
ProxySet lbmethod=bytraffic
</Proxy>

When 100MB file downloads and 1KB API responses are mixed, byrequests simply counts requests, while bytraffic accounts for actual data processed. Best for image/video serving servers.

bybusyness (Minimum Active Requests)​

Routes to the server with the fewest currently active requests. Similar to Nginx's least_conn.

<Proxy "balancer://mycluster">
BalancerMember "http://10.0.0.1:8080"
BalancerMember "http://10.0.0.2:8080"
BalancerMember "http://10.0.0.3:8080"
ProxySet lbmethod=bybusyness
</Proxy>

Best for API servers or backends with heavy DB queries.


Complete BalancerMember Parameter Reference​

<Proxy "balancer://mycluster">
BalancerMember "http://10.0.0.1:8080"
loadfactor=3 # Weight (default: 1)
retry=60 # Retry interval after failure (seconds), 0 = permanent exclusion
timeout=30 # Connection timeout (seconds)
acquire=3000 # Max connection wait time (ms)
max=100 # Max concurrent connections
ttl=60 # Idle connection lifetime (seconds)
route=jvm1 # JVM route ID for mod_jk integration
status=+H # Force status (+H=Hot Standby, +D=Disabled, +S=Stop, +I=Ignore errors)

BalancerMember "http://10.0.0.2:8080" loadfactor=1 status=+H
# +H: Hot Standby β€” only used when all other servers are down

ProxySet lbmethod=bybusyness
ProxySet stickysession=JSESSIONID # Session affinity
</Proxy>

Status Flag Reference​

FlagMeaningWhen to Use
+DDisabledBlock traffic during maintenance
+HHot StandbyStandby server (unused in normal operation)
+SStoppedBlock new connections, keep existing ones
+IIgnore errorsIgnore errors (exclude from health checks)
-DRemove flagRe-enable

Sticky Session​

Configure so the same user always connects to the same server for session-based applications.

<Proxy "balancer://mycluster">
BalancerMember "http://10.0.0.1:8080" route=server1
BalancerMember "http://10.0.0.2:8080" route=server2
BalancerMember "http://10.0.0.3:8080" route=server3

ProxySet lbmethod=byrequests
ProxySet stickysession=JSESSIONID # Tomcat's default session cookie name
</Proxy>

Set jvmRoute in Tomcat's server.xml:

<!-- server.xml -->
<Engine name="Catalina" defaultHost="localhost" jvmRoute="server1">

Tomcat then appends .server1 to session IDs:

Set-Cookie: JSESSIONID=ABC123.server1; Path=/

Apache reads this cookie and routes to the server with route=server1.


Balancer Manager (Web Management Interface)​

Apache provides a management page to monitor load balancer status and change settings in real time from a browser.

<Location "/balancer-manager">
SetHandler balancer-manager
Require ip 127.0.0.1 10.0.0.0/8 # Allow internal network only
</Location>
# Enable and reload
sudo a2enconf balancer-manager
sudo systemctl reload apache2

# Access
curl http://localhost/balancer-manager

What you can do from the management page:

  • View status, request count, and error count for each server
  • Disable/enable servers (during maintenance)
  • Change weights (loadfactor) in real time
  • Reset session data

Production Configuration: Complete Load Balancer Setup​

# /etc/apache2/sites-available/production-lb.conf

<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com

ProxyRequests Off
ProxyPreserveHost On

# Main app cluster
<Proxy "balancer://appcluster">
BalancerMember "http://10.0.0.1:8080" loadfactor=3 retry=5 route=jvm1
BalancerMember "http://10.0.0.2:8080" loadfactor=3 retry=5 route=jvm2
BalancerMember "http://10.0.0.3:8080" loadfactor=1 retry=5 route=jvm3 status=+H

ProxySet lbmethod=bybusyness
ProxySet stickysession=JSESSIONID
ProxySet nofailover=Off
</Proxy>

# Static file cluster
<Proxy "balancer://staticcluster">
BalancerMember "http://10.0.1.1:80" loadfactor=1
BalancerMember "http://10.0.1.2:80" loadfactor=1
ProxySet lbmethod=byrequests
</Proxy>

# Static files: dedicated cluster
ProxyPass "/static/" "balancer://staticcluster/static/"
ProxyPassReverse "/static/" "balancer://staticcluster/static/"

# Admin page: single server (exclude from load balancing)
ProxyPass "/admin/" "http://10.0.0.1:8080/admin/"
ProxyPassReverse "/admin/" "http://10.0.0.1:8080/admin/"

# All other requests: app cluster
ProxyPass "/" "balancer://appcluster/"
ProxyPassReverse "/" "balancer://appcluster/"

ProxyTimeout 60

# Balancer Manager (internal access only)
<Location "/balancer-manager">
SetHandler balancer-manager
Require ip 127.0.0.1 10.0.0.0/8
</Location>

CustomLog /var/log/apache2/lb-access.log combined
ErrorLog /var/log/apache2/lb-error.log
</VirtualHost>

Algorithm Selection Guide​

SituationRecommended lbmethod
Simple even distribution, identical specsbyrequests
File downloads, media streamingbytraffic
API servers, variable processing timesbybusyness
Existing app without session sharingbyrequests + stickysession

The next page covers AJP-based load balancing with mod_jk.