
“为什么香港节点带宽够、CPU 够,可美国东海岸用户还是要 400 ms 才打开首页?”——这是“2025年618”前夕,老板冲进机房对我吼的第一句话。
当时我们的核心业务已经迁到香港专用机房,自带 CN2 +BGP 回国双向优质带宽,按理说亚洲访问飞快。但用户分布 60 % 在欧美、中东、拉美,跨洋 RTT 把漂亮的 PageSpeed 分数拖成了笑话。
我用三周时间把 「香港单源 + 智能 CDN + 动态缓存」 落地:
- 全球实时 RTT 从 200 – 450 ms 下降到 60 – 120 ms
- 峰值带宽成本降低 37 %
- TTFB 抖动收敛到 P95 < 110 ms
- 下面完整拆解我的方案和踩坑过程。
1. 目标与指标
| 指标 | 改造前 | 目标值 |
|---|---|---|
| 全球平均 RTT | 230 ms | ≤ 120 ms |
| P95 TTFB | 380 ms | ≤ 150 ms |
| 峰值源站带宽 | 8 Gbps | ≤ 5 Gbps |
| 缓存命中率 | 42 % | ≥ 80 % |
衡量思路:核心关注 RTT + 服务器处理 的业务感知延迟,而不仅是 CDN 日志里的静态命中率。
2. 宏观架构
┌────────────┐ Anycast DNS + GeoIP ┌──────────────┐
│ 全球用户 │ ──────────────────────▶ │ 最近 CDN POP │
└────────────┘ └──────┬───────┘
│Cache/Edge Logic
▼
┌────────────────────────┐
│ 香港 Origin Cluster │
│ (双活机柜) │
└────────────────────────┘
- GeoDNS / Anycast:把同一域名解析到离用户最近的 CDN POP,减第一跳。
- 单香港源站:避免多源同步一致性的复杂度;使用 MHA + DRBD 做底层 HA。
- 动态缓存:让「几乎动态」的内容也在边缘收敛,真正削峰。
3. 逐步实施
3.1 选型:CDN POP 分布与传输协议
| 方案 | POP 数量 | 动态回源 | HTTP/3 | 计费 |
|---|---|---|---|---|
| Cloudflare Enterprise | ≈ 310 | Tiered Cache + R2 | ✔ | 95 th 带宽 |
| 腾讯云 ECDN | ≈ 180 | 源站直回 | ✖ | 5 秒峰值 |
| Akamai Ion | > 275 | Adaptive Acceleration | ✔ | 日峰值 |
决策:Cloudflare 的 Tiered Cache 和 Cache Reserve 能把「跨洲回源」次数压到最低;而广东 <–> 香港 2 ms 内链路对 A5 机房非常友好。
3.2 DNS 地域分配
域名劈分
api.example.com # 动态+API
static.example.com # 纯静态
media.example.com # 大文件冷热分级
GeoDNS
- 使用 NS1 策略:US-East -> POP_Newark, RU -> POP_Finland, 其余默认 Cloudflare Anycast`
错误兜底
- 解析失败 fallback 到香港原生 IP(优先保证可访问)
3.3 动态缓存策略
| 业务模块 | 缓存键 | 过期策略 | 回源准则 |
|---|---|---|---|
| 商品列表 | /{lang}/products?page={id} |
max-age=30, stale-while-revalidate=30 |
缓存 MISS + revalidate |
| 订单接口 | POST /api/order |
no-store |
永不缓存 |
| 用户中心 | GET /user/{uid} |
edge ttl = 3 s | Cookie = login=1 时 bypass |
Edge Rules(Cloudflare Workers) 示例:
export default {
async fetch(req, env) {
// 1. 鉴权 Cookie 决定是否缓存
const loggedIn = req.headers.get("Cookie")?.includes("login=1")
if (loggedIn) {
return fetch(req) // 私密数据,直接回源
}
// 2. 自定义 Cache-Key:语言 + 移动/PC
const device = req.headers.get("sec-ch-ua-mobile") ? "m" : "d"
const lang = req.headers.get("Accept-Language")?.split(",")[0] || "en"
const cacheKey = new Request(
new URL(`${new URL(req.url).pathname}?dev=${device}&lang=${lang}`, req.url),
req
)
return caches.default.match(cacheKey) || (async () => {
const res = await fetch(req, { cf: { cacheEverything: true } })
// 把响应克隆一份写入缓存
const resCopy = new Response(res.body, res)
resCopy.headers.append("Cache-Control", "max-age=30, stale-while-revalidate=30")
await caches.default.put(cacheKey, resCopy.clone())
return resCopy
})()
}
}
3.4 源站优化
Nginx
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=EDGE:10g max_size=40g inactive=2h use_temp_path=off;
map $http_cf_cache_status $loggable {
default 1;
HIT 0;
STALE 0;
}
log_format main '$remote_addr - $host [$time_local] $request '
'$status $body_bytes_sent $upstream_cache_status-$http_cf_cache_status '
'$request_time $upstream_response_time';
TLS Offload:利用 A5 机房的 Intel QAT 卡,在源站侧启用 ssl_async 减轻 CPU。
TCP 优化:
sysctl -w net.core.rmem_max=16777216
sysctl -w net.ipv4.tcp_tw_reuse=1
3.5 监控与回放
- Prometheus + Grafana:采集 edge_time, origin_time, cf_cache_status label。
- Real-User-Monitoring (RUM):JS SDK 上报 ttfb, fcp, cls 按国家/地区分 bucket。
- 日志回放:选 1 % 流量在 Staging POP 重放,验证任何规则改动不会 “惊群” 回源。
4. 基础设施声明化
用 Terraform + GitHub Actions 持续交付:
resource "cloudflare_ruleset" "product_page_cache" {
zone_id = var.zone
name = "ProductPageEdge"
kind = "custom"
phase = "http_request_cache_settings"
rules {
expression = "http.request.uri.path matches \"/[a-z]{2}/products.*\""
action = "set_cache_settings"
action_parameters {
cache = true
ttl = 30
swr = 30
}
}
}
workflow "Apply" {
on = "push"
jobs = [
{
uses = "hashicorp/terraform-github-actions@v2"
secrets = ["CLOUDFLARE_API_TOKEN"]
}
]
}
5. 性能验证
# 美国东部测试
$ curl -w "%{time_connect} %{time_starttransfer}\n" -o /dev/null -s https://api.example.com/
0.039 0.087
# 之前同地点:0.170 0.410
结果:改造后全球 RUM 统计 P95 TTFB 从 380 ms ↓ 110 ms;CDN Edge 命中率平均 83 %。
← Grafana 直方图(P95 收敛处明显左移)
6. 常见坑 & 护城河经验
- 缓存穿透:移动端 Device/UA 差异导致 Cache-Key 爆炸,务必用 map 压缩维度。
- Cookie 污染:营销 ABTest 写入全局 Cookie,会让静态资源无法命中,改写为 SameSite=Lax; Path=/abtest。
- 跨洲热链:拉美法务视频动辄 500 MB,小文件 CDN 命中高但触发 Regional Tier 计费高;用 Cloudflare R2 存储 “预热版” + 延迟拉源。
- HTTP/3 兼容:部分企业防火墙丢 UDP 443,必须同时开启 HTTP/2 fallback。
- 监控盲区:Grafana 里单看平均值无感知,要拆分 cf_cache_status=MISS 的 SLO。
我通过 香港优质源站 + 全球 POP 智能调度 + 动态边缘缓存,把 “近” 与 “快” 的矛盾解耦,让一次跨洲点击像隔壁 LAN 一样丝滑。希望这份拆解能帮你在下一次流量洪峰前,把全球用户的耐心留在 100 ms 以内。
如果你正准备大促前提速,先把 DNS 与缓存键梳理好,比加 10 台服务器更省钱、也更优雅。祝顺利!











