一个决策疑问:跳转服务该预留多少冗余才不翻车
上个月有个做竞价投放的客户问了我一个问题,挺直接的:百度斗篷的跳转服务器,CPU常年吃不满百分之三十,是不是可以把机器规格降一降,省点成本。听着是个省钱的事,但往深了想,这背后其实是个容量决策的问题——斗篷跳转链路的容量规划,到底该按日均流量定,还是按峰值流量定,还是按峰值的某个倍数来定。你要是只盯着平均负载看,早晚出事。审核波峰一来,或者碰上恶意扫描,跳转链路几秒钟之内就能被打满,规则判断超时,正常访客被误判成爬虫,整个投放账户跟着遭殃。所以答案很明确:百度斗篷的容量规划得拿压测基线当锚点,而不是拿日常看到的平均负载当锚点。资源预留的核心逻辑就一句话,给突发流量和故障转移留出足够的决策时间窗。
百度斗篷容量规划的机制构成
百度斗篷的容量规划覆盖的是整条跳转决策链路,不是单台服务器的事。一个典型的百度斗篷部署,里面有三个容量敏感层:入口接入层负责接请求、做第一层特征采集;规则决策层跑Cloak判定逻辑、选跳转路径;数据回传层管日志写入、监控上报还有转化事件回传。每一层的容量特性不一样,压测方法和基线指标也不一样。
接入层的容量特征
接入层的主要资源消耗在TCP连接建立、TLS握手和HTTP头部解析这几块。百度斗篷这个场景有个特点,来自百度推广的访问请求,UA字符串往往特别长,Cookie种类多,Referer信息也复杂,头部解析的成本比普通静态页请求高不少。压测接入层的时候,最需要盯的是并发连接数和CPU内核数的比例关系。单核CPU在Nginx或者OpenResty这类异步事件模型下,维持几千个空闲连接通常没问题,但活跃连接的吞吐量取决于单个连接的平均处理时长。要是接入层做了设备指纹采集脚本注入,每个新建连接还会额外触发内存分配和字符串处理,内存水位比纯转发场景高出一个量级。
规则决策层的容量特征
规则决策层是百度斗篷的CPU密集区。每一个请求进到决策层,系统要跑IP信誉查询、UA特征匹配、设备指纹校验、访问频率阈值判断这一串规则。这些规则之间有短路逻辑——高优先级规则命中之后,后面的规则就跳过了,所以规则链的长度和顺序直接影响单请求的CPU消耗。压测基线必须覆盖最坏情况:访问请求来自一个全新的IP、全新的UA和全新的设备指纹组合,所有规则都得跑一遍,单请求耗时达到峰值。规则决策层的容量,通常按每秒决策次数来算,而不是简单的QPS。因为一次访问可能触发多次内部决策,比如初始判定、二次校验、跳转之后的事件回传判定。
数据回传层的容量特征
数据回传层的问题不在吞吐量,在缓冲能力。日志写入走异步批量落盘的时候,瞬时流量不会直接冲击磁盘IO,但要是流量持续超过日志缓冲区的消费速度,内存里的缓冲队列会一直膨胀,最后触发内存上限,进程直接被杀。压测数据回传层的时候要测的是缓冲区从空到满的时间窗口,以及在这个窗口内系统还能维持多高的跳转成功率。
压测基线推导的方法论
压测基线的推导,顺序是从单点测量到全链路验证。先对每个容量敏感层单独施压,确定单层极限,然后放到全链路状态下验证多层之间的资源竞争效应。
单层压测的输入设计
单层压测的关键在于压测流量要逼近真实百度推广流量的特征。用简单HTTP GET请求把QPS打满,那个数据没什么参考价值,真实访问的头部结构、Cookie复杂度、请求时序跟压测流量差太远了。压测脚本得模拟三类流量:正常访客流量,带完整UA和设备指纹、正常访问间隔;审核爬虫流量,数据中心IP段、没有Cookie、高频请求、深度页面扫描;混合突发流量,在正常流量基础上叠加瞬时的爬虫扫描。三类流量的比例得根据实际投放类目调整,没有统一标准。
压测跑完之后会拿到一组原始数据:各层在不同并发下的QPS、P50/P99延迟、CPU和内存占用、错误率。容量基线不是简单取极限值的百分之多少就完事了。正确的推导逻辑是:把P99延迟开始劣化的点作为容量上限的候选值,而不是拿错误率飙升的点当上限。原因是百度斗篷的跳转链路对延迟特别敏感。一个跳转请求要是在决策层多停留一百毫秒,用户端的感知就会被放大——浏览器得等重定向响应,移动端网络抖动再一叠加,总耗时拉得更长。P99延迟从正常水位开始明显上翘的时候,系统其实已经进入资源竞争状态了,就算没报错,跳转体验已经在劣化。
全链路验证的必要性
单层压测过了之后必须做全链路压测。单层测试的时候各层用独立资源池,互不干扰;全链路状态下,接入层的高并发连接会占内存带宽,规则决策层的高CPU消耗会推迟数据回传层的日志刷新。有个常见的翻车点:单层测试时接入层能扛两万并发,规则决策层能处理八千QPS,但全链路压测时接入层到一万五千并发就开始出现连接超时。原因是决策层的CPU争抢导致接入层的事件循环没法及时回收空闲连接,连接池堆积,内存碎片增加,最后把整条链路拖垮。
资源预留策略的实现框架
容量基线定下来之后,资源预留策略要解决的是另一个问题:日常运营中系统应该跑在基线容量的什么水位,以及什么时候触发扩容。资源预留不是简单设一个百分之五十的使用率告警线就完事了,得区分常规冗余、突发冗余和故障冗余三个层次。
常规冗余用来吸收日常流量波动。百度推广的点击量一天之内有明显的时间段差异,早十点到晚十点的流量可能占全天总量的七成以上。按日均值配资源的话,晚高峰必然过载。常规冗余的目标是让晚高峰的峰值负载不超过基线容量的百分之六十到七十。这个比例不是固定常数,取决于投放类目的流量波动幅度。竞价类目波动大,预留比例得高;品牌词类目流量平稳,预留比例可以适当放低。
弹性阈值触发扩容的规则得提前定义好。扩容动作本身有延迟——云主机的秒级弹性网卡扩容也好,容器副本的启动也好,都有十秒到几分钟不等的生效时间。弹性阈值必须低于容量上限,而且差值要大于扩容生效期间可能涌入的流量。打个比方,压测基线显示系统在八千QPS时P99延迟开始劣化,扩容阈值就该设在五千到六千QPS,而不是七千五。
突发冗余与审核波峰
百度斗篷的流量有一种普通Web服务没有的突发模式:审核波峰。百度平台发起一轮新的广告审核或者页面质量抽查的时候,来自百度数据中心IP段的请求会在短时间内集中涌进来。这类波峰的特征是来得快、去得快、请求深度大——审核爬虫会逐层扫描页面内容,不只看落地页首屏。突发冗余就是给这类场景留的空间。如果日常晚高峰的负载占基线容量的六成,突发冗余得额外留出一到两成的空间给审核波峰。这意味着实际日常水位控制在四到五成比较安全。
故障冗余与降级路径
故障冗余解决的是单点故障时的容量缺口。假设部署用的是双节点负载均衡,单节点故障后剩下的节点得承接全部流量。两台机器日常各跑四成负载,一台挂了之后另一台瞬间升到八成。这个水位在突发流量下安不安全,取决于压测基线八成的负载对应多少延迟劣化。故障冗余的核心决策是:接不接受降级。百度斗篷允许在极端情况下把部分非核心规则降级跳过,比如暂停设备指纹深层校验,只保留IP和UA判断。降级之后的容量上限会提升,因为单请求的CPU消耗降下来了。故障冗余策略需要明确降级触发条件、降级后的容量上限、以及恢复正常运行的条件。
适用条件与边界
百度斗篷容量规划这套方法框架有它的适用前提。首先,这套方法假设部署架构是分层解耦的——接入层、决策层、数据层可以单独扩缩容。要是用单体架构,所有逻辑跑在一个进程里,分层压测和资源预留的粒度都会变粗,基线数据只能反映整体行为,定位不了瓶颈层。其次,压测基线的有效期受规则库复杂度限制。每加一条新规则,决策层的单请求CPU消耗就往上走一点,旧基线不再准确。规则库变更之后得重新执行决策层的单层压测,至少要做增量压测来校准基线。
说个匿名化的案例,能说明边界在哪。一个做本地生活服务类竞价投放的客户,日均点击量一千二三,部署了两台四核八G的服务器,跳转规则包含IP信誉、UA过滤、设备指纹和访问频率四层判断。初始压测基线显示单台极限约两千QPS,P99延迟在十五毫秒。客户觉得容量很充裕,日常水位只跑了两成不到,就把监控告警阈值调得很高。结果某天百度发起一轮页面质量抽查,审核流量在十分钟内把单台QPS推到了三千以上。P99延迟瞬间恶化到两百毫秒以上,跳转成功率从百分之九十九掉到百分之八十几。问题不在硬件规格不够,在于没有针对审核波峰做突发冗余设计,也没有设置足够低的弹性告警线。后来调整的过程包括:重新压测确定审核流量下的容量上限、把弹性告警阈值往下调、增加第三台节点做负载均衡、在规则链里增加针对审核IP段的快速短路逻辑。调整之后同样的抽查波峰,跳转成功率稳定在百分之九十七以上。
相邻概念对比:容量规划与性能优化的区别
容量规划和性能优化经常被人混在一起说,但两者解决的问题方向不一样。性能优化追求的是在给定硬件条件下降低单请求的资源消耗,让同样配置跑出更高QPS;容量规划追求的是在给定性能水平下确定安全运行区间,决定需要多少硬件和多少冗余。性能优化的产出是代码改进和配置调优,容量规划的产出是基线数据、告警阈值和扩容策略。
另一个容易混淆的概念是容量规划与负载测试。负载测试是容量规划的手段之一,但容量规划还包括资源预留策略、故障转移容量核算、弹性扩缩容规则设计。只做压测不做预留策略的团队,经常在压测通过之后仍然在流量波动中翻车,因为他们没有把压测数据转化成日常运营的决策依据。
容量规划的运行生命周期
百度斗篷容量规划不是一次性上线前的动作。它跟着规则库演进、流量规模变化和平台审核策略调整在持续迭代。一个完整的容量规划生命周期有五个阶段:初始压测建立基线、上线后监控验证基线偏差、规则变更后增量压测校准基线、流量增长后重新推导预留比例、架构调整后全链路压测重建基线。每个阶段的触发条件得提前定义。比如当日均流量增长超过百分之三十,或者规则库新增超过五条高优先级规则,或者百度平台审核频率出现可观察的变化,就得进入对应阶段的容量规划流程。
规则库的变更对容量基线的影响很容易被低估。一条看起来简单的UA过滤规则,要是放在规则链的前三位,每个请求都得执行一次;放在末尾的话,只有前面规则全部未命中时才执行。同样一条规则,放的位置不同,对容量基线的影响差异可能达到百分之十以上。容量规划文档里需要记录规则链的顺序变更,作为基线校准的输入之一。
百度斗篷容量规划的最终产出是一份可操作的运行手册:各层的基线QPS和延迟数据、日常水位安全区间、弹性扩容触发阈值、故障降级触发条件、以及规则变更后的基线校准流程。这套手册让跳转链路在流量冲击下保持行为可预测,而不是靠运气和事后补救。