部署在香港服务器上的网络游戏,我们如何结合 CN2 GIA 线路降低国内和东南亚玩家的登录排队延迟?

凌晨 1:40,我在香港葵涌机房的监控屏上,广州、成都、曼谷三条曲线同时抬头——登录峰值远超预期,网关服的等待队列一路飙,玩家在论坛里刷屏“排队 6000+,卡在验证”。同一套游戏服、同一套网关逻辑,为什么香港机房离得这么近,延迟还会突然咬人?
我拿着保温杯蹲在机柜旁,另一只手不停地跑 mtr 和 tcpdump。5 分钟后,结论出来:回国路径绕行、抖动大,半数流量没有走 CN2 GIA,而是被挤到普通国际出口上了。
那一夜我们改了路由策略、接入第二条 GIA、切换 GeoDNS、调了 TCP 栈,队列从 5800 掉到 1200,峰值登录耗时从 9.4s 砍到 2.1s。接下来的这篇文章,就是把那次“抢修”整理成可复制的落地教程,不玩玄学,全部按CentOS 7 环境写,既能给新同学照着做,也能给老兵提供优化和排坑清单。
目标画像与关键思路
- 目标玩家区域:中国大陆(电信/联通/移动)+ 东南亚(泰国、越南、马来西亚、新加坡、印尼)。
- 核心目标:降低登录阶段的排队等待时间,把首包/握手延迟和队列停留时间打下来。
关键抓手:
- 入口/出口路径收敛到 CN2 GIA(或等效高质量线路),降低抖动/丢包;
- 入口分流 + 出口策略路由,实现“谁来、走哪条线”的对称与稳定;
- 登录网关轻量化 + 并发承载能力提升(连接跟踪、队列、内核 TCP 栈、BBR);
- DNS/Anycast/多 EIP 组合,把流量“就近”吸到合适的入口;
- 可观测与应急切换,实时盯丢包/时延,路由一键回滚。
1. 现场环境与参数(真实上手可复刻)
1.1 硬件与网络拓扑
| 角色 | 机型 | CPU | 内存 | 存储 | 网卡 | 线路 |
|---|---|---|---|---|---|---|
| 网关 (GW-A) | 1U 独服 | Xeon 4310 *2 | 64GB | NVMe 1TB | 2×10GbE (Intel X710) | HK 运营商 #1(原生 CN2 GIA) |
| 网关 (GW-B) | 1U 独服 | Xeon 4310 *2 | 64GB | NVMe 1TB | 2×10GbE (Intel X710) | HK 运营商 #2(GIA/等效优先大陆 & ASEAN) |
| 业务集群(Login/Logic/DB) | 2U × N | EPYC 7313P | 128GB | NVMe RAID10 | 2×25GbE | 机房内东西向 |
- OS:CentOS 7.9(统一内核版本便于运维)
- 内核:生产建议 ELRepo kernel-ml 以启用 BBR2;若暂不升级,也可按下文给出 CentOS7 3.10 的保守优化。
1.2 网络策略(高层)
- 入站:通过 GeoDNS 将 大陆/ASEAN 客户端解析到不同的 EIP(分别挂载到 GW-A / GW-B),确保入口天然收敛到相应的高质量上游(GIA)。
- 出站:在 GW 上做 策略路由(ip rule + fwmark + GeoIP/ipset),中国大陆 & 东南亚 请求走 CN2 GIA,其余走普通国际。
- 对称回程:入站 EIP 与出站下一跳绑定,避免回程绕行与路径抖动。必要时以独立 IP 段分别公告(或独立 EIP),保证对称。
- LB 层:登录 TCP/UDP 走 HAProxy (L4);Web/TLS 接口走 Nginx (TLS1.3/0-RTT 可选)。
2. 选线与“真假 GIA”识别清单(避坑)
- 看路由而不是广告词:mtr -T -P 443 your.ip,大陆侧是否进入 59.43/AS4809 等 CN2 节点,是否中间跳过多海缆/欧美绕路。
- 时段抖动:晚间 20:00–23:00 连续跑 smokeping;真 GIA 抖动低、丢包低,p95/p99 稳定。
- 分省份/分运营商测试:华南/华东/西南、电信/联通/移动各测一轮,避免只在广州电信好。
- ASEAN 回程:曼谷/吉隆坡/新加坡分别 mtr,确认不是“去程好、回程差”。
- 签 SLA 和可视化:要求运营商提供 Looking Glass、BFD/告警,并写进合同可退换(至少试跑 7 天)。
3. 域名与入口:GeoDNS / 多 EIP 策略
3.1 规划
- login.game.example:中国大陆优先解析到 EIP-CN2(GW-A);ASEAN 解析到 EIP-ASEAN(GW-B);其他地区解析到普通 EIP(可与 GW-B 复用)。
- 健康检查:各 EIP /healthz,TTL 30–60s,避免过度抖动。
3.2 GeoDNS 实操要点
- 权威 DNS 选可配置 地理路由 与 最短 RTT 的厂商;
- 监控字段:每地区解析命中率、切换次数、黑洞率;
- 故障策略:单地域故障自动回落到另一条 GIA(写成灰度策略,详见 第9点)。
4. 网关(CentOS 7)网络内核与队列优化
4.1 基线内核参数(保守版,3.10 内核)
/etc/sysctl.d/99-game-net.conf
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 250000
net.core.rmem_max = 268435456
net.core.wmem_max = 268435456
net.ipv4.tcp_rmem = 4096 87380 134217728
net.ipv4.tcp_wmem = 4096 65536 134217728
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_synack_retries = 3
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_mtu_probing = 1
net.ipv4.ip_local_port_range = 10000 65000
net.ipv4.tcp_syn_retries = 3
# 开启 fq +(如升级 kernel-ml 后再启用 bbr)
net.core.default_qdisc = fq
若升级 ELRepo kernel-ml(推荐),加上:
net.ipv4.tcp_congestion_control = bbr
4.2 NIC 与中断
# 查看/调优 ring
ethtool -g eth0
ethtool -G eth0 rx 4096 tx 4096
# 关闭可能影响延迟的一些 offload(按需)
ethtool -K eth0 tso off gso off gro on
# CPU 亲和/中断均衡
yum install irqbalance -y
systemctl enable --now irqbalance
5. 出口“走哪条线”:策略路由 + GeoIP 打标
5.1 多上联路由表
假设:
- eth0 → GW-A 上的 CN2 GIA,网关 10.10.10.1,表 101
- eth1 → 普通国际,网关 10.20.20.1,表 102
# /etc/iproute2/rt_tables
101 gia
102 intl
# 配置路由表
ip route add default via 10.10.10.1 dev eth0 table gia
ip route add default via 10.20.20.1 dev eth1 table intl
5.2 基于 GeoIP / ASN 的打标(iptables + ipset)
5.2.1 安装与生成中国 & ASEAN 目的地址集合
yum install ipset xtables-addons -y
# 以 CN, TH, VN, MY, SG, ID 为例(可用 cymru / ip2location / maxmind 转换脚本生成)
ipset create geo_cn hash:net
ipset create geo_asean hash:net
# 批量导入(示例)
while read cidr; do ipset add geo_cn $cidr; done < cn_cidr.txt
while read cidr; do ipset add geo_asean $cidr; done < asean_cidr.txt
也可用 ASN 维度(如 AS4134/AS9929/AS4809 等)生成 ipset,更贴近运营商路径。
5.2.2 用防火墙标记流量
# 标记去往 CN/ASEAN 的出站流量
iptables -t mangle -N GEO_MARK
iptables -t mangle -A OUTPUT -p tcp -m conntrack --ctstate NEW -j GEO_MARK
iptables -t mangle -A GEO_MARK -m set --match-set geo_cn dst -j MARK --set-mark 0x1
iptables -t mangle -A GEO_MARK -m set --match-set geo_asean dst -j MARK --set-mark 0x1
# 其余默认不标记 -> 走 intl
5.2.3 策略路由规则
ip rule add fwmark 0x1 table gia
ip rule add fwmark 0x0 table intl
关键点:登录服务的回包必须走同一上联,避免路径不对称导致抖动。对内网到网关的默认路由也要一致(或 SNAT 统一到对应 EIP)。
6. 入口“从哪条线进”:多 EIP + 绑定上联
6.1 EIP 与上联绑定
- 在 GW-A 只把 EIP-CN2 绑在 eth0(GIA),RP 策略设为 strict 或用 iptables 保证源 EIP 的回程走 eth0。
- GW-B 同理将 EIP-ASEAN 绑定 eth1(或第二家 GIA/优质 ASEAN 上联)。
# 防源路由欺骗
sysctl -w net.ipv4.conf.all.rp_filter=2
sysctl -w net.ipv4.conf.eth0.rp_filter=2
6.2 DNS 侧路由示意
- 大陆来访 → 解析 login.game.example → EIP-CN2(GW-A)
- 泰国/马来等 → 解析到 EIP-ASEAN(GW-B)
- 其他地区 → EIP-INTL(GW-B 备份)
7. 登录层负载:HAProxy(L4)与 Nginx(TLS/接口)
7.1 HAProxy(TCP 登录握手/网关)
/etc/haproxy/haproxy.cfg
global
maxconn 200000
tune.ssl.default-dh-param 2048
log 127.0.0.1 local0
nbthread 8
defaults
mode tcp
timeout connect 3s
timeout client 30s
timeout server 30s
option dontlognull
# 前端:分别监听不同 EIP(绑定上联)
frontend fe_login_cn2
bind EIP-CN2:7000
default_backend be_login_nodes
frontend fe_login_asean
bind EIP-ASEAN:7000
default_backend be_login_nodes
backend be_login_nodes
balance leastconn
server s1 10.0.1.11:7000 check maxconn 30000
server s2 10.0.1.12:7000 check maxconn 30000
说明:两个前端口分别承接 CN2/ASEAN 入口,后端共享,以便弹性扩容与业务对齐。
7.2 Nginx(TLS1.3 / 0-RTT 可选,用于启动器 API)
/etc/nginx/conf.d/api.conf
server {
listen 443 ssl http2 reuseport;
server_name api.game.example;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_early_data on; # 0-RTT,视接口幂等性启用
ssl_session_cache shared:SSL:50m;
location /auth {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass http://api_backend;
}
}
0-RTT 只对幂等接口开启,避免重放风险。
8. 登录队列“真凶”与三板斧
登录排队并不只来自并发超限,更多是 首包慢、握手重传 让排队驻留时间上升:
- 线路抖动/丢包 → SYN 重传、TLS 重传 → 队列膨胀
- 连接跟踪/端口耗尽 → 新连接挂起
- 应用层“串行点”(如单点 Redis、单线程校验)
8.1 内核连接跟踪与端口
# 连接跟踪
sysctl -w net.netfilter.nf_conntrack_max=2621440
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=120
# 临时端口范围已在 §4 设置为 10000–65000
8.2 应用层快取与分片
- 登录态校验加本地缓存(memcached/Redis Cluster),失败再回源。
- 验证码/短信等三方接口,加异步队列与熔断,避免拖后腿。
- 网关无状态化:JWT/短令牌,减少粘连。
9. 可观测与“秒级”切线:MTR / Smokeping / 一键回滚
9.1 观测项
- 按地域:广州/成都/北京/上海/深圳 + 曼谷/新加坡/雅加达 mtr 每 60s;
- 四分位:p50/p90/p95/p99 延迟,抖动(StdDev),丢包率;
- 登录阶段:从 SYN 到第一个业务包(或 200/成功码)的耗时。
9.2 自动降级与回滚
- 当 p99 > 350ms 或 丢包 > 1% 持续 2 分钟:
- 切换 GeoDNS 使受影响地区回落到另一条 GIA;
- GW 上 ip rule 切至备表(预设好 table gia_b)。
- 所有切换写成 Ansible Playbook 与 一键脚本,控制台双确认。
10. 效果数据(实测)
连续 7 天压力回放 + 线上灰度
| 指标 | 优化前 | 优化后(CN2/ASEAN 分流 + TCP 调优) |
|---|---|---|
| 登录首包 p50 | 138 ms | 46 ms |
| 登录首包 p95 | 420 ms | 112 ms |
| 排队平均驻留 | 4.6 s | 1.3 s |
| 排队峰值长度 | 5,800 | 1,200 |
| 丢包率(晚高峰) | 0.9% | 0.2% |
| 抖动(StdDev) | 38 ms | 11 ms |
11. 进阶:BGP / GRE 叠加与对称性强化(可选)
如果你具备 BGP 能力(自有 /30 段、上游开 BGP 会话):
- 同一前缀分别在两家上游公告,使用 Community 与 LocalPref 控制不同国家/AS 的入口择优;
- 对 CN/ASEAN 设更高 LocalPref 到 GIA,上游按社区做优选;
- 灰度时期用 MED 或 prepend 做细粒度分流;
- BFD 保证掉线秒级收敛。
- 若无 BGP,可在 GW 与上游 POP 建 GRE/IPIP 隧道,将特定地域的出站强制走 GIA POP,实现“去 GIA、回 GIA”。
12. 常见坑与现场解法
“伪 GIA”只在华南好
解法:按省/运维商分桶评估,写入合同可换线;上线前让运营商提供 AS-Path 与 LG 证据。
入/出不对称(入口是 GIA,回程走了普通国际)
解法:EIP 绑定上联、对内 SNAT 到对应 EIP;必要时分前缀公告或DNS 强绑定。
xt_geoip 规则被内核升级打断
解法:写 systemd ExecStartPre 重新加载 ipset;有条件用 ASN ipset 降低频繁更新。
端口耗尽/conntrack 满
解法:扩大 ip_local_port_range、调 nf_conntrack_max;HAProxy 开启 reuseport、提升 maxconn。
TLS 0-RTT 导致偶发重复提交
解法:仅对 幂等 GET 或 幂等验证接口开启,写防重放逻辑。
13. 交付清单(可直接照搬)
- 两条上联:CN2 GIA + Intl/ASEAN 优选
- GeoDNS:地区 → EIP 映射,健康检查 + 回退
- GW:sysctl 基线、ip rule + fwmark、ipset(CN/ASEAN)
- LB:HAProxy L4、Nginx TLS1.3/0-RTT(幂等接口)
- 可观测:mtr/smokeping + p95/p99 看板,SLA 告警
- 应急:一键切线剧本 + 回滚
14. 附录:脚本与配置片段
14.1 ipset 重载脚本(systemd)
/usr/local/bin/reload-geoip.sh
#!/bin/bash
set -e
ipset restore < /etc/ipset/geoip.restore
/etc/systemd/system/geoip-reload.service
[Unit]
Description=Reload GeoIP ipset
[Service]
Type=oneshot
ExecStart=/usr/local/bin/reload-geoip.sh
/etc/systemd/system/geoip-reload.path
[Unit]
Description=Watch ipset restore file
[Path]
PathChanged=/etc/ipset/geoip.restore
[Install]
WantedBy=multi-user.target
14.2 Ansible 片段(切换到备用 GIA)
- name: switch to gia_b
hosts: gateways
tasks:
- name: add rule to use table gia_b
command: ip rule add fwmark 0x1 table 201
- name: change default gw of table gia
command: ip route change default via 10.10.20.1 dev eth0 table gia
凌晨 3:10,香港机房的嗡鸣声像白噪音,曲线回到顺滑的形状。微信群里有人仍在讨论“为什么昨晚排队这么快就下来了”。我没回,拎着工具包去楼下买了一杯冻柠茶。
说到底,登录排队不是怪在玩家多,也不是某一段代码“运气不好”。线路是否干净、路径是否对称、队列是否短链路,这些细节凑在一起,才决定了玩家点下“开始游戏”后的那几秒是不是顺滑。
如果你现在也在机房里对着曲线发愁——就从上面这份清单开始:入口分流、出口策略、CN2 GIA 收敛、TCP 栈打磨、观测与回滚。
等你把这些都跑通了,再回头看“排队”,它多半已经变成了“眨眼就进"。



