负载均衡器设置 load-balancer-setup

部署和配置负载均衡器以在多个后端服务器之间分配流量,确保高可用性、容错性和基础设施资源的最优利用。关键词:负载均衡器、HAProxy、AWS ALB、健康检查、SSL/TLS、DDoS 缓解。

DevOps 0 次安装 0 次浏览 更新于 3/4/2026

负载均衡器设置

概览

部署和配置负载均衡器以在多个后端服务器之间分配流量,确保高可用性、容错性和基础设施资源的最优利用。

何时使用

  • 多服务器流量分配
  • 高可用性和故障转移
  • 会话持久性和粘性会话
  • 健康检查和自动恢复
  • SSL/TLS 终止
  • 跨区域负载均衡
  • 在负载均衡器处进行 API 速率限制
  • DDoS 缓解

实施示例

1. HAProxy 配置

# /etc/haproxy/haproxy.cfg
global
    log stdout local0
    log stdout local1 notice
    maxconn 4096
    daemon

    # 安全
    tune.ssl.default-dh-param 2048
    ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
    ssl-default-bind-options ssl-min-ver TLSv1.2

defaults
    log global
    mode http
    option httplog
    option denylogin
    option forwardfor
    option http-server-close

    # 超时
    timeout connect 5000
    timeout client 50000
    timeout server 50000

    # 统计
    stats enable
    stats uri /stats
    stats refresh 30s
    stats admin if TRUE

# 前端 - 面向公众
frontend web_frontend
    bind *:80
    bind *:443 ssl crt /etc/ssl/certs/myapp.pem
    mode http
    option httplog

    # 将 HTTP 重定向到 HTTPS
    http-request redirect scheme https if !{ ssl_fc }

    # 日志记录
    log /dev/log local0 debug

    # 速率限制
    stick-table type ip size 100k expire 30s store http_req_rate(10s)
    http-request track-sc0 src
    http-request deny if { sc_http_req_rate(0) gt 100 }

    # ACLs
    acl is_websocket hdr(Upgrade) -i websocket
    acl is_api path_beg /api/
    acl is_health path /health
    acl is_static path_beg /static/

    # 路由到适当的后端
    use_backend health_backend if is_health
    use_backend api_backend if is_api
    use_backend static_backend if is_static
    use_backend web_backend if is_websocket
    default_backend web_backend

# 前端用于内部 API
frontend internal_api_frontend
    bind 127.0.0.1:8080
    mode http
    default_backend stats_backend

# 健康检查后端
backend health_backend
    mode http
    balance roundrobin
    server local 127.0.0.1:8080 check

# 主要 Web 后端
backend web_backend
    mode http
    balance roundrobin

    # 会话持久性
    cookie SERVERID insert indirect nocache

    # 压缩
    compression algo gzip
    compression type text/html text/plain text/css application/json

    # 带有健康检查的服务器
    server web1 10.0.1.10:8080 check cookie web1 weight 5
    server web2 10.0.1.11:8080 check cookie web2 weight 5
    server web3 10.0.1.12:8080 check cookie web3 weight 3

    # 健康检查配置
    option httpchk GET /health HTTP/1.1\r
Host:\ localhost
    timeout check 5s

# API 后端与连接限制
backend api_backend
    mode http
    balance least_conn
    maxconn 1000

    option httpchk GET /api/health
    timeout check 5s

    server api1 10.0.2.10:3000 check weight 5
    server api2 10.0.2.11:3000 check weight 5
    server api3 10.0.2.12:3000 check weight 3

# 静态文件后端
backend static_backend
    mode http
    balance roundrobin

    # 静态文件的缓存控制
    http-response set-header Cache-Control "public, max-age=31536000, immutable"

    server static1 10.0.3.10:80 check
    server static2 10.0.3.11:80 check

# 统计后端
backend stats_backend
    stats enable
    stats uri /stats
    stats refresh 30s

2. AWS 应用负载均衡器(CloudFormation)

# aws-alb-cloudformation.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: '带有目标组的应用负载均衡器'

Parameters:
  VpcId:
    Type: AWS::EC2::VPC::Id
    Description: VPC ID
  SubnetIds:
    Type: List<AWS::EC2::Subnet::Id>
    Description: ALB 的公共子网 ID
  Environment:
    Type: String
    Default: production
    AllowedValues: [dev, staging, production]

Resources:
  # ALB 的安全组
  LoadBalancerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: ALB 的安全组
      VpcId: !Ref VpcId
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 0.0.0.0/0
      SecurityGroupEgress:
        - IpProtocol: -1
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-alb-sg'

  # 应用负载均衡器
  ApplicationLoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Name: !Sub '${Environment}-alb'
      Type: application
      Scheme: internet-facing
      SecurityGroups:
        - !Ref LoadBalancerSecurityGroup
      Subnets: !Ref SubnetIds
      Tags:
        - Key: Environment
          Value: !Ref Environment

  # HTTP 监听器(重定向到 HTTPS)
  HttpListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - Type: redirect
          RedirectConfig:
            Protocol: HTTPS
            Port: '443'
            StatusCode: HTTP_301
      LoadBalancerArn: !Ref ApplicationLoadBalancer
      Port: 80
      Protocol: HTTP

  # HTTPS 监听器
  HttpsListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - Type: forward
          TargetGroupArn: !Ref WebTargetGroup
      LoadBalancerArn: !Ref ApplicationLoadBalancer
      Port: 443
      Protocol: HTTPS
      Certificates:
        - CertificateArn: !Sub 'arn:aws:acm:${AWS::Region}:${AWS::AccountId}:certificate/xxxxxxxx'

  # Web 服务器的目标组
  WebTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Name: !Sub '${Environment}-web-tg'
      Port: 8080
      Protocol: HTTP
      VpcId: !Ref VpcId
      TargetType: instance

      # 健康检查
      HealthCheckEnabled: true
      HealthCheckPath: /health
      HealthCheckProtocol: HTTP
      HealthCheckIntervalSeconds: 30
      HealthCheckTimeoutSeconds: 5
      HealthyThresholdCount: 2
      UnhealthyThresholdCount: 3

      # 粘滞性
      TargetGroupAttributes:
        - Key: deregistration_delay.timeout_seconds
          Value: '30'
        - Key: stickiness.enabled
          Value: 'true'
        - Key: stickiness.type
          Value: 'lb_cookie'
        - Key: stickiness.lb_cookie.duration_seconds
          Value: '86400'

  # API 的目标组
  ApiTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Name: !Sub '${Environment}-api-tg'
      Port: 3000
      Protocol: HTTP
      VpcId: !Ref VpcId
      TargetType: instance

      HealthCheckPath: /api/health
      HealthCheckIntervalSeconds: 15
      HealthCheckTimeoutSeconds: 5
      HealthyThresholdCount: 2
      UnhealthyThresholdCount: 2

  # API 路由的监听器规则
  ApiListenerRule:
    Type: AWS::ElasticLoadBalancingV2::ListenerRule
    Properties:
      Actions:
        - Type: forward
          TargetGroupArn: !Ref ApiTargetGroup
      Conditions:
        - Field: path-pattern
          Values: ['/api/*']
      ListenerArn: !Ref HttpsListener
      Priority: 1

Outputs:
  LoadBalancerDNS:
    Description: ALB 的 DNS 名称
    Value: !GetAtt ApplicationLoadBalancer.DNSName
  LoadBalancerArn:
    Description: ALB 的 ARN
    Value: !Ref ApplicationLoadBalancer
  WebTargetGroupArn:
    Description: Web 目标组的 ARN
    Value: !Ref WebTargetGroup
  ApiTargetGroupArn:
    Description: API 目标组的 ARN
    Value: !Ref ApiTargetGroup

3. 负载均衡器健康检查脚本

#!/bin/bash
# health-check.sh - 监控后端健康

set -euo pipefail

BACKENDS=("10.0.1.10:8080" "10.0.1.11:8080" "10.0.1.12:8080")
HEALTH_ENDPOINT="/health"
TIMEOUT=5
ALERT_EMAIL="ops@myapp.com"

check_backend_health() {
    local backend=$1
    local host=${backend%:*}
    local port=${backend#*:}

    if timeout "$TIMEOUT" bash -c "echo >/dev/tcp/$host/$port" 2>/dev/null; then
        if curl -sf --max-time "$TIMEOUT" "http://$backend$HEALTH_ENDPOINT" > /dev/null; then
            return 0
        fi
    fi
    return 1
}

main() {
    local unhealthy_backends=()

    for backend in "${BACKENDS[@]}"; do
        if ! check_backend_health "$backend"; then
            unhealthy_backends+=("$backend")
            echo "WARNING: Backend $backend is unhealthy"
        else
            echo "OK: Backend $backend is healthy"
        fi
    done

    if [ ${#unhealthy_backends[@]} -gt 0 ]; then
        local message="Unhealthy backends detected: ${unhealthy_backends[*]}"
        echo "$message"
        echo "$message" | mail -s "Load Balancer Alert" "$ALERT_EMAIL"
        exit 1
    fi
}

main "$@"

4. 负载均衡器监控

# prometheus-scrape-config.yaml
scrape_configs:
  - job_name: 'haproxy'
    static_configs:
      - targets: ['localhost:8404']
    metrics_path: '/stats;csv'
    scrape_interval: 15s

  - job_name: 'alb'
    cloudwatch_sd_configs:
      - region: us-east-1
        port: 443
    relabel_configs:
      - source_labels: [__meta_aws_cloudwatch_namespace]
        action: keep
        regex: 'AWS/ApplicationELB'

负载均衡算法

  • 轮询: 顺序分配
  • 最少连接: 最少活跃连接
  • IP 哈希: 基于客户端 IP
  • 加权: 与服务器容量成比例
  • 随机: 随机分配

最佳实践

✅ DO

  • 实施健康检查
  • 使用连接池
  • 需要时启用会话持久性
  • 监控负载均衡器指标
  • 实施速率限制
  • 使用多个可用区
  • 启用 SSL/TLS 终止
  • 实施优雅的连接排空

❌ DON’T

  • 允许单点故障
  • 跳过健康检查配置
  • 混合 HTTP 和 HTTPS 而不重定向
  • 忽略后端服务器限制
  • 无监控超额配置
  • 缓存敏感响应
  • 使用默认安全组
  • 忽视备份负载均衡器

资源