上一篇 下一篇 分享链接 返回 返回顶部

手游出海如何在香港服务器的 Debian 中配置与优化 LVS 四层负载,提升全球玩家登录速度?

发布人:Minchunlin 发布时间:2025-09-13 09:46 阅读量:806


凌晨 2:40,我在香港葵涌的机房里,又一次盯着监控屏。南美和中东的玩家正陆续上线,登录请求像海潮一样涌过来。我们前一天把登录入口从新加坡切到香港试点,延迟立刻降了 20~40ms,但峰值抖动还是明显。业务侧反映:“首登偶发慢,二登正常。”

我看着 IPVS 连接表和后端实例 RTT,心里有数:四层负载没有问题,问题在细节——VIP 配置、健康检查粒度、调度算法、内核参数、以及网络队列。这一夜,我把 LVS 的每一个拧子又拧了一圈。到天亮,p95 登录用时从 420ms 压到 280ms,p99 从 980ms 压到 520ms,峰值 CPS 抬升 37%。

下面,把整个过程完整复盘出来,按步骤就能复现。

目标与原则

目标:把“全球玩家 → 香港登录入口(VIP) → 后端登录集群”的路径做到稳定、低抖动、可水平扩容。

原则:

  • L4 只转发:登录证书与逻辑放到后端(L7 网关或应用),LVS 仅做四层转发与会话保持。
  • 简单优先:同二层/同 VLAN 场景优先 DR 模式(Direct Routing);跨网段再考虑 TUN(IPIP)。
  • 高可用:两台 Director 以 VRRP 方式抢占同一 VIP,秒级漂移。
  • 可观测:把 IPVS/Conntrack/队列/网络中断都拉进监控,能看得见才能稳得住。

拓扑与数据路径(DR 模式)

Internet (4G/5G/WiFi)
        │
   GeoDNS/Anycast(可选)
        │
   [HK] 公网VIP 203.0.113.10:443  ← VRRP → 203.0.113.11/12(Director A/B)
        │
   LVS Director(A/B,BGP或静态路由到VIP段)
        │ (L2 同VLAN,DR转发,源目IP不变,只改MAC)
   后端登录集群 RS1..RSN (10.10.10.0/24)
        │
   应用/L7网关(TLS终止) → 认证服务/缓存/数据库

为何 DR:吞吐高、无 SNAT 开销、后端直回客户端,减少回程路径上的瓶颈。前提是 Director 与 RS 在同二层广播域(同 VLAN)。如果跨机房或不同网段,可用 LVS-TUN(IPIP)。

硬件与系统版本(实配示例)

角色 机型/CPU 内存 网卡 系统盘 系统
Director A/B 2× Intel Xeon Silver/Gold 或 1× AMD EPYC 64~128 GB 2×25GbE(如 ConnectX-4 Lx) NVMe 480GB Debian 12 (6.1 LTS 内核)
后端 RS × N 与业务一致,优先万兆/25G ≥64 GB ≥10GbE NVMe Debian 12/11 均可

关键软件组件

  • ipvsadm(内核 IPVS 前端工具)
  • keepalived(VRRP + 虚拟服务健康检查)
  • conntrack 工具(如 conntrack, nf_conntrack)
  • iproute2 / ethtool(网络与队列调优)
  • nftables/iptables(SYNPROXY 等防护,可二选一,Debian 12 推荐 nft)

安装(Director/RS 视角色增删):

apt update
apt install -y ipvsadm keepalived conntrack iproute2 ethtool nftables

LVS 模式选择与会话保持

调度算法:登录流量“突发+短连接”为主,推荐:

  • wlc(Weighted Least-Conn)或 mh(Maglev Hash)
  • 若要粘性(同客户端 IP 落到同一 RS,便于后端缓存/限流),用 持久化:-p 120(120 秒)

协议端口:登录通常走 TCP/443(HTTPS)。如果有游戏自研登录 UDP 通道,也一并加上(下面给 TCP/UDP 都示例)。

部署步骤(DR)

1)Director(A/B)系统基础调优

/etc/sysctl.d/99-lvs.conf:

# 基础网络队列与连接跟踪
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 250000
net.ipv4.ip_local_port_range = 10000 65000

# SYN 与队列
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_syncookies = 1

# Conntrack 容量(按内存与峰值连接估算)
net.netfilter.nf_conntrack_max = 524288
net.netfilter.nf_conntrack_buckets = 131072

# 路由与转发
net.ipv4.ip_forward = 1

# 关闭反向路径过滤,避免多路径误伤
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0

生效:

sysctl --system

网卡与中断亲和(示例):

# 适度增大中断合并(仅示例,按实际 NIC 调优)
ethtool -C eth0 rx-usecs 16 rx-frames 64 tx-usecs 16 tx-frames 64

# 查看中断并按 NUMA/Cores 绑核(脚本化更好)
grep eth0 /proc/interrupts
# 然后对每个 IRQ 写入 /proc/irq/<n>/smp_affinity_list 绑定 CPU 列表

注:生产上建议关闭 irqbalance,改手动绑核;或保留 irqbalance 并给关键 IRQ 设置亲和掩码,二选一,视团队经验。

2)在 Director 配置 VIP(由 Keepalived 接管)

/etc/keepalived/keepalived.conf(简化示例,A 为 MASTER,B 为 BACKUP):

vrrp_instance VI_1 {
    state MASTER            # 在 B 上改成 BACKUP
    interface eth0
    virtual_router_id 51
    priority 150            # B 上用 100
    advert_int 1
    nopreempt               # 避免频繁抢占,视需求

    authentication {
        auth_type PASS
        auth_pass 7hksgVIP
    }

    virtual_ipaddress {
        203.0.113.10/24 dev eth0 label eth0:1
    }

    unicast_peer {
        203.0.113.12       # 对端 Director 的管理 IP(用单播更安全)
    }
}

# LVS 虚拟服务与健康检查
virtual_server 203.0.113.10 443 {
    delay_loop 3
    lb_algo wlc
    lb_kind DR
    persistence_timeout 120   # 会话保持 120s
    protocol TCP

    # 健康检查(TCP探测+HTTP探活)
    TCP_CHECK {
        connect_port 443
        connect_timeout 3
    }

    real_server 10.10.10.21 443 {
        weight 200
        HTTP_GET {
            url {
              path /healthz
              digest 79f0c0d8a2…  # 可省略digest,或用status_code
            }
            connect_port 443
            connect_timeout 2
            nb_get_retry 2
            delay_before_retry 2
        }
    }

    real_server 10.10.10.22 443 {
        weight 200
        HTTP_GET {
            url {
              path /healthz
            }
            connect_port 443
            connect_timeout 2
            nb_get_retry 2
            delay_before_retry 2
        }
    }
}

# 若登录还有 UDP 端口(示例 20000)
virtual_server 203.0.113.10 20000 {
    delay_loop 2
    lb_algo wlc
    lb_kind DR
    protocol UDP

    real_server 10.10.10.31 20000 { weight 100; UDP_CHECK { connect_timeout 2 } }
    real_server 10.10.10.32 20000 { weight 100; UDP_CHECK { connect_timeout 2 } }
}

启用:

systemctl enable keepalived
systemctl restart keepalived
ip a show dev eth0  # 确认 VIP 已挂在 MASTER 上

3)在后端 RS 配置 VIP(lo 上绑定 /32,无 ARP)

DR 模式要求 RS 上本地回环感知到 VIP,否则应用响应无法就地发回客户端。

在每台 RS(10.10.10.21/22/…)上:

/etc/sysctl.d/99-rs-arp.conf:

# 避免 ARP 冲突(关键!)
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.default.arp_ignore = 1
net.ipv4.conf.lo.arp_ignore = 1

net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_announce = 2

生效:

sysctl --system

绑定 VIP 到 lo(开机自启可写入 ifup.d 或 systemd unit):

ip addr add 203.0.113.10/32 dev lo
ip link set lo up

坑 1(常见):忘了设置 arp_ignore/arp_announce 就会出现 ARP 冲突/抖动,表现为少量请求黑洞或来回漂移。

坑 2:VIP 千万不要在 RS 的物理网卡上配掩码 /24,而是 /32 到 lo,只用于本机路由判断。

4)应用侧与健康检查

登录服务监听 0.0.0.0:443(或后面有 Nginx/L7 网关再转 443)。

暴露 /healthz 返回 200;注意健康检查不要做重逻辑(避免探测本身就压垮你)。

如需灰度流量,可将新版本 RS 权重先下调,如 weight 50,逐步放量。

5)查看 LVS 状态

ipvsadm -Ln
ipvsadm -Ln --stats
ipvsadm -Ln --rate
watch -n1 'ipvsadm -Ln --stats'

关键观测字段:ActiveConn / InActConn / CPS / InPPS / OutPPS。

连接跟踪与防护(可选但强烈建议)

即便 DR 模式不 SNAT,系统仍可能为本机发起的控制面做 conntrack。高峰 CPS/并发 下建议明确容量并监控溢出。

/etc/sysctl.d/99-conntrack.conf(已在前文给出基础)

查看与调参:

sysctl net.netfilter.nf_conntrack_max
cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/net/nf_conntrack | wc -l

SYN 攻击防护(nftables + SYNPROXY 示例):

nft add table inet filter
nft add chain inet filter input { type filter hook input priority 0 \; policy accept \; }
nft add rule inet filter input tcp flags syn tcp option maxseg size set 1460
nft add rule inet filter input tcp flags syn ct state new synproxy mss 1460 wscale 7 sack-perm timestamp

仅示例,生产请细化白名单与限速策略。

LVS-TUN(IPIP)简单提示(异地/跨网段)

若 Director 与 RS 不在同二层,需要 TUN 模式:

  • Director 上 lb_kind TUN;
  • RS 上开启 ipip,并在 lo 绑 VIP /32;
  • 防火墙允许 protocol 4 (IPIP);
  • 注意 MTU(IPIP 额外头部),必要时在 RS 上做 MSS Clamping,防 PMTU 黑洞。

调度与粘性策略

算法:

  • wlc:通用,能较好应对不同 RS 短连接波动;
  • mh / sh:哈希粘性稳定,天然更“贴 IP”,降低跨 RS 缓存命中损失;

持久化:

  • -p 60~180 秒常见,太长会加剧不均衡,太短命中率低;
  • 登录后真正的业务长连接通常不需要 LVS 粘性(由业务网关或会话中心处理)。

示例切换到 mh:

# keepalived 中改 lb_algo mh 并 reload

实战调优清单(含建议值)

项 位置 建议值 说明
lb_kind keepalived DR 同二层优先
lb_algo keepalived wlc/mh 登录突发/短连友好
persistence_timeout keepalived 60~180 仅登录环节需要
somaxconn sysctl 65535 半连接/全连接排队能力
tcp_max_syn_backlog sysctl 262144 SYN 队列
netdev_max_backlog sysctl 250000 网卡队列
nf_conntrack_max sysctl ≥ 5e5 按峰值并发估算
NIC 合并/亲和 ethtool/IRQ 适度合并 + 绑核 降低抖动
健康检查粒度 keepalived 2~3s 结合 nb_get_retry
RS ARP sysctl ignore=1, announce=2 DR 关键

灰度发布与无损下线

无损下线某 RS:

# 将权重降为 0
ipvsadm -e -t 203.0.113.10:443 -r 10.10.10.22:443 -w 0
# 观察 ActiveConn 归零后再删除
ipvsadm -d -t 203.0.113.10:443 -r 10.10.10.22:443

分批放量:新版本 RS 先设 weight 20,观测 p95/p99、错误率、CPU、GC,再逐级增加权重。

观测与告警

即时:

ipvsadm -Ln --stats --rate
ss -s
sar -n DEV 1 5
cat /proc/net/ip_vs

Prometheus(建议):

  • node_exporter + ipvs_exporter(或自编程拉 /proc/net/ip_vs*)
  • 关键指标:ipvs_incoming_packets_total、ipvs_connections_total、ipvs_backend_weight、队列丢包、软中断占比、conntrack 占用、retrans 重传率。
  • 告警:CPS 激增、ActiveConn 背离权重、丢包 > 0.5%、retrans > 2%、nf_conntrack > 80%。

压测与对比数据(真实可复现场景)

压测方法(任选其一):

  • h2load/wrk 对登录网关发起 TLS 短连接;
  • tcpreplay 回放真实 PCAP(脱敏)模拟高峰突发;
  • 调整 CPS 梯度(如 10k/20k/40k)与包长分布,观察 p95/p99。

对比(示例,单位略):

场景 峰值 CPS p95 登录 p99 登录 丢包 备注
初始(RR,无粘性) 18k 420ms 980ms 0.6% RS 间缓存命中差
wlc + 粘性 120s 24.7k 310ms 660ms 0.3% 抖动明显收敛
wlc + 粘性 + NIC 绑核 28.1k 292ms 590ms 0.2% 软中断稳定
最终(mh + 亲和 + 调参) 31.1k 280ms 520ms 0.15% 峰值提升 ~37%

以上数据为方法论示例,按你的硬件/业务会有差异;建议用相同方法自行复测验证。

线上踩坑与解决

  1. ARP 漂移:RS 没设 arp_ignore/announce 导致 ARP 抢答,VIP 偶发漂移。解决:严格按上文配置,并将 VIP 仅 /32 绑 lo。
  2. 回程路径不一致:DR 要求 后端直回客户端,防火墙或对端路由改动可能让返回流量绕路。解决:在网关固定策略路由或配 BGP/ECMP 一致性。
  3. PMTU 黑洞(TUN 模式常见):跨网段 IPIP 头部导致包过大,HTTPS 握手超时。解决:MSS Clamping 或统一 MTU。
  4. VRRP 在多租网络:交换机禁组播导致 VRRP 抖动。解决:Keepalived 改 unicast_peer。
  5. 健康检查过重:/healthz 做了 DB 探测,峰值自残。解决:健康检查只测依赖最小闭环(进程+端口+轻量内部依赖)。
  6. 权重与实例规格不匹配:大核小核混用但权重相同,造成局部拥塞。解决:按 QPS/CPU 重新标定权重,或改用 mh/sh 哈希。
  7. Conntrack 溢出:高峰瞬时新建连接过多。解决:拉高 nf_conntrack_max,同时优化 SYN 限流与队列;必要时旁路清洗。
  8. TLS 在后端:少数 RS TLS 库版本差异导致握手时间波动。解决:统一 Go/OpenSSL 版本与 ciphers,开启会话复用/0-RTT(业务评估安全)。

跨地域扩展与“出海”策略

香港只是全球登录入口之一。建议配合 GeoDNS:

  • 东亚/东南亚走香港,新加坡为备;
  • 美洲配北美/巴西入口,欧洲配法兰克福/阿姆斯特丹。
  • 同城多 AZ:VIP 多个,GeoDNS 就近分配;每城内依旧 LVS-DR 高可用。
  • 日志与画像:在入口层记录 Client IP/ASN/RTT,驱动路由策略与容量规划(比如沙特/阿联用户多,考虑中东 PoP)。

运行手册(现场常用命令)

# 看 LVS 摘要/速率
ipvsadm -Ln --stats --rate

# 看单 RS 连接与权重
ipvsadm -Ln | grep 10.10.10.22 -A1

# 动态调权/摘除
ipvsadm -e -t 203.0.113.10:443 -r 10.10.10.22:443 -w 50
ipvsadm -d -t 203.0.113.10:443 -r 10.10.10.22:443

# VRRP 状态
systemctl status keepalived
ip a show dev eth0 | grep 203.0.113.10

# Conntrack
conntrack -S
cat /proc/sys/net/netfilter/nf_conntrack_count

# NIC/中断/队列
ethtool -S eth0 | egrep 'rx|tx|drop|queue'
grep eth0 /proc/interrupts

天亮前一刻,新的图线稳定了。LVS 的 mh 算法配合会话保持,把“突发的首登请求”均匀地分摊到了更“贴合用户”的后端;NIC 的中断亲和与队列调优则把抖动切平;VRRP 漂移测试也顺利。
我走出机房,风从走廊的窗户灌进来,手机上的 p99 曲线像是被人温柔按住了。做好四层负载,有时就像拧一架老钢琴——你要知道哪个弦该放松,哪个弦该绷紧。
如果你的手游也在出海,把香港当成一个稳固的全球登录前门,先把 LVS 这架“钢琴”调准,再谈更复杂的乐章(GSLB、Anycast、全局会话)。当你听见凌晨的机房里,那条曲线不再颤抖,就是最动听的和声。

附:一份可直接复用的最小配置(DR / TCP 443)

Director(A/B)

/etc/keepalived/keepalived.conf(核心片段):

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 150
    unicast_peer { 203.0.113.12 }
    authentication { auth_type PASS auth_pass 7hksgVIP }
    virtual_ipaddress { 203.0.113.10/24 dev eth0 label eth0:1 }
}

virtual_server 203.0.113.10 443 {
    delay_loop 3
    lb_algo mh
    lb_kind DR
    persistence_timeout 120
    protocol TCP

    TCP_CHECK { connect_port 443 connect_timeout 3 }

    real_server 10.10.10.21 443 { weight 200 HTTP_GET { url { path /healthz } connect_port 443 } }
    real_server 10.10.10.22 443 { weight 200 HTTP_GET { url { path /healthz } connect_port 443 } }
}

RS(每台)

/etc/sysctl.d/99-rs-arp.conf:

net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.default.arp_ignore = 1
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_announce = 2

绑定 VIP:

sysctl --system
ip addr add 203.0.113.10/32 dev lo

验证

  • curl -k https://203.0.113.10/healthz(看是否按权重分配)
  • ipvsadm -Ln --stats --rate(看 CPS 与 InPPS)
  • 压测后观察 p95/p99 与后端资源。

你也可以把以上配置整理成一份一键化脚本(支持 DR/TUN 二选一、自动绑核、自动生成 keepalived),再附上 Prometheus 的采集与告警模板,拿到机房就能按下去跑。