
之前有个跑百度竞价的客户来找我们,他们那套跳转服务跑在一台4核8G的云主机上,一天大概八千到一万两千的点击量,早上九点到十一点、晚上七点到九点这两个时间段特别集中。平时没什么毛病,可一到推广预算猛烧的时候,跳转响应时间就从两百毫秒直接窜到两秒以上,有些请求干脆超时,502就出来了。运维那边一开始想的是加机器,结果一加发现瓶颈跑到数据库连接池去了,等于白忙活一场。这种场景我见得太多了,高并发跳转卡住,通常不是某一个环节的问题,而是限流和排队的策略跟实际流量的形态对不上。下面我按准备、执行、复盘三个阶段,把评估这件事掰开揉碎讲一遍。
准备阶段:先摸清流量结构和容量基线
限流和排队说到底要解决一个矛盾:资源就这么多,怎么让尽量多的有效请求正常返回,同时别让瞬时流量把系统干趴下。所以动手配规则之前,有两件事必须先弄清楚——流量到底长什么样,系统到底能扛多少。
流量结构得从三个角度去看
时间分布是头一个要看的。百度推广的流量跟预算消耗的节奏绑得很紧,预算集中投放的那十几分钟里,点击量翻个几倍太正常了。这时候需要把过去两周的分钟级请求量曲线拉出来,看峰值出现在哪些时间窗口,峰值倍率大概是多少。再一个是来源结构。不同关键词、不同匹配方式带过来的流量,在请求频率和跳转目标上差别很大。广泛匹配的词可能甩过来一堆低频但分散的请求,精确匹配的词就不一样了,短时间能给你堆出一大波密集的跳转请求。终端分布也不能忽略。移动端和PC端的请求特征两码事,移动端网络切换频繁,重试请求的比例明显更高,这部分重试流量在限流的时候特别容易被误伤,得单独拎出来看。
操作层面,我们一般会在跳转服务的入口处加一层轻量日志采集,把每个请求的时间戳、来源IP段、User-Agent、目标URL和响应耗时都记下来。跑满一周之后,按小时聚合出请求量分布,再按来源和终端做交叉分析。这一步做完会得到一份流量画像文档,里面包含峰值时段、峰值QPS、重试请求占比和主要来源分布,后面配限流规则全靠它。
容量基线怎么测出来
容量基线这东西拍脑袋定没用,得用压测工具在预发环境实打实地打出来。压测的时候有两个点要特别注意。一个是你压测的流量得尽量模拟真实请求的分布,别拿同一个URL翻来覆去地打,那样缓存命中率会虚高,测出来的容量偏乐观,上线就翻车。另一个是要把“系统能扛住的最大QPS”和“响应时间开始明显恶化的QPS拐点”区分开。限流阈值应该设在拐点之前,留出百分之二十到三十的余量,别卡着拐点设。
还有一点,压测环境跟生产环境的差异要记录清楚。预发环境没接真实的百度推广流量,请求特征可能比线上规整得多;数据库的数据量也比线上小,查询耗时偏低。这些差异都会让压测结果偏乐观,上线之后必须根据实际监控数据来修正阈值,不能压测完就一劳永逸了。
- 准备阶段输入:过去两周分钟级请求日志、部署架构图、资源规格清单
- 准备阶段输出: 流量画像文档、容量基线与限流阈值建议值
- 验收标准: 峰值时段识别准确,容量拐点误差不超过百分之十五
执行阶段:限流算法与排队机制的组合选择
限流和排队是两码事,但实际用的时候经常得搭在一起。限流管的是哪些请求放行、哪些直接拒掉;排队管的是放行的请求按什么顺序、什么节奏去处理。选型的时候不能脱离跳转服务的业务特点:跳转请求基本是无状态的,单次处理时间很短,但并发量很高;用户对跳转延迟的容忍度极低,超过三秒的等待基本等同于用户流失。
限流算法各自的适用条件
常见的限流算法有计数器、滑动窗口、令牌桶和漏桶这几种。计数器实现起来最简单,但有个临界点的问题——比如你限制每分钟一百个请求,在两个窗口交界的地方可能瞬间通过两百个,等于限了个寂寞。滑动窗口能解决临界点问题,代价是需要维护更细粒度的时间片,内存开销稍微高一点。令牌桶允许一定程度的突发流量,像跳转服务这种有明显峰谷特征的场景就比较合适。漏桶强制请求以恒定速率被处理,适合对下游有严格保护需求的情况,但用户那边会多等一些时间。
具体到百度推广的跳转服务,我比较推荐按来源维度做分层限流。比如对同一个IP段或者同一个推广计划的请求单独限流,这样单个来源的异常流量就不会挤占整体容量。阈值怎么定?参考准备阶段的流量画像就行,高频来源设严一点,正常分布的来源放宽一些。但分层维度别搞太多,超过三层之后规则维护成本蹭蹭往上涨,出了问题排查起来也头疼。
排队机制怎么选
排队机制的核心就两件事:请求等多久,按什么顺序处理。FIFO队列公平是公平,但可能让所有请求都等到超时,谁也走不了。优先级队列可以按请求来源或目标URL的重要性来排序,但前提是你得定义清楚优先级规则,不然就是拍脑袋。令牌桶的等待队列属于被动排队,只有拿到令牌的请求才会被处理。跳转服务通常建议用短队列加快速失败:队列长度控制在容量基线的百分之十到二十,等待时间上限设在一秒到一点五秒之间,超了就快速返回一个默认跳转或错误提示,别让用户对着白屏干等。
验证方法上,可以在预发环境模拟三种场景来跑:正常流量、两倍峰值流量、五倍峰值流量,观察限流触发比例、排队等待时间和最终成功率。重点看五倍峰值下系统还能不能保住核心请求的正常响应,以及被限流的请求有没有返回合理的降级内容。
高并发下的降级与熔断设计
限流和排队只能应付请求量的波动,如果下游依赖出了岔子,还得靠降级和熔断来兜底。跳转服务的下游依赖一般包括规则引擎、目标URL健康检查、日志写入这些。规则引擎查询超时是最常见的故障点,规则数据量一大的时候,单次查询从几毫秒涨到几百毫秒很常见。
降级策略什么时候触发
降级策略得提前把触发条件定好。举个例子,规则引擎查询耗时超过两百毫秒,就切换到本地缓存的规则快照;日志写入队列积压超过一万条,就临时降采样,只记错误和慢请求。降级的核心原则是保住跳转主链路,非关键路径该砍的砍、该异步的异步。需要注意,降级期间数据会丢一部分,这在一开始就要有预期,复盘阶段评估影响后再决定要不要补录。
熔断阈值怎么设
熔断一般用在调用外部服务的场景,比如调百度API回传转化数据。阈值可以参考准备阶段测出来的容量基线:外部服务的错误率超过百分之十,或者平均响应时间超过基线值的三倍,就触发熔断,直接走本地兜底逻辑。熔断之后要设一个恢复探测周期,比方说每隔三十秒放一个探测请求过去,连续三个成功就恢复调用。这个机制不复杂,但不设的话,要么熔断后一直不恢复,要么恢复了又被打挂。
复盘阶段:用压测和线上指标验证策略有效性
策略上线可不代表事情结束了,得持续用数据去验证它到底管不管用。复盘阶段的核心工作是建一套跟限流排队相关的监控指标,另外定期做压测回放,看看策略还适不适应现在的流量结构。
- 限流触发率:被限流的请求占总请求的比例,正常应该低于百分之五,持续偏高说明阈值偏低或流量结构变了
- 排队平均等待时间: 正常应该在一百毫秒以内,如果持续上涨,说明处理能力跟不上或队列配置不合理
- 跳转成功率: 核心指标,要区分正常返回和降级返回,降级比例超过百分之十需要排查原因
- P99响应时间: 反映长尾请求的体验,超过三秒的请求占比超过百分之一就要关注
验证方法上,我们一般每周做一次小规模压测回放,拿上周的真实请求日志在预发环境重放一遍,对比限流触发率和响应时间的变化。如果差异超过百分之二十,那就得重新评估阈值了。
一个实际的复盘案例
前面提到的那个家居流量站团队,他们的跳转服务最开始只做了简单的计数器限流,阈值设得挺高,基本上没触发过。后来有一次赶上百度推广的行业流量高峰,瞬时QPS涨到平时的四倍多,规则引擎查询开始超时,大量请求排队等着,最终超过一半的请求在五秒后才返回,用户早把页面关了。
他们调整的过程分了三步。头一步是把限流维度从全局改成按推广计划分层,消耗快的计划设更严格的阈值,避免单个计划把全局容量打满。第二步,把规则引擎的查询结果做了两级缓存,本地内存缓存加Redis缓存,热点规则的查询耗时从一百多毫秒压到十毫秒以内。第三步是加了短队列快速失败机制,队列长度设了两百,等待上限一秒,超了就返回一个轻量的中间页,让用户可以手动点击继续。
改完跑了一个月,高峰时段的跳转成功率从原来不到百分之五十拉回到了百分之九十五以上,P99响应时间稳定在八百毫秒左右。中间也踩过坑:分层限流的维度一开始设了五层,规则太细,运维同学排查问题时根本定位不到是哪一层触发的限流,后来收敛到三层才顺手。
限流与排队策略的检查项收束
回到评估这件事本身,判断一套限流排队策略合不合格,可以对照下面这几个检查项来看:
- 流量画像是否覆盖了峰值时段、来源分布和重试请求占比,数据是否来自至少一周的真实日志
- 容量基线是否经过压测验证,限流阈值是否留有百分之二十以上余量
- 限流维度是否控制在三层以内,是否有明确的优先级规则
- 排队队列是否有长度上限和等待时间上限,超限请求是否有合理的降级内容
- 降级和熔断的触发条件是否明确,恢复探测机制是否经过验证
- 监控指标是否覆盖限流触发率、排队等待时间、跳转成功率和P99响应时间
- 是否建立了定期压测回放机制,回放结果与线上指标的偏差是否在可接受范围内
这些检查项不用一口气全做到,按准备、执行、复盘的顺序慢慢补齐就行。关键是先把流量画像和容量基线这两个输入搞定,后面的限流排队配置才有依据,复盘也才有对照标准。限流和排队策略这东西,没有一劳永逸的配置,流量结构变了、部署环境变了、验收要求变了,策略就得跟着调。