6.2 限流与降级:挡住恶流量,保住主流程


6.2 限流与降级:挡住恶流量,保住主流程

摘要:限流处理"流量太大",降级处理"功能太弱"。限流在入口按阈值挡掉超额请求(令牌桶/漏桶/滑动窗口),降级在压力或故障下提供"次一级但可接受"的响应。两者常配合使用,让系统在过载时还能偏向地保住核心体验,而不是一视同仁地全崩。

熔断管的是"下游坏了",限流管的是"流量太冲",降级管的是"压力太大时别硬扛"。三个老兄弟常被一起提,但干的活不一样——本节先讲清限流怎么做,再讲降级怎么选,然后把"限流+降级"拼起来看。

限流:我要看的不是"来了多少",是"我还放行多少"

限流的核心是给系统定一个放行上限:每秒最多处理 N 个请求,超过的直接拦截(返回 429 或排队),防止后端被瞬时洪峰打穿。它保护的是"系统资源本身"。

三种常见限流算法的心智模型

  • 固定窗口:把时间切成一个个固定时间段(比如每秒一个桶),每桶限个数量。实现最简单,但窗口边界会"双倍过货"(前一个窗口尾部+后一个窗口头部一起爆量)。
  • 滑动窗口:把统计窗口连续滑动,修正边界爆量的毛病,实现略重。
  • 令牌桶/漏桶:令牌桶——以恒定速率往桶里放令牌,请求要消费令牌才能过,能容忍突发;漏桶——以恒定速率出水,把突发"削平"。

一张表选型:

算法 心智 突发容忍 实现成本
固定窗口 每段限额 窗口边界会爆 最低
滑动窗口 连续统计
令牌桶 攒令牌冲突发 好(允许攒)
漏桶 恒定速率削峰 无突发

一块常见的令牌桶读写示意(表达意图,示意成分大于完整实现):

// 令牌桶:桶里有令牌就放行,没有就拦截(语义示意) type TokenBucket struct{ tokens int; rate int; mu sync.Mutex } func (b *TokenBucket) Allow() bool { b.mu.Lock(); defer b.mu.Unlock() if b.tokens > 0 { b.tokens--; return true } return false // 超限,返回 429 }

限流放哪个层次,也有讲究:可以在网关层做(面向整个系统/按 IP 限)、在服务内做(按用户/按业务维度限)、还可以对特定下游做。别只看总量——按用户维度的限流,比按总量限流更能防单个大户把别人挤死

降级:压力下不是"全有或全无",而是"给个次中能接受的"

降级回答的是另一个问题:压不住了或依赖坏了,我怎么"省着办"还能给用户个交代? 它不是回到"什么都没了",而是主动提供一种"更省资源但依然可接受"的响应。

几类常见降级:

  • 静态降级:热点推荐挂了,就返回一个固定的"热门商品"列表页面,接口结果用一个静态值长期垫底。
  • 部分功能关闭:评论、搜索这类非核心功能,压力大时先关掉,护住下订单主流程。
  • 切换数据源:主库重时切到只读副本出数据。
  • 开关控制:用配置中心/开关在不下发代码的情况下,动态打开或关闭某个降级策略。

一个完整的"限流+降级"合力场景

把两个拼起来看一次秒杀:下单瞬间请求量冲爆。限流在网关先把超额的请求拦下(有人排队、有人干脆 429),把进入后端的量压在它能扛的水平;后端在下单主流程稳住的同时,对"猜你想买""相似推荐"这类非核心功能打开降级开关,直接返回静态列表——于是核心下单流程稳住,次要体验受损但整体可用。这个"伤次要保核心"的取舍,就是限流+降级的合力价值。它和降级的核心思想完全一致:面对超载,关键不是每条请求都成功,而是把最重要的那部分保住

陷阱一:限流挡了正常用户

限流最怕误伤真实用户。如果阈值拍脑袋定得比真实峰还要低,平时就会把好好的用户给 429 掉。所以限流的阈值要建立在历史真实峰值 + 扩容后的余量上,并且要按维度分化(IP、用户、token 各不相同),不能一刀切。"挡错的"比"全崩"更伤口碑——因为全崩能查,挡错了查不清又天天误伤。

陷阱二:降级把"响应变成错误"

降级的错误做法是把返回内容换成"出错啦"或者干脆让前端报错。降级的真意是返回一个"用户能接受、系统负担小"的结果——哪怕是"推荐暂时不可用,稍后再试"这种诚实的话,也比一坨报错好。别为了让监控"看起来没报错"而硬编一个张冠李戴的假数据,那才真是把降级做成了造假。

三个机制的位置感:限流在入口,熔断在下游,舱壁在资源

把第 6 章的几个兄弟放回一张部署图上,位置感比抽象定义更记得住:限流站在最外面(网关/入口),先按量把超额流量挡在外;熔断跟着某个具体下游调用走,那一调和哪段坏了它就在那段下;舱壁管的是每个下游各自占的资源,连接池/线程池都按下游切开。三者就像三道设在不同环节的闸,各管一段,最后一起把"雪崩"这条最大的系统性风险给拆成小风险。

之所以强调位置,是因为现实中很多"容错失效"不是没装,而是装错了地方——把限流塞进了一个具体服务内部当成万能入口,或者把熔断设在网关却拦不住下游真正坏死的那一路。放对位置,每条机制才能各司其职:总量闸在入口、坏路闸在下游、资源闸在连接池。

本节要点

  • 一句话:限流挡"太多",降级给"次级的可用",它们合力保住最重要的那部分

  • 限流防"流量太大",降级治"压力太大",熔断管"下游坏了",三者分工不同

  • 令牌桶容忍突发,漏桶削峰,滑动窗口修正窗口边界,按场景选

  • 别只看总量,按用户维度的限流更能防大户挤死小户

  • 降级是"给次级的可接受响应",静态降级/关非核心/切只读都是手段

  • 阈值建立在真实峰值上,别误伤正常用户;降级别变成造假响应


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U