Raja's Exocortex

Nginx Stateful Load Balancing

  1. Sample standalone nginx config to statefully load balance HTTP requests.
  2. Reuses Tomcat/Java JSESSIONID cookie to statefully load balance between multiple backends.
  3. Nginx itself is completely stateless and can be round-robin load balanced from a firewall.

Limitations/Notes

  1. Nginx open source does not support extensive health checking, use varnish or haproxy instead.
  2. The JVM guarantees that JSESSIONID is unique only to a single tomcat instance. To guarantee unique JSESSIONID across the Tomcat cluster, it is recommended to append the tomcat hostname to the JSESSIONID cookie.

Complete nginx config

# Nginx sample standalone config for active/active load balancing to
# a stateful backend.

# Note: nginx itself is fully stateless, therefore can be run active/active
# Note2: nginx uses JSESSIONID as the hash to statefully load balance the backend

daemon off;

error_log  /dev/stderr;

events {}

http {

    map $cookie_JSESSIONID $session_cookie {
        ""      $remote_port;           # no cookie, randomly assign a backend
        default $cookie_JSESSIONID;     # with cookie, choose stateful backend
    }

    upstream tomcat_backend {
        hash $session_cookie consistent;
        server tomcat1:8080 max_fails=3 fail_timeout=5s;  # use backend server IPs to avoid DNS failures
        server tomcat2:8080 max_fails=3 fail_timeout=5s;  # use backend server IPs to avoid DNS failures
    }

    server {

        listen 80;

        access_log /dev/stdout;
        root /dev/null;

        location / {
            proxy_pass_request_headers on;
            proxy_pass http://tomcat_backend;
        }
    }
}

Testing

To test this without a Tomcat application, an easy way is to use Apache/PHP and set PHP to use the same session cookie as Tomcat. This PHP script can be hosted on backend PHP servers with the nginx as an upstream load balancer.

<?php

// index.php to change PHP use Java session ID cookie

session_name('JSESSIONID');

session_start();

echo '<h1>Welcome</h1>';

echo '<h1>SERVER_PORT: ' . 9001 . '/<h1>';

echo '<h1>count: ' . $_SESSION['count']++ . '</h1>';