Nginx as Load Balancer
Nginx can distribute requests between multiple backends (round-robin, least connections, IP hash) for scalability and high availability.
Architecture
Client → Nginx (Load Balancer) → Backend 1 (10.0.0.1)
→ Backend 2 (10.0.0.2)
→ Backend 3 (10.0.0.3)
Basic configuration (Round Robin)
nano /etc/nginx/conf.d/loadbalancer.conf
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;
}
}
nginx -t && systemctl reload nginx
Load balancing algorithms
Round Robin (default)
Distributes requests in cyclic sequence. Simple and fair if backends are equivalent.
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.
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.
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)
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;
}
Backup servers (failover)
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
}
Passive health check
Nginx automatically removes backends that don't respond:
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
Load Balancer with SSL (SSL termination)
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;
}
TCP/UDP Load Balancing (stream)
To balance non-HTTP traffic (MySQL, Redis, games):
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 {}.
Monitoring and debug
# 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;
}
curl http://localhost/nginx_status
Output:
Active connections: 12
server accepts handled requests
1234 1234 5678
Reading: 0 Writing: 1 Waiting: 11
Load balancing test
# 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.
Gerelateerde artikelen
