字节跳动的微服务架构有数千个相互依赖的服务。单个慢服务或故障服务可能触发级联故障,拖垮整条产品线。后端工程师必须理解如何在服务网格中构建弹性——在字节跳动的规模下这不是可选项,而是必备基础设施。
定义问题:级联故障发生在下游慢服务导致上游服务等待响应耗尽线程池,然后传播到它们的调用方。
描述限流方案:每对服务间的令牌桶,支持本地和分布式限流,通过中心策略服务配置。
解释熔断器模式:关闭→打开→半开状态机,可配置失败阈值和恢复探针。
讨论如何集成到服务网格:以Sidecar代理或SDK中间件实现,各服务无需自定义实现。
我会构建集成到服务网格Sidecar中的两层弹性系统。第一层限流:每个服务间调用经过Sidecar中的令牌桶限流器。本地限流用内存令牌桶每秒补充。全局限流通过Redis滑动窗口计数器跨实例协调,每500ms同步以平衡准确性和性能。限流策略在中心配置服务管理,通过gRPC流推送到Sidecar。请求被限流时,Sidecar返回429带Retry-After头,调用方实现指数退避。第二层熔断:Sidecar在30秒滑动窗口内跟踪每个下游服务的错误率和p99延迟。当错误率超过50%或p99超过基线5倍时,熔断器打开——所有请求立即收到兜底响应(缓存数据或优雅降级)。10秒后进入半开状态,放行5%流量作为探针。探针成功则关闭,失败则重新打开并加倍冷却时间。两层都向Prometheus监控系统发送指标,熔断器打开时触发PagerDuty告警。关键设计决策是将这些做成Sidecar关注点而非应用库,这样每个服务无需代码修改就默认具备弹性。
强调Sidecar方案——字节跳动使用服务网格,弹性应该是基础设施层面的而非应用层面的。
讨论本地限流和分布式限流的区别以及各自适用场景。
提到熔断器打开时的兜底策略——仅仅快速失败不够,需要优雅降级。
限流控制请求量防止过载。熔断检测下游服务不健康时停止发送请求让其恢复。两者互补:限流预防问题,熔断遏制问题。
Sidecar代理为所有服务透明提供弹性,不受编程语言限制。确保行为一致,简化升级,避免某个团队忘记在服务中实现限流的情况。