土法炼钢兴趣小组的算法知识备份

【网络工程】动态加速:TCP 优化、路由优化与边缘计算

文章导航

分类入口
network
标签入口
#cdn#dynamic-acceleration#edge-computing#tcp-optimization#cloudflare-workers

目录

CDN 最初是为静态资源(图片、CSS、JS)设计的缓存网络。但现代 CDN 的价值远不止缓存——它拥有全球部署的边缘节点、优化的骨干网络和接近用户的计算能力。这些基础设施同样可以用于加速动态请求。

动态加速(Dynamic Site Acceleration,DSA)的核心思路是:即使内容不可缓存,也可以通过优化传输路径传输协议来减少延迟。

一、动态请求为什么慢

在分析加速方案之前,先理解动态请求的延迟构成:

客户端延迟分解(上海用户访问美西源站):

DNS 解析:     ~50ms
TCP 握手:     ~180ms(1 RTT = 180ms)
TLS 握手:     ~360ms(TLS 1.2 需要 2 RTT)
HTTP 请求:    ~180ms(1 RTT 发送请求 + 等待响应头)
服务端处理:   ~50ms(API 处理时间)
数据传输:     ~180ms(1 RTT 传输响应体)
─────────────────────────────────────────
总延迟:       ~1000ms

其中网络延迟占比: (1000 - 50) / 1000 = 95%

对比同样的请求经过边缘节点(上海 PoP):

客户端延迟分解(经过上海 PoP 加速):

DNS 解析:     ~5ms(Anycast,就近解析)
TCP 握手:     ~5ms(到上海 PoP 的 RTT ~5ms)
TLS 握手:     ~10ms(TLS 1.3,1 RTT)
HTTP 请求:    ~5ms(到 PoP 的 1 RTT)
PoP→源站:     ~100ms(优化骨干网 + 持久连接复用)
服务端处理:   ~50ms
数据传输:     ~5ms(PoP 到客户端)
─────────────────────────────────────────
总延迟:       ~180ms

加速比: 1000ms / 180ms ≈ 5.5x

关键优化点:

延迟因素 直连 动态加速 优化手段
DNS 解析 50ms 5ms Anycast DNS
TCP 握手 180ms 5ms 边缘终止
TLS 握手 360ms 10ms 边缘终止 + TLS 1.3
网络传输 360ms 110ms 智能路由 + 持久连接
服务端处理 50ms 50ms 不变(或边缘计算)

二、TCP 优化

动态加速的第一层是 TCP 协议层面的优化。CDN 在边缘节点和源站之间维护优化的 TCP 连接。

2.1 连接复用(Connection Reuse)

传统模式下,每个用户请求都需要与源站建立新的 TCP 连接。CDN 通过连接池(Connection Pool)复用边缘到源站的长连接:

传统模式(每请求一连接):

用户A ──[TCP+TLS]──→ 源站    4 RTT 建立连接
用户B ──[TCP+TLS]──→ 源站    4 RTT 建立连接
用户C ──[TCP+TLS]──→ 源站    4 RTT 建立连接

CDN 连接复用模式:

用户A ──[TCP+TLS]──→ PoP ──[复用连接]──→ 源站   仅 1 RTT(到 PoP)
用户B ──[TCP+TLS]──→ PoP ──[复用连接]──→ 源站   仅 1 RTT(到 PoP)
用户C ──[TCP+TLS]──→ PoP ──[复用连接]──→ 源站   仅 1 RTT(到 PoP)

Nginx 配置边缘到源站的连接池:

upstream origin_pool {
    server origin.example.com:443;
    
    # 每个 worker 进程保持 128 个空闲长连接
    keepalive 128;
    
    # 每个连接最多复用 1000 个请求后关闭
    keepalive_requests 1000;
    
    # 空闲连接超时 60 秒
    keepalive_timeout 60s;
    
    # 每个 worker 最大连接数(包括活跃和空闲)
    keepalive_time 1h;
}

server {
    listen 443 ssl http2;
    
    location / {
        proxy_pass https://origin_pool;
        
        # 必须设置 HTTP/1.1 才能启用 keepalive
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        
        # 源站连接超时
        proxy_connect_timeout 5s;
        proxy_read_timeout 30s;
    }
}

连接复用的效果量化:

假设条件:
- 每秒 1000 个请求到达同一 PoP
- 源站 RTT = 100ms
- TCP + TLS 握手 = 3 RTT = 300ms

无连接复用:
  每秒需要建立 1000 个新连接
  握手开销: 1000 × 300ms = 300 秒(连接建立总耗时)
  源站 SYN 队列压力大

连接复用(keepalive=128):
  稳态下维持 128 个长连接
  每个连接每秒处理 ~8 个请求
  新连接建立: ~0(稳态下)
  节省的握手延迟: 每请求 300ms

2.2 TCP 握手优化

边缘节点可以利用 TCP Fast Open(TFO)和 TLS 1.3 减少握手轮次:

标准 TCP + TLS 1.2(4 RTT):
Client ──── SYN ────────────→ Server
       ←──── SYN-ACK ────────
       ──── ACK ─────────────→        TCP 握手完成(1.5 RTT)
       ──── ClientHello ─────→
       ←──── ServerHello ─────
       ←──── Certificate ─────
       ←──── ServerHelloDone ──
       ──── ClientKeyExchange →
       ──── ChangeCipherSpec ──→
       ──── Finished ─────────→
       ←──── ChangeCipherSpec ──
       ←──── Finished ─────────       TLS 握手完成(2 RTT)
       ──── HTTP Request ─────→       总计 3.5+ RTT

TCP Fast Open + TLS 1.3(1 RTT):
Client ──── SYN + TFO Cookie + ClientHello ──→ Server
       ←──── SYN-ACK + ServerHello + Finished ──
       ──── ACK + Finished + HTTP Request ──→    总计 1 RTT

Linux 内核的 TFO 和 TLS 优化配置:

# 边缘节点内核参数
# 启用 TCP Fast Open(客户端和服务端)
sysctl -w net.ipv4.tcp_fastopen=3

# 增大 TFO 队列
sysctl -w net.ipv4.tcp_fastopen_blackhole_timeout_sec=0

# 启用 TCP 窗口缩放
sysctl -w net.ipv4.tcp_window_scaling=1

# 增大初始拥塞窗口(Google 推荐 10)
ip route change default via $GATEWAY dev eth0 initcwnd 10 initrwnd 10

# 启用 BBR 拥塞控制
sysctl -w net.core.default_qdisc=fq
sysctl -w net.ipv4.tcp_congestion_control=bbr

# 验证
sysctl net.ipv4.tcp_congestion_control
# → bbr

2.3 拥塞控制优化

CDN 在不同网段使用不同的拥塞控制算法:

┌──────────┐    公网(BBR)    ┌──────┐   骨干网(CUBIC)  ┌──────────┐
│  客户端   │ ◄──────────────→ │ PoP  │ ◄───────────────→ │  源站     │
└──────────┘   高延迟/有丢包   └──────┘   低延迟/低丢包    └──────────┘
               BBR 适合            │       CUBIC 适合
                                   │
                              连接在此终止
                              两段独立的 TCP

BBR 在高延迟、有丢包的公网上表现优于 CUBIC:

# 对比测试:跨太平洋链路(RTT=180ms, 丢包率=0.1%)

# CUBIC
$ iperf3 -c origin.us-west.example.com -t 30
[  5]   0.00-30.00  sec   125 MBytes  34.9 Mbits/sec  sender

# BBR
$ sysctl -w net.ipv4.tcp_congestion_control=bbr
$ iperf3 -c origin.us-west.example.com -t 30
[  5]   0.00-30.00  sec   312 MBytes  87.2 Mbits/sec  sender

# BBR 吞吐量是 CUBIC 的 2.5 倍

2.4 初始拥塞窗口(initcwnd)优化

TCP 连接建立后,初始拥塞窗口(initcwnd)决定了第一次能发送多少数据。Linux 默认 initcwnd=10(约 14KB),对于小页面可能一次 RTT 就够了,但对于大响应需要多次 RTT:

initcwnd=10(~14KB)传输 100KB 响应:

RTT 1:  发送 14KB  (cwnd=10)
RTT 2:  发送 28KB  (cwnd=20, 慢启动翻倍)
RTT 3:  发送 56KB  (cwnd=40)
RTT 4:  发送 2KB   (剩余数据)
总计:   4 RTT

initcwnd=32(~46KB)传输 100KB 响应:

RTT 1:  发送 46KB  (cwnd=32)
RTT 2:  发送 54KB  (cwnd=64, 慢启动翻倍)
总计:   2 RTT

节省: 2 RTT × 180ms = 360ms

CDN 提供商通常在边缘节点设置较大的 initcwnd:

# 查看当前路由的 initcwnd
ip route show | grep initcwnd

# 设置 initcwnd=32(适用于边缘节点,带宽充裕)
ip route change default via $GATEWAY dev eth0 initcwnd 32 initrwnd 32

# 注意:过大的 initcwnd 在弱网环境可能导致丢包
# 生产环境建议 10-32 的范围

三、智能路由

TCP 优化解决的是协议效率问题,智能路由解决的是网络路径问题——公网的 BGP 路由并不总是最优的。

3.1 公网路由的问题

BGP(Border Gateway Protocol)选择路径的标准是最短 AS 路径,而不是最低延迟:

公网 BGP 路径(上海 → 美西):

上海 → 中国电信上海 → 中国电信骨干 → 洛杉矶 IX → US-West DC
延迟: 180ms
经过: 5 个 AS,3 个国际骨干节点

可能存在的问题:
1. 骨干链路拥塞(晚高峰)
2. 国际出口限速
3. 路径次优(绕行)
4. 某段链路丢包率高

mtr 观察公网路由质量:

$ mtr -rw -c 100 origin.us-west.example.com
HOST                              Loss%   Snt   Last   Avg  Best  Wrst StDev
1. gateway.local                    0.0%   100    0.5   0.5   0.4   0.8   0.1
2. 202.97.33.1 (ChinaTelecom)       0.0%   100    5.2   5.1   4.8   6.2   0.3
3. 202.97.90.34                      0.0%   100   15.3  14.8  13.9  18.2   1.1
4. 202.97.94.78 (国际出口)           2.0%   100   42.1  45.3  40.2  89.7  12.3  ← 丢包
5. 63.218.0.1 (PCCW 骨干)           2.0%   100  152.3 155.8 148.7 220.1  15.6  ← 抖动大
6. 149.6.34.2 (洛杉矶 IX)           2.0%   100  172.4 175.1 170.3 195.2   5.8
7. 10.0.0.1 (目标DC)                2.0%   100  178.3 180.2 176.1 198.7   4.2

问题:
- 跳 4 国际出口有 2% 丢包
- 跳 5 抖动大(StDev=15.6)
- 整体丢包率累积到 2%

3.2 CDN 私有骨干网

大型 CDN 提供商(Cloudflare、Akamai、Google)拥有自己的骨干网络,可以避开公网的拥塞和次优路由:

CDN 私有骨干网路径:

用户(上海) → 上海 PoP → [私有骨干] → 洛杉矶 PoP → 源站
              5ms         80ms          5ms
              总计: 90ms(vs 公网 180ms)

私有骨干网的优势:
1. 专用光纤,不与公网共享带宽
2. 自主控制路由策略(不依赖 BGP 的 AS 路径选择)
3. 实时监控链路质量,动态切换路径
4. 端到端的 QoS 保障

Cloudflare Argo Smart Routing 的工作原理:

┌──────────────────────────────────────────────────────┐
│           Cloudflare 智能路由系统                       │
│                                                      │
│  实时探测网络:                                        │
│  ┌──────┐    RTT: 3ms     ┌──────┐                   │
│  │上海PoP│ ──────────────→ │东京PoP│                   │
│  │      │    Loss: 0%     │      │                   │
│  └──────┘                 └──────┘                   │
│      │                        │                      │
│      │ RTT: 80ms              │ RTT: 60ms            │
│      │ Loss: 0.1%             │ Loss: 0%             │
│      ↓                        ↓                      │
│  ┌──────┐    RTT: 20ms   ┌──────┐                    │
│  │洛杉矶 │ ←────────────── │旧金山 │                    │
│  │ PoP  │    Loss: 0%     │ PoP  │                    │
│  └──────┘                 └──────┘                    │
│                                                      │
│  最优路径选择:                                        │
│  路径A: 上海 → 洛杉矶(直连)    80ms, 0.1% loss      │
│  路径B: 上海 → 东京 → 旧金山 → 洛杉矶  83ms, 0% loss  │
│  选择: 路径B(虽然延迟略高,但零丢包)                    │
└──────────────────────────────────────────────────────┘

3.3 实时路由质量探测

CDN 的智能路由依赖实时的路径质量探测:

# 路由质量探测的简化模型
import time
import statistics

class PathProbe:
    """每条路径的探测数据"""
    def __init__(self, path_id, hops):
        self.path_id = path_id
        self.hops = hops
        self.samples = []  # (timestamp, rtt, loss)
    
    def add_sample(self, rtt_ms, loss_rate):
        self.samples.append((time.time(), rtt_ms, loss_rate))
        # 保留最近 5 分钟的样本
        cutoff = time.time() - 300
        self.samples = [(t, r, l) for t, r, l in self.samples if t > cutoff]
    
    def score(self):
        """计算路径综合评分(越低越好)"""
        if not self.samples:
            return float('inf')
        
        recent_rtts = [r for _, r, _ in self.samples[-30:]]
        recent_losses = [l for _, _, l in self.samples[-30:]]
        
        avg_rtt = statistics.mean(recent_rtts)
        p99_rtt = sorted(recent_rtts)[int(len(recent_rtts) * 0.99)]
        jitter = statistics.stdev(recent_rtts) if len(recent_rtts) > 1 else 0
        avg_loss = statistics.mean(recent_losses)
        
        # 综合评分:延迟 + 抖动惩罚 + 丢包惩罚
        score = avg_rtt + jitter * 2 + avg_loss * 1000 + (p99_rtt - avg_rtt) * 0.5
        return score

class SmartRouter:
    """智能路由选择"""
    def __init__(self):
        self.paths = {}  # path_id -> PathProbe
    
    def select_best_path(self, src, dst):
        """选择 src→dst 的最优路径"""
        candidates = [
            p for pid, p in self.paths.items()
            if pid.startswith(f"{src}-{dst}")
        ]
        if not candidates:
            return None
        
        # 按评分排序,选最优
        candidates.sort(key=lambda p: p.score())
        best = candidates[0]
        
        # 如果最优路径评分变差,考虑切换
        if len(candidates) > 1:
            second = candidates[1]
            # 只有新路径明显更好时才切换(避免频繁抖动)
            if second.score() < best.score() * 0.85:
                return second
        
        return best

3.4 Anycast 与路由收敛

CDN 使用 Anycast 技术让多个 PoP 共享同一个 IP 地址,BGP 自动将流量路由到最近的 PoP:

Anycast 工作原理:

CDN IP: 104.16.1.1(被多个 PoP 同时宣告)

上海电信用户 → BGP 路由 → 上海 PoP(104.16.1.1)
东京用户     → BGP 路由 → 东京 PoP(104.16.1.1)
纽约用户     → BGP 路由 → 纽约 PoP(104.16.1.1)

优势:
- 零配置的就近接入
- 天然的 DDoS 分散能力
- DNS 解析零延迟(IP 不变)

挑战:
- BGP 路由收敛时可能导致连接中断
- 长连接可能被重路由到不同 PoP
- QUIC 的 Connection ID 可以缓解这个问题

四、边缘计算

动态加速的终极形态是将计算逻辑推到边缘——不只是缩短传输路径,而是直接在边缘完成请求处理。

4.1 边缘计算平台对比

┌────────────────────────────────────────────────────────┐
│               边缘计算平台对比                           │
├──────────────┬──────────┬──────────┬───────────────────┤
│              │Cloudflare│ AWS      │ Fastly            │
│              │Workers   │Lambda@Edge│Compute@Edge      │
├──────────────┼──────────┼──────────┼───────────────────┤
│ 运行时       │ V8 Isolate│ Node.js  │ Wasm + JS        │
│ 冷启动       │ 0ms      │ 50-500ms │ ~0ms             │
│ 执行时间限制 │ 30s (付费)│ 5s       │ 60s              │
│ 部署节点数   │ 300+     │ 13 Region│ 70+              │
│ 编程语言     │ JS/Wasm  │ Node/Py  │ JS/Rust/Go/Wasm  │
│ 存储         │ KV/R2/D1 │ DynamoDB │ KV Store         │
│ WebSocket    │ 支持     │ 不支持    │ 支持              │
│ 定价模型     │ 按请求   │ 按请求+时间│ 按请求           │
└──────────────┴──────────┴──────────┴───────────────────┘

4.2 Cloudflare Workers 实战

Workers 使用 V8 Isolate 模型,与传统容器相比冷启动接近零毫秒:

// worker.js — 边缘 API 网关示例
export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    
    // 1. 边缘认证:在边缘验证 JWT,无效请求直接拒绝
    const authResult = await verifyAuth(request, env);
    if (!authResult.valid) {
      return new Response('Unauthorized', { status: 401 });
    }
    
    // 2. 边缘缓存:对特定 API 路径做短时间缓存
    if (url.pathname.startsWith('/api/products/')) {
      const cacheKey = new Request(url.toString(), request);
      const cache = caches.default;
      
      let response = await cache.match(cacheKey);
      if (response) {
        return response;  // 边缘缓存命中,零回源
      }
      
      // 回源获取
      response = await fetch(request);
      
      // 克隆响应并修改缓存头
      const cached = new Response(response.body, response);
      cached.headers.set('Cache-Control', 's-maxage=30');
      
      // 异步写入缓存(不阻塞响应)
      event.waitUntil(cache.put(cacheKey, cached.clone()));
      
      return cached;
    }
    
    // 3. A/B 测试:在边缘决定用户分组
    if (url.pathname === '/') {
      const bucket = hashUserId(authResult.userId) % 100;
      const variant = bucket < 10 ? 'experiment' : 'control';
      
      const originUrl = new URL(request.url);
      originUrl.hostname = 'origin.example.com';
      
      const modifiedRequest = new Request(originUrl, {
        headers: {
          ...Object.fromEntries(request.headers),
          'X-AB-Variant': variant,
          'X-Edge-PoP': request.cf?.colo || 'unknown',
        },
      });
      
      return fetch(modifiedRequest);
    }
    
    // 4. 默认:透传到源站
    return fetch(request);
  }
};

async function verifyAuth(request, env) {
  const token = request.headers.get('Authorization')?.replace('Bearer ', '');
  if (!token) return { valid: false };
  
  try {
    // 使用 Web Crypto API 验证 JWT
    const [header, payload, signature] = token.split('.');
    const key = await crypto.subtle.importKey(
      'raw',
      new TextEncoder().encode(env.JWT_SECRET),
      { name: 'HMAC', hash: 'SHA-256' },
      false,
      ['verify']
    );
    
    const valid = await crypto.subtle.verify(
      'HMAC',
      key,
      base64UrlDecode(signature),
      new TextEncoder().encode(`${header}.${payload}`)
    );
    
    if (valid) {
      const claims = JSON.parse(atob(payload));
      return { valid: true, userId: claims.sub };
    }
  } catch (e) {
    // 验证失败
  }
  
  return { valid: false };
}

function hashUserId(userId) {
  let hash = 0;
  for (let i = 0; i < userId.length; i++) {
    hash = ((hash << 5) - hash + userId.charCodeAt(i)) | 0;
  }
  return Math.abs(hash);
}

function base64UrlDecode(str) {
  str = str.replace(/-/g, '+').replace(/_/g, '/');
  const padding = str.length % 4;
  if (padding) str += '='.repeat(4 - padding);
  return Uint8Array.from(atob(str), c => c.charCodeAt(0));
}

4.3 AWS 实战

在 CloudFront 的四个事件点运行:

请求流程中的 Lambda@Edge 触发点:

客户端                CloudFront               源站
  │                     │                       │
  │── 请求 ──→          │                       │
  │      ①Viewer Request│                       │
  │                     │── 请求 ──→            │
  │                     │    ②Origin Request     │
  │                     │                       │
  │                     │         ←── 响应 ──   │
  │                     │    ③Origin Response    │
  │          ←── 响应 ──│                       │
  │      ④Viewer Response                       │

① Viewer Request:  修改请求头、URL 重写、认证检查
② Origin Request:  修改源站请求、添加自定义头
③ Origin Response: 修改源站响应头、添加安全头
④ Viewer Response: 修改最终响应、添加 Cookie

实际的 函数示例:

// Viewer Request — 地理位置路由
exports.handler = async (event) => {
    const request = event.Records[0].cf.request;
    const headers = request.headers;
    
    // CloudFront 自动注入地理位置信息
    const country = headers['cloudfront-viewer-country']?.[0]?.value || 'US';
    const city = headers['cloudfront-viewer-city']?.[0]?.value || '';
    
    // 根据地理位置路由到不同源站
    const regionMap = {
        'CN': 'origin-cn.example.com',
        'JP': 'origin-ap.example.com',
        'KR': 'origin-ap.example.com',
        'US': 'origin-us.example.com',
        'DE': 'origin-eu.example.com',
        'FR': 'origin-eu.example.com',
    };
    
    const originHost = regionMap[country] || 'origin-us.example.com';
    
    // 修改 Host 头指向对应源站
    request.headers['host'] = [{ key: 'Host', value: originHost }];
    request.origin = {
        custom: {
            domainName: originHost,
            port: 443,
            protocol: 'https',
            sslProtocols: ['TLSv1.2'],
            readTimeout: 30,
            keepaliveTimeout: 5,
        }
    };
    
    // 传递地理位置信息到源站
    request.headers['x-viewer-country'] = [{ key: 'X-Viewer-Country', value: country }];
    request.headers['x-viewer-city'] = [{ key: 'X-Viewer-City', value: city }];
    
    return request;
};

4.4 边缘计算的适用场景

不是所有逻辑都适合放在边缘。判断标准:

适合边缘计算的场景:
┌──────────────────────────────────────────────────────┐
│ ✓ 认证/授权检查(JWT 验证、API Key 校验)              │
│ ✓ 请求路由/重写(A/B 测试、地理位置路由、设备适配)      │
│ ✓ 响应转换(HTML 注入、图片格式转换、压缩)             │
│ ✓ 安全防护(Rate Limiting、Bot 检测、IP 封禁)         │
│ ✓ API 聚合(合并多个后端请求,减少客户端往返)           │
│ ✓ 个性化(根据 Cookie/地理位置返回不同内容)            │
└──────────────────────────────────────────────────────┘

不适合边缘计算的场景:
┌──────────────────────────────────────────────────────┐
│ ✗ 需要访问关系型数据库的复杂查询                        │
│ ✗ 长时间运行的后台任务(>30秒)                         │
│ ✗ 需要大量内存的计算(>128MB)                          │
│ ✗ 需要持久化状态的有状态服务                             │
│ ✗ 涉及事务的业务逻辑                                    │
└──────────────────────────────────────────────────────┘

4.5 边缘与源站的数据同步

边缘计算最大的挑战之一是数据访问——边缘节点距离中心数据库很远。解决方案:

数据访问模式对比:

1. 边缘 KV 存储(最终一致)
   ┌────────┐     ┌────────┐     ┌────────┐
   │上海 PoP │     │东京 PoP │     │纽约 PoP │
   │  KV副本  │     │  KV副本  │     │  KV副本  │
   └────┬───┘     └────┬───┘     └────┬───┘
        │              │              │
        └──────────────┼──────────────┘
                       │
                ┌──────┴──────┐
                │  中心 KV 主库  │
                └─────────────┘
   延迟: 1-5ms(本地读取)
   一致性: 最终一致(秒级传播)
   适用: 配置、Feature Flag、IP 黑名单

2. 边缘数据库(Cloudflare D1 / Turso)
   每个 PoP 有 SQLite 只读副本
   延迟: 1-5ms(本地读取),写入需要回中心
   适用: 用户配置、产品目录(读多写少)

3. 回源查询(强一致)
   边缘 → 私有骨干 → 中心数据库
   延迟: 50-200ms
   适用: 需要强一致性的数据(账户余额、库存)

Cloudflare Workers KV 的使用示例:

// 使用 Workers KV 做边缘特性开关
export default {
  async fetch(request, env) {
    // 从边缘 KV 读取 Feature Flag(本地读取,~1ms)
    const flags = await env.FEATURE_FLAGS.get('flags', { type: 'json' });
    
    if (!flags) {
      return fetch(request);  // KV 未初始化,直接回源
    }
    
    // 根据 Feature Flag 决定行为
    if (flags.maintenance_mode) {
      return new Response(
        '<h1>系统维护中</h1><p>预计 10 分钟后恢复。</p>',
        { status: 503, headers: { 'Content-Type': 'text/html; charset=utf-8' } }
      );
    }
    
    // 新版 API 灰度发布
    const url = new URL(request.url);
    if (url.pathname.startsWith('/api/v2/') && flags.v2_api_percentage > 0) {
      const bucket = Math.random() * 100;
      if (bucket < flags.v2_api_percentage) {
        // 路由到新版 API 服务
        url.hostname = 'api-v2.example.com';
        return fetch(new Request(url, request));
      }
    }
    
    return fetch(request);
  }
};

五、动态加速的架构模式

将以上技术组合,形成完整的动态加速架构:

5.1 全栈加速架构

┌────────────────────────────────────────────────────────┐
│                  动态加速全栈架构                         │
│                                                        │
│  ┌──────────────────────────────────────┐              │
│  │          客户端优化层                  │              │
│  │  DNS Prefetch / TCP Preconnect       │              │
│  │  H2 Push / 103 Early Hints           │              │
│  └──────────────┬───────────────────────┘              │
│                 │                                      │
│  ┌──────────────┴───────────────────────┐              │
│  │          边缘计算层(PoP)              │              │
│  │  认证 / 路由 / A/B / Rate Limit       │              │
│  │  边缘缓存 / KV 存储                   │              │
│  └──────────────┬───────────────────────┘              │
│                 │                                      │
│  ┌──────────────┴───────────────────────┐              │
│  │          传输优化层                    │              │
│  │  TCP 连接复用 / BBR / 智能路由         │              │
│  │  私有骨干网 / QUIC                    │              │
│  └──────────────┬───────────────────────┘              │
│                 │                                      │
│  ┌──────────────┴───────────────────────┐              │
│  │          源站卸载层                    │              │
│  │  TLS 终止 / 压缩 / 请求合并           │              │
│  │  DDoS 防护 / WAF                     │              │
│  └──────────────────────────────────────┘              │
└────────────────────────────────────────────────────────┘

5.2 性能收益量化

完整的动态加速效果对比:

优化环节 直连延迟 加速后延迟 节省 优化手段
DNS 解析 50ms 5ms 45ms Anycast DNS
TCP 握手 180ms 5ms 175ms 边缘终止
TLS 握手 360ms 10ms 350ms 边缘 TLS 1.3
首字节传输 180ms 100ms 80ms 智能路由 + initcwnd
认证检查 50ms 1ms 49ms 边缘 JWT 验证
API 处理 50ms 50ms 0ms 仍需回源
响应传输 180ms 5ms 175ms 边缘就近返回
合计 1050ms 176ms 874ms 加速 6x

5.3 动态加速的成本分析

动态加速不是免费的——需要权衡收益和成本:

成本构成:

1. CDN 流量费用
   - 静态缓存:0.01-0.08 USD/GB(命中缓存无回源)
   - 动态加速:0.08-0.20 USD/GB(每次都回源)
   - 动态加速的流量成本是静态缓存的 2-10 倍

2. 边缘计算费用
   - Cloudflare Workers: 0.50 USD/百万请求
   - Lambda@Edge: 0.60 USD/百万请求 + 执行时间
   - 大流量场景成本显著

3. 带宽承诺
   - 大多数 CDN 需要最低带宽承诺
   - 动态加速通常需要更高的带宽配额

决策矩阵:

场景                    | 推荐方案
─────────────────────────────────────────────────
低延迟要求 + 全球用户      | 全栈动态加速(值得投入)
区域性服务(单一市场)      | 区域 CDN + 边缘终止
内部服务(B2B)           | VPN/专线(不需要 CDN)
预算有限                  | 仅静态缓存 + DNS 优化

六、实战:诊断与优化动态请求延迟

6.1 延迟分解方法

系统化分解一个动态请求的延迟:

# 使用 curl 分解 HTTP 请求延迟
curl -o /dev/null -s -w @- https://api.example.com/v1/users/me <<'EOF'
    DNS 解析:     %{time_namelookup}s\n
    TCP 连接:     %{time_connect}s\n
    TLS 握手:     %{time_appconnect}s\n
    首字节时间:   %{time_starttransfer}s\n
    总时间:       %{time_total}s\n
    下载速度:     %{speed_download} bytes/s\n
    远程 IP:      %{remote_ip}\n
    HTTP 状态:    %{http_code}\n
EOF

# 输出示例(直连):
    DNS 解析:     0.048s
    TCP 连接:     0.228s      ← RTT ≈ 180ms
    TLS 握手:     0.592s      ← 2 RTT for TLS 1.2
    首字节时间:   0.823s      ← 服务端处理 ~50ms + 1 RTT
    总时间:       0.891s
    下载速度:     15234 bytes/s
    远程 IP:      203.0.113.1
    HTTP 状态:    200

# 输出示例(经过 CDN 动态加速):
    DNS 解析:     0.004s      ← Anycast DNS
    TCP 连接:     0.009s      ← 到边缘 PoP ~5ms
    TLS 握手:     0.019s      ← TLS 1.3, 1-RTT
    首字节时间:   0.152s      ← 边缘→源站 + 处理
    总时间:       0.158s
    下载速度:     92847 bytes/s
    远程 IP:      104.16.1.1   ← CDN Anycast IP
    HTTP 状态:    200

6.2 对比测试脚本

批量测试动态加速效果:

#!/bin/bash
# benchmark-dsa.sh — 动态加速 A/B 对比测试

DIRECT_URL="https://origin.example.com/api/v1/users/me"
CDN_URL="https://api.example.com/api/v1/users/me"
ITERATIONS=100
TOKEN="Bearer eyJ..."

echo "=== Dynamic Site Acceleration Benchmark ==="
echo "Iterations: $ITERATIONS"
echo ""

run_test() {
    local label=$1
    local url=$2
    local total_dns=0 total_connect=0 total_tls=0 total_ttfb=0 total_time=0
    local results=()
    
    for i in $(seq 1 $ITERATIONS); do
        result=$(curl -o /dev/null -s -w "%{time_namelookup} %{time_connect} %{time_appconnect} %{time_starttransfer} %{time_total}" \
            -H "Authorization: $TOKEN" \
            "$url")
        
        read dns connect tls ttfb total <<< "$result"
        total_dns=$(echo "$total_dns + $dns" | bc)
        total_connect=$(echo "$total_connect + $connect" | bc)
        total_tls=$(echo "$total_tls + $tls" | bc)
        total_ttfb=$(echo "$total_ttfb + $ttfb" | bc)
        total_time=$(echo "$total_time + $total" | bc)
        results+=("$total")
    done
    
    # 计算平均值
    avg_dns=$(echo "scale=3; $total_dns / $ITERATIONS * 1000" | bc)
    avg_connect=$(echo "scale=3; $total_connect / $ITERATIONS * 1000" | bc)
    avg_tls=$(echo "scale=3; $total_tls / $ITERATIONS * 1000" | bc)
    avg_ttfb=$(echo "scale=3; $total_ttfb / $ITERATIONS * 1000" | bc)
    avg_total=$(echo "scale=3; $total_time / $ITERATIONS * 1000" | bc)
    
    # 计算 P99(排序后取第 99 位)
    sorted=($(printf '%s\n' "${results[@]}" | sort -n))
    p99_idx=$((ITERATIONS * 99 / 100))
    p99=$(echo "scale=3; ${sorted[$p99_idx]} * 1000" | bc)
    
    printf "%-12s DNS: %6sms  TCP: %6sms  TLS: %6sms  TTFB: %6sms  Total: %6sms  P99: %6sms\n" \
        "$label" "$avg_dns" "$avg_connect" "$avg_tls" "$avg_ttfb" "$avg_total" "$p99"
}

echo "Testing direct connection..."
run_test "Direct:" "$DIRECT_URL"

echo "Testing CDN accelerated..."
run_test "CDN:" "$CDN_URL"

七、总结

动态加速的三个层次:

  1. TCP 优化:连接复用、TFO、BBR、initcwnd——在协议层减少握手和传输的 RTT 开销
  2. 智能路由:私有骨干网、实时路径探测、Anycast——在网络层选择最优传输路径
  3. 边缘计算:Workers、——在计算层将逻辑推到靠近用户的位置

选型建议:


上一篇: CDN 缓存策略:TTL、Purge 与 stale-while-revalidate 下一篇: CDN 与 HTTPS:边缘 TLS、证书管理与安全

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-04-22 · network

网络工程索引

汇总本站网络工程系列文章,覆盖分层模型、以太网、IP、TCP、DNS、TLS、HTTP/2/3、CDN、BGP 与故障诊断。


By .