Pular para o conteúdo principal

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.