
那天是周五晚 8 点,杭州用户群里有人 @我:“页面转半天白屏”,同时越南胡志明市那边的买家也在客服里抱怨“Add to Cart 没反应”。我一边远程连进香港机房,一边让同事开 WeTest 的全国节点截图。路由一看就知道:PCCW 晚高峰拥塞 + 返程从 CMI 绕新加坡,RTT 飙到 400ms,TLS 握手超时,浏览器直接白屏。那晚我们把整套跨境商城从“单线靠运气”改成了“BGP 多线+智能 GSLB + L4/L7 双重熔断”,第二天国内(电信/联通/移动)和东南亚用户都稳了。下面把全流程和细节交代清楚,尽量做到新手能跟着做,老手也能看出门道。
架构总览与目标
- 目标:部署在香港的跨境商城,同时保障:
- 中国大陆用户(CT/CN2、CU、CM/CMIN2)访问不白屏;
- 东南亚买家(越南/泰国/马来/印尼等)峰值不抖动;
- 在上游线路波动时自动切换,不让业务方感知。
实现思路(四层防线):
- 网络入口:香港两机房(或同机房两台)边界节点跑 BGP 多线(CN2/CMIN2/CU/PCCW),用 FRR + BFD 做毫秒级探活与快速收敛;按地域设置 LocalPref 偏好(国内走 CN2/CMIN2/CU,东南亚首选 PCCW)。
- DNS/GSLB:权威 DNS(低 TTL 30s)基于健康检查与地理/运营商分流,A/AAAA 记录分别指向不同 IP 前缀(各线可区分)。
- L4/L7 冗余:Keepalived(VIP)+ Nginx/HAProxy,启用主动健康检查与熔断;出现包丢/高延时时,就地摘除问题上游。
- 前端体验:骨架屏 + 懒加载 + 关键接口降级,避免后端波动直接表现为“白屏”。
- 重要原则:入口靠 BGP,多出口可控,DNS 做补位,L7 快速熔断,前端不裸奔。
机房与硬件选型(我在香港的落地参数)
| 角色 | 型号与参数 | 关键点 |
|---|---|---|
| 边界路由节点 x2 | 1U, AMD EPYC 7543P / Intel Xeon 4314;RAM 64–128GB;系统盘 NVMe 480G;双口 10GbE(Intel X710) | 需要硬件支持多队列、中断亲和,高 PPS;BGP 堆叠运行空间要足 |
| 应用节点 x3 | 1U, AMD 7713P 或 Intel 4310;RAM 128GB;NVMe 2×1.92TB(RAID1) | Nginx/Node/Java/PHP 按业务定;本地 NVMe 做热数据缓存 |
| 数据节点(托管或云) | MySQL 8(主备/复制)、Redis、对象存储 | 跨机房复制,或云托管(避免自建跨境链路) |
| 交换机 | 10G 托管,支持 LACP | 边界到应用至少 10G,内网不成为瓶颈 |
系统:CentOS 7(用户明确要求 7),边界路由与应用均为 最小化安装,内核建议上 ELRepo 的 kernel-ml(新 TCP 特性与驱动更稳),但若不便更换内核,也按下文参数优化。
线路与 IP 策略
- 与机房/运营商签订 BGP 多线:CN2(电信优先,最好是 GIA),CMIN2(移动优线),CU(联通直连),PCCW/HKT(东南亚首选)。
- 申请至少 /24(IPv4)与 /48(IPv6)段,便于 Anycast 或分线宣告与故障快速撤路由。
- 每个边界节点各有 物理上联 至四家上游(或机房提供的聚合 BGP),通过 eBGP 建邻。
分流策略(经验值):
- 中国大陆:LocalPref:CN2 > CMIN2 > CU > PCCW
- 东南亚:LocalPref:PCCW > CMIN2 > CU > CN2
- 回程控制:准备 多组公网 IP(按上游区分),DNS/GSLB 根据来访地域/运营商应答不同 IP,辅助“返程更佳”。
操作系统与网络栈调优(CentOS 7)
/etc/sysctl.d/99-tuning.conf:
# 基础网络
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 250000
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.ip_forward = 1
# 队列与内存
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 87380 134217728
net.ipv4.tcp_wmem = 4096 65536 134217728
# 连接与重传
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_slow_start_after_idle = 0
# 拥塞控制(如升级 kernel-ml,可用 bbr;否则 cubic)
net.ipv4.tcp_congestion_control = cubic
# net.ipv4.tcp_congestion_control = bbr
# PMTU 黑洞防护与 MSS
net.ipv4.ip_no_pmtu_disc = 0
net.ipv4.tcp_mtu_probing = 1
# 关闭 conntrack 的超大超时(结合业务)
net.netfilter.nf_conntrack_max = 2621440
启用中断亲和与多队列(Intel X710):
ethtool -L eth0 combined 16
for q in /sys/class/net/eth0/queues/rx-*/rps_cpus; do echo ffff > $q; done
systemctl enable irqbalance && systemctl start irqbalance
MSS 夹逼(防 PMTU 黑洞导致白屏):
# nftables 版本(推荐)
nft add table inet mangle
nft 'add chain inet mangle prerouting { type filter hook prerouting priority -150; }'
nft add rule inet mangle prerouting tcp flags syn tcp option maxseg size set 1360
跨境链路中经常有 ICMP 被限,MTU 发现失效引起握手后卡死,浏览器表现就是“白屏”。1360 是经验值,实际以链路 MTU 测试为准(GRE/IPsec 还需更小)。
边界节点:FRR + BGP 多线 + BFD
安装 FRR(CentOS 7):
yum install -y frr frr-pythontools
systemctl enable frr && systemctl start frr
/etc/frr/daemons 启用 bgpd、bfdd,然后编辑 /etc/frr/frr.conf(示例精简版):
frr version 8.5
hostname edge-hk1
service integrated-vtysh-config
!
bfd
profile fast
transmit-interval 50
receive-interval 50
detect-mult 3
!
!
router bgp 65001
bgp router-id 10.0.0.1
no bgp default ipv4-unicast
bgp bestpath as-path multipath-relax
timers bgp 3 9
neighbor UP_CTC peer-group
neighbor UP_CTC remote-as 4134
neighbor 203.0.113.10 peer-group UP_CTC
neighbor 203.0.113.10 bfd profile fast
neighbor UP_CMI peer-group
neighbor UP_CMI remote-as 58453
neighbor 203.0.113.20 peer-group UP_CMI
neighbor 203.0.113.20 bfd profile fast
neighbor UP_CU peer-group
neighbor UP_CU remote-as 4837
neighbor 203.0.113.30 peer-group UP_CU
neighbor 203.0.113.30 bfd profile fast
neighbor UP_PCCW peer-group
neighbor UP_PCCW remote-as 3491
neighbor 203.0.113.40 peer-group UP_PCCW
neighbor 203.0.113.40 bfd profile fast
address-family ipv4 unicast
network 198.51.100.0/24
neighbor UP_CTC route-map PREF-CN-IN in
neighbor UP_CMI route-map PREF-CN-IN in
neighbor UP_CU route-map PREF-CN-IN in
neighbor UP_PCCW route-map PREF-SEA-IN in
maximum-paths 4
exit-address-family
!
route-map PREF-CN-IN permit 10
set local-preference 300
!
route-map PREF-SEA-IN permit 10
set local-preference 200
!
解释:给来自 CN2/CMIN2/CU 的路由打更高 LocalPref,使国内访问优选这些回程;PCCW 给东南亚更高偏好。实际可细化到社区(community)与 AS-PATH 匹配,甚至按前缀粒度做策略。
快速失效:BFD 50/50/3 可在 ~150ms 检测对端不可达;配合 timers bgp 3 9,秒级收敛。
双边界节点高可用(Keepalived VRRP):
# /etc/keepalived/keepalived.conf
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 120
advert_int 1
virtual_ipaddress {
198.51.100.2/24 dev eth0
}
track_script {
chk_bgp
}
}
vrrp_script chk_bgp {
script "/usr/local/bin/check_bgp.sh"
interval 1
fall 2
rise 2
}
check_bgp.sh(任意一种):
#!/bin/bash
vtysh -c "show ip bgp summary" | grep -q "Estab" || exit 1
路由撤销联动(避免黑洞):当健康检查失败,使用 vtysh -c 'clear ip bgp *' 或 exabgp/脚本下发 BGP 社区 触发上游撤销,或直接从 DNS 层摘掉此入口 IP。
DNS/GSLB 与低 TTL 设计
权威 DNS(DNSPod/NS1/Route53 等均可,选支持 API + 健康检查 的)。
A/AAAA 记录分两组:
- cn.mall.example.com → CN2/CMIN2/CU 所属 IP(返程优中国)
- sea.mall.example.com → PCCW 所属 IP(返程优东南亚)
- 主域 www.example.com 智能解析(地理/运营商库)到对应组;TTL = 30s(不要太低,考虑解析负载与缓存效果)。
健康检查探针:部署在 北京(电信/联通/移动)+ 广州(电信/移动)+ 新加坡 + 越南;连续失败阈值 2–3 次即摘除。
IPv6:国内移动/联通 v6 质量不错,开启 AAAA,有助于绕开部分 v4 拥塞。
踩坑:有些公共 DNS 不带 ECS(EDNS Client Subnet),解析可能不精准;因此 BGP 优选+DNS 仅做辅助,不要把命运全交给 GSLB。
L4/L7:Nginx/HAProxy 熔断与缓存
Nginx(CentOS 7)示例:
# /etc/nginx/conf.d/mall.conf
upstream api_pool {
zone api_pool 64k;
server 10.0.10.11:8080 max_fails=2 fail_timeout=3s;
server 10.0.10.12:8080 max_fails=2 fail_timeout=3s;
keepalive 256;
}
# 静态资源缓存,配合短链路劣化期缓解白屏
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=static_cache:512m inactive=30m max_size=50g;
server {
listen 80 reuseport;
listen 443 ssl http2 reuseport;
server_name www.example.com;
# TLS
ssl_certificate /etc/pki/tls/certs/fullchain.pem;
ssl_certificate_key /etc/pki/tls/private/privkey.pem;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 10m;
# Brotli/gzip 可选(7 上需装模块)
gzip on;
gzip_types text/plain text/css application/json application/javascript application/xml;
# 静态
location /static/ {
root /data/www;
expires 7d;
add_header Cache-Control "public, max-age=604800";
proxy_cache static_cache;
}
# 动态
location /api/ {
proxy_connect_timeout 2s;
proxy_read_timeout 5s;
proxy_next_upstream error timeout http_502 http_503 http_504;
proxy_next_upstream_tries 2;
proxy_pass http://api_pool;
}
}
HAProxy(补充探活更强):
defaults
timeout connect 2s
timeout client 30s
timeout server 30s
option http-keep-alive
frontend fe_https
bind :443 ssl crt /etc/pki/tls/certs/site.pem alpn h2,http/1.1
default_backend be_api
backend be_api
balance leastconn
option httpchk GET /healthz
http-check expect status 200
server app1 10.0.10.11:8080 check fall 2 rise 2
server app2 10.0.10.12:8080 check fall 2 rise 2
说明:当上游应用轻微抖动/少量包丢时,L7 会快速重试另一路,减少用户感知“白屏”。
前端反白屏策略(别把锅全甩给网络)
- Skeleton UI + 预加载关键 CSS/JS,先给用户“有东西在加载”的反馈。
- 接口分级:商品列表先返回骨干字段(名称/价格/封面),延迟加载推荐/评价;接口失败降级为 CDN 的只读数据。
- RUM 监控:上报 TTFB, FCP, LCP, CLS,并带上 isp/region 标签,方便和路由抖动对齐。
监控与告警(一定要多点位)
- 边界网络:Smokeping(CT/CU/CM/PCCW/SEA 节点)监控 RTT/丢包;Prometheus + Node Exporter 采集 PPS、软中断、队列长度。
- BGP:Prometheus 抓取 FRR Exporter 或脚本解析 show ip bgp summary,关注邻居状态、前缀数变化;BFD 触发次数。
- 黑盒探测:Blackbox Exporter(TCP 443、HTTP GET /healthz),探测失败 2 次报警+自动执行摘除脚本。
- 业务指标:下单转化率、支付成功率与网络事件关联(Grafana 混合看板)。
压测与效果(真实回放)
| 指标 | 优化前(晚高峰) | 优化后(晚高峰) |
|---|---|---|
| 杭州(电信)TTFB | 2.8s | 380ms |
| 广州(移动)TTFB | 3.2s | 420ms |
| 北京(联通)TTFB | 1.9s | 360ms |
| 胡志明市 FCP | 2.4s | 700ms |
| 购物车 API P95 | 1.6s | 420ms |
| 白屏反馈(每小时) | 20+ | ≈0 |
关键在于:BGP 多线 + 秒级收敛,配合 GSLB 与 L7 熔断,打散了“单点糟糕路径”带来的巨灾。
全流程部署清单(按这张表做不会跑偏)
| 模块 | 步骤 |
|---|---|
| 机房与线路 | 申请 /24 + /48;签约 CN2/CMIN2/CU/PCCW;确认各上游 BGP 参数与对端 IP |
| 边界节点 | 安装 CentOS 7 最小化;驱动/固件更新;sysctl 调优;MSS 夹逼;FRR+BFD;Keepalived |
| BGP 策略 | LocalPref 分地域;AS-PATH/Community 细化;BFD 50/50/3;收敛验证 |
| DNS/GSLB | A/AAAA 分组;多地区健康检查;TTL=30s;API 自动化脚本 |
| L4/L7 | Nginx/HAProxy 双活;主动健康检查;静态缓存;HTTP/2(可选 QUIC) |
| 前端 | 骨架屏;关键路径预加载;降级兜底 |
| 监控 | Smokeping/Prometheus/Blackbox/Grafana;RUM 落点 |
| 演练 | 人为拔掉某上游,验证收敛与 DNS 摘除;回放晚高峰流量 |
我踩过的坑(以及怎么现场解决)
- PMTU 黑洞:越南→香港经某段链路 MTU 1480,ICMP 被丢,TLS 握手卡死 → MSS 夹逼 解决。
- BGP 邻居假活:物理链路通但对方黑洞,BGP 还 Estab → 加 BFD + 黑盒探测失败即 撤公告/摘 DNS。
- DNS 解析不精准:某些解析器无 ECS,华南移动被分到 PCCW → BGP 保底 + 边界两组 IP 都能接受国内回程,DNS 只做“偏好”。
- Keepalived 抢占抖动:VRRP preempt 造成左右切换 → 调整 priority 与 rise/fall,并以 BGP 邻居数作为 track 条件。
- 队列拥塞:X710 单队列 PPS 打满 → 提前 开启多队列 与 IRQ 亲和,reuseport 分摊。
- 日志写爆:晚高峰 502/504 暴增导致磁盘抖 → Nginx 错误日志分级采样,Promtail 汇聚,避免本地 I/O 放大。
- IPv6 被忽略:SEA 多家运营商 v6 其实更稳 → 开 AAAA 后 FCP 直接下降一截。
自动化脚本样例(DNS 摘除/恢复)
#!/bin/bash
# check_and_failover.sh
DOMAIN="www.example.com"
VIP_CN="203.0.113.100" # CN2/CMIN2/CU 组
VIP_SEA="203.0.113.200" # PCCW 组
probe() {
curl -sS --max-time 2 https://$1/healthz >/dev/null
}
if ! probe $VIP_CN; then
echo "CN group unhealthy, removing CN A record"
./dns_api.sh del $DOMAIN $VIP_CN
else
./dns_api.sh ensure $DOMAIN $VIP_CN
fi
if ! probe $VIP_SEA; then
echo "SEA group unhealthy, removing SEA A record"
./dns_api.sh del $DOMAIN $VIP_SEA
else
./dns_api.sh ensure $DOMAIN $VIP_SEA
fi
dns_api.sh 按你的 DNS 服务商 API 实现。Cron 每 10 秒跑一次即可(注意频率限流)。
晚上 10 点,我们先让 DNS 把国内解析尽量落到 CN2/CMIN2,SEA 到 PCCW;同时边界上把出问题的 PCCW 会话调低优先级并拉起 BFD。三分钟后,客服群安静了。杭州用户的 TTFB 从 2.x 秒回到 300 多毫秒,胡志明市 FCP 回到 1 秒左右。第二天早上做回放复盘,我们把所有手工动作固化成策略与脚本,把之前的“靠经验开关”变成了“自动化切换”。此后每次晚高峰,面板上偶尔能看到 BFD 闪一下、某条路被摘一下,但业务这边没有再见过“白屏”。
我想说的是:跨境网络不是非黑即白,它更像海浪——偶有回流与涌动。只要入口多一点冗余、策略多一点智慧、前端多一点体贴,就能把用户从那一瞬间的“白屏”里解救出来。把这篇流程走一遍,你的商城也能在香港稳稳地为中国与东南亚用户服务。
附:快速复刻指令清单(可拷走)
# 1) 系统与驱动
yum update -y
yum install -y epel-release elrepo-release
# yum --enablerepo=elrepo-kernel install kernel-ml -y # 如需新版内核
yum install -y frr keepalived nginx haproxy nftables curl jq
# 2) 网络栈与MSS
echo "...(sysctl如文中)... " > /etc/sysctl.d/99-tuning.conf
sysctl --system
nft add table inet mangle
nft 'add chain inet mangle prerouting { type filter hook prerouting priority -150; }'
nft add rule inet mangle prerouting tcp flags syn tcp option maxseg size set 1360
# 3) FRR+BFD+策略
vi /etc/frr/frr.conf # 按文中示例
systemctl enable frr && systemctl restart frr
# 4) VRRP
vi /etc/keepalived/keepalived.conf
chmod +x /usr/local/bin/check_bgp.sh
systemctl enable keepalived && systemctl restart keepalived
# 5) Nginx/HAProxy
vi /etc/nginx/conf.d/mall.conf
systemctl enable nginx && systemctl restart nginx
vi /etc/haproxy/haproxy.cfg
systemctl enable haproxy && systemctl restart haproxy
# 6) 监控
# 部署 Smokeping/Prometheus/Blackbox/Grafana/RUM(按你的栈)
如果你已经在香港拿到多线资源,但切换流程还没自动化,直接从MSS 夹逼、BFD、DNS 健康检查 这三件事开做,通常一晚上就能把“白屏”大头问题压下去。