部署在香港服务器上的跨境商城网站,如何结合BGP多线(CN2/CMIN2/CU/PCCW)保障国内用户和东南亚买家访问商城时不因线路波动出现白屏?
技术教程 2025-09-17 09:31 208


那天是周五晚 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 摘除;回放晚高峰流量

我踩过的坑(以及怎么现场解决)

  1. PMTU 黑洞:越南→香港经某段链路 MTU 1480,ICMP 被丢,TLS 握手卡死 → MSS 夹逼 解决。
  2. BGP 邻居假活:物理链路通但对方黑洞,BGP 还 Estab → 加 BFD + 黑盒探测失败即 撤公告/摘 DNS。
  3. DNS 解析不精准:某些解析器无 ECS,华南移动被分到 PCCW → BGP 保底 + 边界两组 IP 都能接受国内回程,DNS 只做“偏好”。
  4. Keepalived 抢占抖动:VRRP preempt 造成左右切换 → 调整 priority 与 rise/fall,并以 BGP 邻居数作为 track 条件。
  5. 队列拥塞:X710 单队列 PPS 打满 → 提前 开启多队列 与 IRQ 亲和,reuseport 分摊。
  6. 日志写爆:晚高峰 502/504 暴增导致磁盘抖 → Nginx 错误日志分级采样,Promtail 汇聚,避免本地 I/O 放大。
  7. 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 健康检查 这三件事开做,通常一晚上就能把“白屏”大头问题压下去。