Harness 中的动态批处理:合并多个轻量请求
Harness 中的动态批处理:合并多个轻量请求,让云原生控制平面性能提升3倍引言痛点引入如果你负责过云原生DevOps平台、微服务控制平面或者大模型推理服务的性能优化,一定遇到过这样的窘境:平台QPS刚刚突破10万,API网关的CPU就已经打满了,排查下来发现70%的请求都是小于1KB的轻量请求:比如agent上报状态、拉取任务、同步配置、健康检查……每个请求的业务逻辑处理耗时不到10ms,但HTTP握手、TLS协商、鉴权、链路追踪、上下文切换这些开销占了总耗时的80%。你加了机器、调了连接池、开了HTTP/2多路复用,性能只提升了20%,成本却翻了一倍。这正是全球领先的DevOps厂商Harness在2022年遇到的真实场景:当时Harness的控制平面需要对接全球超过10万个部署代理(Delegate)、CI Runner和终端CLI,每个客户端每2秒就会发起3~5个轻量请求,高峰期QPS超过15万,P99延迟飙升到2s,大量客户端超时重发形成雪崩效应,多次出现小规模服务不可用。解决方案概述为了解决这个问题,Harness的架构团队引入了自适应动态批处理技术:在客户端侧自动聚合多个轻量请求为一个批请求,服务端侧统一处理后聚合响应返回,客户端再把响应分发给每个原始请求。和传统的静态批处理不同,这套方案会根据实时请求率、队列长度、延迟阈值自动调整批大小和等待窗口,既保证了吞吐量的提升,又不会出现延迟过高的问题。上线后Harness公布的生产数据显示:控制平面API网关CPU使用率降低了47%整体吞吐量提升了3.2倍P99延迟从2s降到了460ms,降低了77%数据库QPS降低了62%(得益于批处理内置的请求去重和缓存)最终效果展示我们可以先看一组对比测试数据:指标单请求模式静态批处理(固定100ms窗口)动态批处理(Harness实现)QPS支持上限1.2万2.8万3.8万P99延迟(1万QPS)520ms310ms180ms网关CPU使用率(1万QPS)72%38%27%低峰期P99延迟(100QPS)120ms220ms140ms可以看到动态批处理在高低峰场景下都表现优异,完美解决了轻量请求的性能痛点。准备工作环境/工具如果要跟着本文动手实现或者测试动态批处理,你需要准备:Python 3.9+ 版本gRPC 相关依赖(pip install grpcio grpcio-tools)Harness免费账号(可选,用于体验生产环境的批处理效果:Harness注册地址)前置知识阅读本文你只需要具备以下基础知识,零基础也能看懂核心思路:基本的微服务架构概念HTTP/gRPC通信的基本流程异步编程的基础概念如果你想深入学习相关知识,可以参考:gRPC官方文档云原生微服务设计模式核心概念:什么是动态批处理?批处理的本质批处理的核心思想是合并多个独立请求的公共开销:不管是网络通信的握手、头部开销,还是服务端的鉴权、上下文初始化、数据库连接开销,都只需要执行一次,就能服务N个请求,当N越大时,平均每个请求的开销就越低。静态批处理 vs 动态批处理很多人对批处理的印象还停留在“固定窗口攒批”的静态批处理,比如每100ms或者每攒够100个请求就发送一次,这种方案在请求率稳定的场景下好用,但在云原生场景下请求率波动极大(比如上班时间QPS是下班时间的10倍),就会出现严重的问题:低峰期每个请求都要等满100ms,延迟翻倍;高峰期批大小超过上限,队列溢出,请求失败。动态批处理就是为了解决这个问题诞生的:它会根据实时的运行指标自动调整批处理的参数,核心是在延迟约束下最大化吞吐量。我们可以通过下表直观对比两者的差异:对比维度静态批处理动态批处理触发条件固定时间窗口/固定批大小自适应根据请求率、队列长度、延迟阈值调整批大小波动波动大,低峰期批大小远小于最大值波动小,始终保持在最优批大小区间延迟P99波动大,低峰期延迟固定等于窗口大小,高峰期延迟飙升波动小,始终控制在预设的最大延迟阈值内资源利用率低,低峰期浪费等待时间,高峰期队列溢出高,低峰期减小窗口降低延迟,高峰期增大窗口提升吞吐量实现复杂度低,只要定时器+队列即可中高,需要监控指标、自适应算法、参数调优适用场景请求率稳定、延迟不敏感的场景请求率波动大、对延迟和吞吐量都有要求的云原生场景动态批处理和其他优化技术的对比很多人会问:我已经用了连接池、HTTP/2多路复用,还要用动态批处理吗?答案是肯定的,它们的优化维度完全不同,可以叠加使用,我们通过下表对比:技术请求合并粒度网络开销降低比例对延迟的影响实现复杂度适用场景连接池连接复用,请求单独发送20%~30%(减少握手开销)降低10%~20%低所有HTTP/gRPC通信场景HTTP/2多路复用同一个连接并发多个请求,单独处理30%~40%(减少连接和头部开销)降低20%~30%低(只要开启HTTP/2即可)微服务之间通信、前端和后端通信静态批处理多个请求合并为一个请求60%~80%低峰期增加延迟,高峰期降低延迟中请求率稳定的离线场景动态批处理多个请求合并为一个请求,自适应窗口70%~90%整体降低20%~40%中高云原生控制平面、DevOps平台、大模型推理等高QPS轻量请求场景问题背景:Harness为什么需要动态批处理?Harness的架构特点Harness是一个一站式DevOps平台,提供CI/CD、混沌工程、Feature Flag、云成本管理等全链路能力,它的架构采用典型的控制平面+数据平面分离的设计:控制平面:部署在Harness的公有云或者客户的私有云里,负责存储配置、调度任务、统计数据、提供UI接口数据平面:部署在客户的本地环境、K8s集群里的Delegate(代理)、CI Runner、CLI等客户端,负责执行具体的部署、构建、测试任务所有的数据平面客户端都需要和控制平面频繁通信:每2秒拉取一次待执行的任务、上报任务状态、同步最新的配置、上报健康状态,这些请求的共同特点是:payload极小(大多500B)、QPS极高、延迟要求中等(P991s即可)。问题描述2022年Harness的企业客户数突破2000家,活跃的Delegate数量超过10万个,高峰期QPS突破15万,出现了严重的性能问题:API网关CPU打满:60%的CPU消耗在处理TLS握手、HTTP头部解析、鉴权、链路追踪这些公共逻辑,真正的业务逻辑CPU占比不到30%延迟飙升:P99延迟从正常的200ms涨到2s,大量客户端超时重发,形成雪崩效应,高峰期每秒有超过1万的超时请求数据库压力大:大量相同的配置拉取请求反复查询数据库,数据库CPU使用率达到85%,经常出现慢查询成本过高:为了支撑高峰期的流量,API网关的节点数从20个扩容到60个,每月云成本增加了3万美元Harness的架构团队尝试了很多常规优化手段:开启HTTP/2多路复用、调大连接池、增加缓存、升级服务器配置,但最多只提升了25%的性能,远远达不到要求,最终他们决定自研自适应动态批处理方案。系统设计:Harness动态批处理的架构整体架构Harness的动态批处理采用端侧+服务端协同的三层架构,我们用ER图展示核心实体的关系:被聚合到包含调度生成调整参数对应包含CLIENT_REQUESTBATCHSUB_REQUESTBATCH_SCHEDULERADAPTIVE_CONTROLLERSUB_RESPONSEBATCH_RESPONSE整体架构分为三层:客户端SDK层:嵌入在Delegate、CLI、CI Runner等所有客户端中,负责收集请求、自动攒批、发送批请求、分发响应给业务逻辑API网关层:负责接收批请求,统一做一次鉴权、日志、链路追踪,然后路由到对应的后端服务服务处理层:负责解析批请求中的子请求,并行处理,聚合响应后返回,内置请求去重和缓存能力,降低后端和数据库的压力核心交互流程我们用流程图展示整个动态批处理的交互过程: