Nginx as Load Balancer

Nginx can distribute requests between multiple backends (round-robin, least connections, IP hash) for scalability and high availability.

02

Architecture

Client → Nginx (Load Balancer) → Backend 1 (10.0.0.1) → Backend 2 (10.0.0.2) → Backend 3 (10.0.0.3)
03

Basic configuration (Round Robin)

bash
nano /etc/nginx/conf.d/loadbalancer.conf
nginx
upstream backend_pool {
    server 10.0.0.1:8080;
    server 10.0.0.2:8080;
    server 10.0.0.3:8080;
}

server {
    listen 80;
    server_name yourdomain.com;

    location / {
        proxy_pass http://backend_pool;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Timeout
        proxy_connect_timeout 10s;
        proxy_send_timeout 30s;
        proxy_read_timeout 30s;
    }
}
bash
nginx -t && systemctl reload nginx
04

Load balancing algorithms

Round Robin (default)

Distributes requests in cyclic sequence. Simple and fair if backends are equivalent.

nginx
upstream backend_pool {
    server 10.0.0.1:8080;
    server 10.0.0.2:8080;
    server 10.0.0.3:8080;
}

Least Connections

Sends request to the server with the fewest active connections. Ideal if requests have variable duration.

nginx
upstream backend_pool {
    least_conn;
    server 10.0.0.1:8080;
    server 10.0.0.2:8080;
    server 10.0.0.3:8080;
}

IP Hash (sticky sessions)

Each IP is always sent to the same backend. Necessary for apps with server-side sessions.

nginx
upstream backend_pool {
    ip_hash;
    server 10.0.0.1:8080;
    server 10.0.0.2:8080;
    server 10.0.0.3:8080;
}

Weights (servers with different capacity)

nginx
upstream backend_pool {
    server 10.0.0.1:8080 weight=3;   # receives 3x traffic
    server 10.0.0.2:8080 weight=2;
    server 10.0.0.3:8080 weight=1;
}
05

Backup servers (failover)

nginx
upstream backend_pool {
    server 10.0.0.1:8080;
    server 10.0.0.2:8080;
    server 10.0.0.3:8080 backup;   # used only if others are down
}
06

Passive health check

Nginx automatically removes backends that don't respond:

nginx
upstream backend_pool {
    server 10.0.0.1:8080 max_fails=3 fail_timeout=30s;
    server 10.0.0.2:8080 max_fails=3 fail_timeout=30s;
    server 10.0.0.3:8080 max_fails=3 fail_timeout=30s;
}

Active health check (health_check directive) is only available in Nginx Plus (commercial version). On open source Nginx use passive health check or an external tool like Keepalived.

  • max_fails=3: after 3 consecutive errors the backend is marked down
  • fail_timeout=30s: after 30s tries again
07

Load Balancer with SSL (SSL termination)

nginx
upstream backend_pool {
    server 10.0.0.1:8080;
    server 10.0.0.2:8080;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;

    # Backends receive unencrypted HTTP (faster)
    location / {
        proxy_pass http://backend_pool;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
    }
}

server {
    listen 80;
    return 301 https://$host$request_uri;
}
08

TCP/UDP Load Balancing (stream)

To balance non-HTTP traffic (MySQL, Redis, games):

nginx
stream {
    upstream mysql_pool {
        server 10.0.0.1:3306;
        server 10.0.0.2:3306;
    }

    server {
        listen 3306;
        proxy_pass mysql_pool;
        proxy_timeout 10s;
        proxy_connect_timeout 5s;
    }
}

The stream {} block must be at the main level of nginx.conf, NOT inside http {}.

09

Monitoring and debug

bash
# Real-time status
tail -f /var/log/nginx/access.log

# See upstream where traffic comes from
log_format upstream '$remote_addr - [$time_local] "$request" '
                    '$status $upstream_addr $upstream_response_time';

# Statistics (if nginx-extras installed)
location /nginx_status {
    stub_status;
    allow 127.0.0.1;
    deny all;
}
bash
curl http://localhost/nginx_status

Output:

Active connections: 12 server accepts handled requests 1234 1234 5678 Reading: 0 Writing: 1 Waiting: 11
10

Load balancing test

bash
# Verify which backend responds to requests
for i in {1..6}; do
  curl -s http://yourdomain.com/api/whoami
  echo
done

If backends return their hostname, you'll see alternation between them.

DeluxHost, gegründet 2023, bietet hochwertige Hosting-Lösungen für verschiedene digitale Anforderungen. Wir bieten Shared Hosting, VPS und dedizierte Server mit erweiterter Sicherheit und globalen Rechenzentren.

© DeluxHost, Alle Rechte vorbehalten. | USt-IdNr.: IT17734661006
Alle Systeme betriebsbereit