1. 冷启动问题概述
1.1 微服务冷启动的定义
微服务冷启动(Cold Start)是指新启动的服务实例在正式对外提供全量流量之前,需要经历一系列初始化过程,才能达到稳定服务状态的现象。在云原生环境中,冷启动通常发生在以下场景:
- 弹性扩缩容:HPA 触发新 Pod 创建,服务实例从 0 开始初始化
- 滚动更新:新版本服务实例替换旧实例,JVM/运行时需要预热
- 故障恢复:崩溃重启后,缓存、连接池、线程池需要重建
- 蓝绿部署/金丝雀发布:新版本集群首次接入流量
关键认知:冷启动不是"服务是否启动"的二元问题,而是"服务从启动到稳定处理请求"的渐变过程。这个过程通常持续数秒到数分钟,期间服务能力远低于稳态。
1.2 冷启动导致流量尖峰的原因
冷启动之所以会引发流量尖峰,根源在于服务能力曲线与流量接入曲线之间的错配。下表列出了冷启动期间各组件的能力变化:
| 组件/资源 | 冷启动初始状态 | 稳态状态 | 恢复时间 |
|---|---|---|---|
| JIT 编译缓存 | 空(解释执行) | 热点代码已编译 | 30s ~ 120s |
| 数据库连接池 | 0 连接 | 最小连接数已建立 | 5s ~ 30s |
| 本地缓存 | 空 | 热点数据已加载 | 10s ~ 60s |
| 线程池 | 核心线程未全部创建 | 核心线程活跃 | 1s ~ 10s |
| RPC 连接 | 未建立 | 长连接复用 | 2s ~ 15s |
| GC 行为 | 频繁 Full GC | 稳定 Minor GC | 20s ~ 90s |
当新实例刚注册到服务发现中心(如 Kubernetes Service、Consul、Nacos),负载均衡器或 Envoy 会立即将流量路由到该实例。此时实例的处理能力可能只有稳态的 10% ~ 30%,但流量却以全量接入,形成"能力低谷"与"流量高峰"的错配尖峰。
典型故障模式:新 Pod 启动后 10 秒内,由于 JIT 未预热 + 连接池未建立 + 缓存未命中,请求延迟从 5ms 飙升到 500ms,触发上游超时重试,重试流量进一步压垮实例,形成"冷启动雪崩"。
1.3 削峰填谷的必要性
削峰填谷(Peak Shaving and Valley Filling)是一种流量治理策略,其核心思想是:在服务能力爬坡期(冷启动窗口)主动限制流量接入速率,让流量曲线贴合能力曲线,避免瞬时过载。其必要性体现在三个层面:
- 防止雪崩:冷启动实例处理慢 → 上游超时重试 → 重试流量叠加 → 实例过载崩溃 → 级联故障。削峰可以切断这个恶性循环。
- 提升资源利用率:不削峰时,需要预留 3~5 倍冗余资源应对冷启动尖峰;削峰后,资源利用率可从 20% 提升到 60% 以上。
- 保障 SLO:冷启动期间的 P99 延迟可能从 10ms 飙升到 2s,削峰可以将 P99 延迟控制在 SLO 阈值(如 200ms)以内。
常见误区:削峰不等于拒绝流量。削峰是通过限流、排队、慢启动等手段将流量"削平"并"填"到服务能力允许的区间,而不是简单丢弃请求。Envoy 的限流参数正是实现这一目标的关键工具。
1.4 冷启动削峰的技术挑战
在 Envoy 代理层面实现冷启动削峰,需要解决以下核心问题:
| 挑战 | 描述 | Envoy 应对方案 |
|---|---|---|
| 预热时间不确定 | 不同服务、不同负载下预热时间差异大(10s ~ 5min) | 动态调整限流阈值,结合慢启动(Slow Start) |
| 多实例协同 | 多个新实例同时启动时,限流策略需要全局协调 | 全局速率限制(Global Rate Limit) |
| 限流粒度选择 | 按请求数、连接数、还是并发数限流? | Envoy 支持多种限流原语:HTTP 限流、连接限流、重试预算 |
| 与 K8s 生命周期联动 | 限流策略需要在 Pod 就绪探测、滚动更新中自动生效 | 结合 Readiness Probe、PreStop Hook 和 Envoy 热重启 |