关于 load-balancing
load-balancing 是一项配置应用服务器流量分发的技能,适用于运维和开发人员。内容涵盖 nginx、HAProxy 与 AWS 负载均衡器的配置、算法及故障排查。
主要功能
- 01配置 nginx 与 HAProxy
- 02设置 AWS ALB 和 NLB
- 03选择流量分配算法
- 04配置健康检查与会话保持
- 05排查 TLS、超时及后端故障
适用场景
- 01将 HTTP/HTTPS 流量分发到多台服务器
- 02通过健康检查绕过故障实例
- 03为蓝绿或金丝雀发布调整流量
- 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"
}
}
}
负载均衡算法
| 算法 | 使用场景 | nginx | HAProxy |
|---|---|---|---|
| 轮询 | 默认模式,服务器权重相同 | (default) | balance roundrobin |
| 最少连接数 | 请求时长不一 | least_conn | balance leastconn |
| IP 哈希 | 无需 Cookie 的会话持久性 | ip_hash | balance source |
| URI 哈希 | 按 URL 实现缓存局部性 | hash $request_uri | balance uri |
| 两次随机选择 | 大型服务器池 | random two least_conn | balance 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" |
相关技能
- reverse-proxy - 反向代理配置模式
- dns-management - 指向负载均衡器的 DNS 记录
- cdn-setup - 在负载均衡源站前部署 CDN
- service-mesh - Kubernetes 中的服务级负载均衡
评论
支持 Markdown