mcpField
L
load-balancing

load-balancing

github.com/bagelhole云与 DevOps1.2k341 次安装23 周前更新
代码仓库

关于 load-balancing

load-balancing 是一项配置应用服务器流量分发的技能,适用于运维和开发人员。内容涵盖 nginx、HAProxy 与 AWS 负载均衡器的配置、算法及故障排查。

主要功能

  1. 01配置 nginx 与 HAProxy
  2. 02设置 AWS ALB 和 NLB
  3. 03选择流量分配算法
  4. 04配置健康检查与会话保持
  5. 05排查 TLS、超时及后端故障

适用场景

  1. 01将 HTTP/HTTPS 流量分发到多台服务器
  2. 02通过健康检查绕过故障实例
  3. 03为蓝绿或金丝雀发布调整流量
  4. 04在负载均衡器终止 TLS

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/bagelhole/devops-security-agent-skills --skill load-balancing

安装后在 Claude Code 中输入/load-balancing确认已加载。

详细介绍

负载均衡

将流量分发到应用服务器,以实现高可用性、可扩展性和容错能力。

适用场景

  • 将 HTTP/HTTPS 流量分发到多台后端服务器。
  • 实施运行状况检查,以绕过运行异常的实例。
  • 在负载均衡器处终止 TLS,简化证书管理。
  • 通过流量切换实现蓝绿部署或金丝雀部署。
  • 在单一入口后进行水平扩展。

前置条件

  • 两台或更多运行相同应用的后端服务器。
  • 用于终止 HTTPS 的 TLS 证书(ACM、Let's Encrypt,或供内部使用的自签名证书)。
  • 对于 AWS:在多个可用区中包含公有和私有子网的 VPC。
  • 对于 nginx/HAProxy:拥有 root 访问权限的 Linux 服务器。

nginx 负载均衡器

基本轮询
# /etc/nginx/conf.d/loadbalancer.conf
upstream app_backend {
    server 10.0.1.10:8080;
    server 10.0.1.11:8080;
    server 10.0.1.12:8080;
}

server {
    listen 80;
    server_name app.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name app.example.com;

    ssl_certificate     /etc/ssl/certs/app.example.com.pem;
    ssl_certificate_key /etc/ssl/private/app.example.com-key.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;

    location / {
        proxy_pass http://app_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_connect_timeout 5s;
        proxy_read_timeout 30s;
        proxy_send_timeout 30s;
    }

    location /health {
        access_log off;
        return 200 "OK";
    }
}
加权和备用服务器
upstream app_backend {
    least_conn;  # Route to server with fewest active connections

    server 10.0.1.10:8080 weight=5;      # Gets 5x traffic
    server 10.0.1.11:8080 weight=3;      # Gets 3x traffic
    server 10.0.1.12:8080 weight=1;      # Gets 1x traffic
    server 10.0.1.20:8080 backup;        # Only used when others are down
    server 10.0.1.21:8080 down;          # Temporarily removed from pool
}
运行状况检查(nginx Plus / OpenResty)
upstream app_backend {
    zone backend 64k;  # Shared memory zone for health data

    server 10.0.1.10:8080;
    server 10.0.1.11:8080;
    server 10.0.1.12:8080;
}

# Health check (requires nginx Plus or third-party module)
# match healthy {
#     status 200;
#     body ~ "OK";
# }
# health_check interval=5s fails=3 passes=2 match=healthy;
粘性会话(IP 哈希)
upstream app_backend {
    ip_hash;  # Same client IP always goes to the same server
    server 10.0.1.10:8080;
    server 10.0.1.11:8080;
    server 10.0.1.12:8080;
}

HAProxy 配置

完整的生产环境配置
# /etc/haproxy/haproxy.cfg
global
    log /dev/log local0
    maxconn 4096
    daemon
    ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
    ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11
    tune.ssl.default-dh-param 2048

defaults
    mode http
    log global
    option httplog
    option dontlognull
    option forwardfor
    timeout connect 5s
    timeout client  30s
    timeout server  30s
    timeout http-request 10s
    timeout http-keep-alive 5s
    retries 3

frontend http_front
    bind *:80
    redirect scheme https code 301 if !{ ssl_fc }

frontend https_front
    bind *:443 ssl crt /etc/ssl/certs/app.example.com.pem
    http-request set-header X-Forwarded-Proto https

    # Route based on path
    acl is_api path_beg /api/
    acl is_ws  path_beg /ws/

    use_backend api_servers if is_api
    use_backend ws_servers  if is_ws
    default_backend web_servers

backend web_servers
    balance roundrobin
    option httpchk GET /health HTTP/1.1\r\nHost:\ app.example.com
    http-check expect status 200

    cookie SERVERID insert indirect nocache
    server web1 10.0.1.10:8080 check inter 5s fall 3 rise 2 cookie web1
    server web2 10.0.1.11:8080 check inter 5s fall 3 rise 2 cookie web2
    server web3 10.0.1.12:8080 check inter 5s fall 3 rise 2 cookie web3

backend api_servers
    balance leastconn
    option httpchk GET /api/health
    http-check expect status 200

    server api1 10.0.2.10:8080 check inter 5s fall 3 rise 2
    server api2 10.0.2.11:8080 check inter 5s fall 3 rise 2

backend ws_servers
    balance source
    option httpchk GET /health
    timeout tunnel 1h

    server ws1 10.0.3.10:8080 check inter 5s fall 3 rise 2
    server ws2 10.0.3.11:8080 check inter 5s fall 3 rise 2

listen stats
    bind *:8404
    stats enable
    stats uri /stats
    stats refresh 10s
    stats admin if LOCALHOST
HAProxy 管理
# Test config before reloading
haproxy -c -f /etc/haproxy/haproxy.cfg

# Reload without dropping connections
sudo systemctl reload haproxy

# View stats from CLI
echo "show stat" | sudo socat stdio /var/run/haproxy/admin.sock

# Drain a server (stop new connections, let existing finish)
echo "set server web_servers/web1 state drain" | sudo socat stdio /var/run/haproxy/admin.sock

# Set server to maintenance
echo "set server web_servers/web1 state maint" | sudo socat stdio /var/run/haproxy/admin.sock

# Re-enable server
echo "set server web_servers/web1 state ready" | sudo socat stdio /var/run/haproxy/admin.sock

AWS 应用程序负载均衡器(ALB)

通过 CLI 创建 ALB
# Create the load balancer
aws elbv2 create-load-balancer \
  --name my-app-alb \
  --subnets subnet-aaa111 subnet-bbb222 \
  --security-groups sg-xxx123 \
  --type application \
  --scheme internet-facing

# Create a target group
aws elbv2 create-target-group \
  --name my-app-targets \
  --protocol HTTP \
  --port 8080 \
  --vpc-id vpc-xxx123 \
  --health-check-protocol HTTP \
  --health-check-path /health \
  --health-check-interval-seconds 15 \
  --healthy-threshold-count 2 \
  --unhealthy-threshold-count 3 \
  --target-type instance

# Register targets
aws elbv2 register-targets \
  --target-group-arn arn:aws:elasticloadbalancing:us-east-1:123456:targetgroup/my-app-targets/abc123 \
  --targets Id=i-0123456789abc Id=i-0987654321def

# Create HTTPS listener
aws elbv2 create-listener \
  --load-balancer-arn arn:aws:elasticloadbalancing:us-east-1:123456:loadbalancer/app/my-app-alb/abc123 \
  --protocol HTTPS \
  --port 443 \
  --certificates CertificateArn=arn:aws:acm:us-east-1:123456:certificate/abc-123 \
  --default-actions Type=forward,TargetGroupArn=arn:aws:elasticloadbalancing:us-east-1:123456:targetgroup/my-app-targets/abc123

# Create HTTP redirect listener
aws elbv2 create-listener \
  --load-balancer-arn arn:aws:elasticloadbalancing:us-east-1:123456:loadbalancer/app/my-app-alb/abc123 \
  --protocol HTTP \
  --port 80 \
  --default-actions Type=redirect,RedirectConfig='{Protocol=HTTPS,Port=443,StatusCode=HTTP_301}'
检查目标运行状况
# Check health of registered targets
aws elbv2 describe-target-health \
  --target-group-arn arn:aws:elasticloadbalancing:us-east-1:123456:targetgroup/my-app-targets/abc123

AWS 网络负载均衡器(NLB)

# Create NLB (for TCP, UDP, or TLS traffic)
aws elbv2 create-load-balancer \
  --name my-tcp-nlb \
  --subnets subnet-aaa111 subnet-bbb222 \
  --type network \
  --scheme internet-facing

# Create TCP target group
aws elbv2 create-target-group \
  --name my-tcp-targets \
  --protocol TCP \
  --port 5432 \
  --vpc-id vpc-xxx123 \
  --health-check-protocol TCP \
  --target-type ip

使用 Terraform 配置 ALB

resource "aws_lb" "app" {
  name               = "my-app-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.alb.id]
  subnets            = var.public_subnet_ids

  enable_deletion_protection = true
}

resource "aws_lb_target_group" "app" {
  name     = "my-app-tg"
  port     = 8080
  protocol = "HTTP"
  vpc_id   = var.vpc_id

  health_check {
    path                = "/health"
    port                = "traffic-port"
    healthy_threshold   = 2
    unhealthy_threshold = 3
    timeout             = 5
    interval            = 15
    matcher             = "200"
  }

  deregistration_delay = 30

  stickiness {
    type            = "lb_cookie"
    cookie_duration = 86400
    enabled         = true
  }
}

resource "aws_lb_listener" "https" {
  load_balancer_arn = aws_lb.app.arn
  port              = 443
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-TLS13-1-2-2021-06"
  certificate_arn   = aws_acm_certificate.cert.arn

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.app.arn
  }
}

resource "aws_lb_listener" "http_redirect" {
  load_balancer_arn = aws_lb.app.arn
  port              = 80
  protocol          = "HTTP"

  default_action {
    type = "redirect"
    redirect {
      port        = "443"
      protocol    = "HTTPS"
      status_code = "HTTP_301"
    }
  }
}

负载均衡算法

算法使用场景nginxHAProxy
轮询默认模式,服务器权重相同(default)balance roundrobin
最少连接数请求时长不一least_connbalance leastconn
IP 哈希无需 Cookie 的会话持久性ip_hashbalance source
URI 哈希按 URL 实现缓存局部性hash $request_uribalance uri
两次随机选择大型服务器池random two least_connbalance random(2)

故障排查

症状原因解决方法
所有后端均显示“unhealthy”运行状况检查路径返回非 200 状态码确认 /health 端点返回 200;检查安全组
502 Bad Gateway后端未运行或端口错误确认后端正在配置的端口上监听
流量分配不均粘性会话或加权配置检查会话亲和性设置;检查服务器权重
连接超时后端响应过慢或超时时间过短增大 proxy_read_timeout 或 HAProxy 的 timeout server
TLS 握手失败证书不匹配或已过期确认证书与域名匹配;若已过期则续期
ALB 返回 503未注册健康目标检查目标组运行状况;确认目标位于正确的子网中
WebSocket 连接断开代理未配置升级添加 proxy_set_header Upgrade 和 Connection "upgrade"

相关技能

评论

支持 Markdown