我如何把全球平均延迟压进 80 ms:香港服务器 + CDN 地域分配与动态缓存实战

我如何把全球平均延迟压进 80 ms:香港服务器 + CDN 地域分配与动态缓存实战

“为什么香港节点带宽够、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 台服务器更省钱、也更优雅。祝顺利!

未经允许不得转载:A5数据 » 我如何把全球平均延迟压进 80 ms:香港服务器 + CDN 地域分配与动态缓存实战

相关文章

contact