Load Balancing
Este documento explica como implementar balanceamento de carga para n8n em ambiente de produção, abordando configuração de nginx como proxy reverso, distribuição de requisições entre múltiplas instâncias, health checks automáticos, failover inteligente, e estratégias de alta disponibilidade que garantem performance consistente e tolerância a falhas em implementações empresariais de grande escala.
Configuração Básica
Upstream para Diferentes Tipos de Tráfego
upstream n8n_api {
least_conn;
server n8n-1:5678 max_fails=3 fail_timeout=30s;
server n8n-2:5678 max_fails=3 fail_timeout=30s;
server n8n-3:5678 max_fails=3 fail_timeout=30s;
}
upstream n8n_webhooks {
ip_hash; # Sticky sessions para webhooks
server n8n-1:5678 max_fails=3 fail_timeout=30s;
server n8n-2:5678 max_fails=3 fail_timeout=30s;
server n8n-3:5678 max_fails=3 fail_timeout=30s;
}
upstream n8n_ui {
round_robin;
server n8n-1:5678 max_fails=3 fail_timeout=30s;
server n8n-2:5678 max_fails=3 fail_timeout=30s;
server n8n-3:5678 max_fails=3 fail_timeout=30s;
}
Configuração Nginx
Configuração Básica
events {
worker_connections 1024;
use epoll;
multi_accept on;
}
http {
# Configurações básicas
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
client_max_body_size 100M;
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml+rss
application/atom+xml
image/svg+xml;
# Rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=webhook:10m rate=30r/s;
limit_req_zone $binary_remote_addr zone=ui:10m rate=5r/s;
# Upstream para n8n
upstream n8n_backend {
least_conn;
server n8n-1:5678 max_fails=3 fail_timeout=30s;
server n8n-2:5678 max_fails=3 fail_timeout=30s;
server n8n-3:5678 max_fails=3 fail_timeout=30s;
keepalive 32;
}
# Incluir configurações do site
include /etc/nginx/sites-enabled/*;
}
Configuração do Site
# /etc/nginx/sites-available/n8n
server {
listen 443 ssl http2;
server_name seudominio.com www.seudominio.com;
# Certificados SSL
ssl_certificate /etc/letsencrypt/live/seudominio.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/seudominio.com/privkey.pem;
# Configurações SSL
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# API endpoints com rate limiting
location /api/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://n8n_backend;
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;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# Health check
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
}
# Webhook endpoints com rate limiting
location /webhook/ {
limit_req zone=webhook burst=50 nodelay;
proxy_pass http://n8n_backend;
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;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
# Timeouts maiores para webhooks
proxy_connect_timeout 120s;
proxy_send_timeout 120s;
proxy_read_timeout 120s;
# Health check
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
}
# Interface de usuário
location / {
limit_req zone=ui burst=10 nodelay;
proxy_pass http://n8n_backend;
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;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Health check
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
}
}
Configuração Avançada
upstream n8n_backend {
least_conn;
# Servidores com health checks
server n8n-1:5678 max_fails=3 fail_timeout=30s;
server n8n-2:5678 max_fails=3 fail_timeout=30s;
server n8n-3:5678 max_fails=3 fail_timeout=30s;
# Configurações de keepalive
keepalive 32;
keepalive_requests 100;
keepalive_timeout 60s;
}
# Health check endpoint
location /healthz {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
Configuração com Sticky Sessions
# Para webhooks que precisam de sessão consistente
upstream n8n_webhooks {
ip_hash;
server n8n-1:5678 max_fails=3 fail_timeout=30s;
server n8n-2:5678 max_fails=3 fail_timeout=30s;
server n8n-3:5678 max_fails=3 fail_timeout=30s;
}
# Para API e UI que podem ser distribuídas
upstream n8n_api {
least_conn;
server n8n-1:5678 max_fails=3 fail_timeout=30s;
server n8n-2:5678 max_fails=3 fail_timeout=30s;
server n8n-3:5678 max_fails=3 fail_timeout=30s;
}
HAProxy Alternativa
Configuração HAProxy
# haproxy.cfg
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
user haproxy
group haproxy
daemon
maxconn 4096
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
option redispatch
retries 3
# Frontend para HTTPS
frontend n8n_https
bind *:443 ssl crt /etc/ssl/certs/n8n.pem
mode http
# ACLs para diferentes tipos de tráfego
acl is_api path_beg /api/
acl is_webhook path_beg /webhook/
acl is_health path /healthz
# Rate limiting
stick table type ip size 100k expire 30s store http_req_rate(10s)
http-request track-sc0 src
http-request deny deny_status 429 if { sc_http_req_rate(0) gt 10 }
# Roteamento baseado em ACLs
use_backend n8n_webhooks if is_webhook
use_backend n8n_api if is_api
use_backend n8n_ui if !is_api !is_webhook !is_health
use_backend n8n_health if is_health
# Backend para webhooks (sticky sessions)
backend n8n_webhooks
balance roundrobin
option httpchk GET /healthz
http-check expect status 200
# Servidores
server n8n-1 n8n-1:5678 check maxconn 100 cookie n8n-1
server n8n-2 n8n-2:5678 check maxconn 100 cookie n8n-2
server n8n-3 n8n-3:5678 check maxconn 100 cookie n8n-3
# Configurações de failover
option redispatch
retries 3
timeout connect 5s
timeout server 30s
# Backend para API
backend n8n_api
balance leastconn
option httpchk GET /healthz
http-check expect status 200
server n8n-1 n8n-1:5678 check maxconn 100
server n8n-2 n8n-2:5678 check maxconn 100
server n8n-3 n8n-3:5678 check maxconn 100
# Backend para UI
backend n8n_ui
balance roundrobin
option httpchk GET /healthz
http-check expect status 200
server n8n-1 n8n-1:5678 check maxconn 100
server n8n-2 n8n-2:5678 check maxconn 100
server n8n-3 n8n-3:5678 check maxconn 100
# Backend para health check
backend n8n_health
http-request return status 200 content-type text/plain string "healthy\n"
Health Checks
Script de Health Check
#!/bin/bash
# Configurações
N8N_HOST="localhost"
N8N_PORT="5678"
HEALTH_ENDPOINT="/healthz"
# Verificar saúde do n8n
if curl -f -s --max-time 5 "http://$N8N_HOST:$N8N_PORT$HEALTH_ENDPOINT" > /dev/null; then
echo "OK: n8n está saudável"
exit 0
else
echo "ERROR: n8n não está respondendo"
exit 1
fi
Monitoramento de Failover
#!/bin/bash
# Configurações
BACKEND_SERVERS=("n8n-1" "n8n-2" "n8n-3")
WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
echo "=== Monitoramento do Load Balancer ==="
echo
# Verificar cada servidor
for server in "${BACKEND_SERVERS[@]}"; do
if curl -f -s --max-time 5 "http://$server:5678/healthz" > /dev/null; then
echo "✅ $server: Saudável"
else
echo "❌ $server: Não respondendo"
# Enviar notificação
curl -X POST $WEBHOOK_URL \
-H "Content-type: application/json" \
-d "{\"text\":\"🚨 Servidor $server não está respondendo!\"}"
# Tentar reiniciar o container
docker restart $server
fi
done
echo
# Verificar distribuição de carga
echo "=== Distribuição de Carga ==="
for server in "${BACKEND_SERVERS[@]}"; do
CONNECTIONS=$(docker exec $server netstat -an | grep :5678 | grep ESTABLISHED | wc -l)
echo "$server: $CONNECTIONS conexões ativas"
done
Monitoramento de Performance
Métricas Essenciais
#!/bin/bash
echo "=== Métricas do Load Balancer ==="
echo
echo "1. Status do Nginx:"
systemctl status nginx --no-pager -l
echo
echo "2. Configuração do Nginx:"
nginx -t
echo
echo "3. Logs de Erro (últimas 10 linhas):"
tail -10 /var/log/nginx/error.log
echo
echo "4. Estatísticas de Conexões:"
netstat -an | grep :80 | grep ESTABLISHED | wc -l
netstat -an | grep :443 | grep ESTABLISHED | wc -l
echo
echo "5. Distribuição de Carga:"
for server in n8n-1 n8n-2 n8n-3; do
CONNECTIONS=$(docker exec $server netstat -an | grep :5678 | grep ESTABLISHED | wc -l)
echo "$server: $CONNECTIONS conexões"
done
echo
echo "6. Performance do Nginx:"
curl -s http://localhost/nginx_status
Alertas Automáticos
#!/bin/bash
# Configurações
ALERT_THRESHOLD_CONNECTIONS=1000
ALERT_THRESHOLD_ERROR_RATE=50
WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
# Verificar muitas conexões
TOTAL_CONNECTIONS=$(netstat -an | grep :443 | grep ESTABLISHED | wc -l)
if [ $TOTAL_CONNECTIONS -gt $ALERT_THRESHOLD_CONNECTIONS ]; then
curl -X POST $WEBHOOK_URL \
-H "Content-type: application/json" \
-d "{\"text\":\"⚠️ Muitas conexões: $TOTAL_CONNECTIONS\"}"
fi
# Verificar taxa de erro
ERROR_RATE=$(tail -100 /var/log/nginx/access.log | grep -E " 5[0-9][0-9] " | wc -l)
if [ $ERROR_RATE -gt $ALERT_THRESHOLD_ERROR_RATE ]; then
curl -X POST $WEBHOOK_URL \
-H "Content-type: application/json" \
-d "{\"text\":\"⚠️ Taxa de erro alta: $ERROR_RATE erros\"}"
fi
Configurações de Segurança
Rate Limiting
# Configuração avançada de rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=webhook:10m rate=30r/s;
limit_req_zone $binary_remote_addr zone=ui:10m rate=5r/s;
# Headers de segurança
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https:; connect-src 'self' https: wss:;" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
Configuração Completa
server {
listen 443 ssl http2;
server_name seudominio.com;
# SSL configuration
ssl_certificate /etc/letsencrypt/live/seudominio.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/seudominio.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
# Content security policy para n8n
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self' https: wss:; frame-ancestors 'none';" always;
# Proxy configuration
location / {
proxy_pass http://n8n_backend;
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;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Troubleshooting
Problemas Comuns
#!/bin/bash
echo "=== Diagnóstico do Load Balancer ==="
echo
echo "1. Verificar configuração do nginx:"
nginx -t
echo
echo "2. Verificar status dos servidores:"
for server in n8n-1 n8n-2 n8n-3; do
echo "=== $server ==="
curl -I http://$server:5678/healthz
done
echo
echo "3. Verificar logs de erro:"
grep "limiting requests" /var/log/nginx/error.log
echo
echo "4. Verificar configuração de SSL:"
openssl s_client -connect seudominio.com:443 -servername seudominio.com
Checklist de Produção
Configuração
- Nginx instalado e configurado
- SSL/TLS configurado
- Upstreams definidos corretamente
- Health checks configurados
- Rate limiting implementado
Performance
- Gzip compression ativado
- Keepalive configurado
- Timeouts otimizados
- Worker processes adequados
- Cache configurado
Segurança
- Headers de segurança configurados
- Rate limiting implementado
- SSL/TLS configurado
- Acesso restrito por IP
- Logs de acesso ativados
Monitoramento
- Health checks configurados
- Alertas configurados
- Métricas sendo coletadas
- Logs estruturados
- Dashboard de monitoramento
Dica Pro
Configure sticky sessions para webhooks que precisam de estado consistente e use least connections para distribuição equilibrada de carga.
Importante
Sempre teste o load balancing em ambiente de desenvolvimento antes de aplicar em produção. Monitore a distribuição de carga e ajuste conforme necessário.