做高并发系统这么久,我见过太多项目在流量峰值前临时抱佛脚。数据库连接被打满、线程池拒绝服务、一个慢接口拖垮整条调用链,这些问题本质都一样:系统没有一个主动“放手”的机制。限流、熔断、降级,就是应对亿级流量的三大核心防线。这篇文章不讲虚的,从算法原理、参数计算、Redis落地,到全链路整合和实际踩坑,完整拆一遍,适合后端开发、架构师,以及所有需要保障线上稳定性的同学。
1. 先搞清楚:亿级流量是怎么把系统打垮的
1.1 系统崩溃的根源不是流量本身,而是资源竞争
很多人一听到“亿级流量”,第一反应是加机器。但真实情况往往更复杂。流量冲进来的时候,你以为瓶颈是CPU,其实最先告警的往往是数据库连接池、线程池、文件句柄这类“有限资源”。我举个生活化的例子:一家餐厅门口突然涌进来一万个人。餐厅不是被“人多”这件事弄垮的,而是被“同时抢座、同时下单、后厨同时出菜”打垮的。每一环都要争抢有限的资源,一旦某个环节排队积压,整个餐厅就瘫痪了。
在技术系统里,表现就是:应用线程被慢SQL占满,HTTP请求不断在队列里堆积;连接池被占满,新的请求直接拒绝;内存里塞满了等待处理的请求对象,GC频率飙升,CPU忙于处理垃圾回收而不是业务逻辑。你会发现系统不是慢慢变慢,而是从一个临界点开始,断崖式崩溃。这个临界点,就是系统的真实容量上限。
所以,限流、熔断、降级这三道防线,本质上是在回答同一个问题:当系统到达容量上限时,你到底选择让谁进来、让谁等待、让谁放弃。没有这个决策机制,系统就会被“无差别流量”击穿。
1.2 限流、熔断、降级不是同一个概念,别混着用
我面试候选人的时候,经常问一句话:限流、熔断、降级的区别是什么?很多人答不上来,或者混为一谈。这三者确实是高可用体系的组成部分,但守护的位置完全不同。
限流,是控制“入口”的流量速率,防止超过系统承载能力的请求进入系统。它回答的是“让多少流量进来”的问题。熔断,是保护“调用链”的稳定性,当下游依赖出现故障时,快速失败,防止故障沿着调用链向上游扩散。它回答的是“下游挂了怎么办”的问题。降级,是主动“舍弃”部分非核心功能,牺牲次要能力,保证核心链路可用。它回答的是“资源不够时保什么”的问题。
这三者的关系,用厨房来比喻:限流是餐厅门口的排号机,控制有多少人能进店;熔断是厨师发现某个菜品食材变质了,立即停止做这个菜,而不是继续浪费精力;降级是高峰期菜单只保留招牌菜,砍掉费时费力的工艺菜。三者配合,才能让餐厅在客流爆满时依然稳定出餐。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 限流:第一道闸门,把流量挡在系统可承受范围之前
2.1 四种经典限流算法怎么选
限流算法是基础,选错了后面全白搭。我遇到很多项目,代码里写了个计数器就开始限流,结果瞬时流量一来,限流效果等于零。这里把四种主流算法拉出来对比,大家可以根据场景直接对号入座。
| 算法 | 核心思路 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 固定窗口计数器 | 每个时间窗口内计数,超限即拒绝 | 实现简单,内存占用极小 | 窗口边界存在双倍突发穿透 | 简单内部接口、低频保护 |
| 滑动窗口计数器 | 把窗口切成多个小格,滑动统计 | 相比固定窗口,边界穿透明显缓解 | 粒度越细,存储与计算成本越高 | 一般业务接口限流 |
| 漏桶算法 | 请求进入桶中,以固定速率漏出 | 输出速率恒定,对下游最友好 | 面对突发流量不够灵活,容易积压丢弃 | 对下游保护要求极高的场景 |
| 令牌桶算法 | 以固定速率生成令牌,请求需获取令牌 | 允许一定突发流量,兼顾平稳与弹性 | 需要维护令牌生成器,复杂度略高 | 网关限流、大部分业务场景 |
固定窗口计数器的思路就是:1秒内最多允许100个请求,用一个计数器累加,超过就拒绝,每过一秒清零。这个算法最大的坑在边界:假设窗口是1秒,第1秒最后10ms来了100个请求,第2秒前10ms又来了100个请求。从单窗口看都没超限,但实际在20ms内打进来了200个请求,系统照样被冲垮。这就是经典的“窗口临界穿透”。
滑动窗口计数器算是对固定窗口的修补。把1秒拆成10个100ms的小格,记录每个小格内的请求数,滑动统计当前1秒内的总数。临界穿透问题大幅缓解,但也不是绝对消除,因为小格之间仍然存在更细粒度的边界。漏桶和令牌桶是更成熟的方案。漏桶天然削峰填谷,不管流量多猛,出去的速度恒定,适合保护数据库这类不希望被瞬间打满的组件。令牌桶则允许一定程度的突发,比如桶里有100个令牌,流量突然来200个请求,前100个能立即通过,后面100个只能等令牌,这样既照顾了正常突发,又不会让系统超载。
我在实际项目中,网关层一般用令牌桶,因为入口流量往往有突发特征;应用层对下游依赖的调用保护,倾向于漏桶,因为我要保护的是数据库或者第三方接口,恒定速率比灵活突发更重要。
2.2 Redis分布式限流怎么落地
单机限流好做,本地内存里开个计数器就行。但一旦服务多实例部署,单机限流就失灵了——每个实例各自计数,整体流量可能已经是单机阈值的10倍。这时候就需要分布式限流,而Redis是业界最常用的方案。
Redis限流的核心,是用Lua脚本保证“读取-判断-写入”的原子性。别用“先GET再INCR”的方式,因为并发下多个线程可能同时读到同一个旧值,导致计数不准。正确做法是把逻辑塞进Lua脚本里,让Redis单线程执行,天然原子。
固定窗口的Redis限流脚本,逻辑很简单:用当前时间作为key,INCR后判断是否超过阈值。但正如前面说的,固定窗口有边界穿透问题,所以我更推荐滑动窗口实现。滑动窗口在Redis里通常用ZSET(有序集合)实现:每个请求到来时,把一个带时间戳的成员插入ZSET,然后删除窗口之前的过期成员,再用ZCARD统计窗口内的请求数,超限就拒绝。对应的Lua脚本大概长这样:
lua复制local key = KEYS[1]
local now = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local limit = tonumber(ARGV[3])
local member = now .. "_" .. ARGV[4]
redis.call('ZADD', key, now, member)
redis.call('ZREMRANGEBYSCORE', key, 0, now - window)
local count = redis.call('ZCARD', key)
redis.call('EXPIRE', key, window)
if count > limit then
return 0
end
return 1
这段脚本的细节值得说一说。每个请求的member必须唯一,所以我在时间戳后面拼了一个请求唯一标识ARGV[4],避免并发下两个请求的时间戳完全相同,导致ZADD覆盖同一个成员。EXPIRE也必须要加,否则key永远不删,Redis内存会被慢慢吃光。ZREMRANGEBYSCORE用于清理窗口外的旧记录,保证统计的一定是最近window时间内的请求数。
实际使用时,每次请求都要执行这段脚本,对Redis性能有一定压力。我的经验是,限流用的Redis实例最好和业务缓存分开,单独部署,避免限流逻辑影响正常业务读写。另外,Redis本身的超时时间要设置得很短,比如50ms,一旦Redis抖动,限流服务要快速失败,直接放行,而不是让所有请求都卡在等待Redis响应上。
2.3 单机限流与分布式限流怎么配合
很多人纠结一个问题:到底用单机限流还是分布式限流?我的答案是:层级不同,选择不同。在入口网关层,一定要用分布式限流,因为网关是所有流量的汇聚点,只有在这里统一计数,才能控制住整体的入口流量。在应用层内部,每个实例做单机限流就够了,因为入口已经控制了总量,应用层单机限流的目的是保护当前实例的自身资源,防止某个实例因为负载不均而被打垮。
一个典型的配置是:网关层限制某个API的总QPS为10000,同时每台应用实例自身再限制单机QPS为1000。假设网关下挂了20台应用实例,理论上总容量是20000,但网关只放进来10000,这样即使部分实例宕机,剩余实例也不会被全部流量压垮。这种双层限流的思路,比单纯依赖某一层更稳健。
这里有个容易被忽略的点:网关层的限流阈值,不是简单加总后端实例的容量,而是要考虑冗余。比如20台实例,每台压测上限是1000 QPS,那正常情况下总容量是20000,但网关限流阈值建议设置在15000左右,留出约25%的冗余空间,用于应对单台实例故障后的流量重新分配。
2.4 限流阈值怎么定:压测是唯一参考
限流阈值绝对不能拍脑袋。我见过太多项目,架构师写了“限流1000 QPS”,问为什么是这个数字,答“大概差不多吧”。这种阈值上去,要么误伤正常用户,要么压根没起到保护作用。
正确的做法是,先对系统进行全链路压测,找到系统的真实容量拐点。怎么找?逐步加压,观察系统的RT(响应时间)和错误率。刚开始加压,RT平稳,错误率为0;继续加压,某个节点开始RT明显上涨,错误率慢慢增加;再往上压,RT急剧恶化,错误率飙升。这个“从平稳到恶化”的拐点,就是系统的真实容量上限。
限流阈值应该设置在容量的70%到80%左右。比如压测发现系统在1000 QPS时开始恶化,那限流阈值就设为700到800 QPS。为什么不是1000?因为压测环境通常比较干净,线上有波动、有热点、有慢请求,如果按满负荷设置,一个波动就容易冲破上限,导致系统进入不可控状态。
3. 熔断:不让一个坏节点拖垮整条链路
3.1 熔断器状态机:三个状态和一个循环
熔断的设计灵感来自电路保护器。我经常用一个类比来解释:家里电路短路时,空气开关会跳闸,断电保护线路。熔断器在代码里也是同样逻辑,只是它管的是服务调用。
熔断器有三个核心状态:关闭(Closed)、打开(Open)、半开(Half-Open)。关闭状态下,所有请求正常通过,但系统在背后默默统计错误率。当错误率超过阈值,熔断器从关闭切换到打开。打开状态下,所有请求直接快速失败,不再真正调用下游。但熔断器不会永远打开,否则下游恢复了也没人知道。它会经过一个冷静期,进入半开状态。
半开状态是熔断机制里最核心的设计。它允许少量请求试探性地通过,去调用真实的依赖。如果这些试探请求成功了,说明依赖已经恢复,熔断器重新关闭,全量流量放行;如果试探请求还是失败,熔断器马上回到打开状态,继续阻断流量。这个“试探-确认-恢复”的循环,才是熔断器能够自适应恢复的关键。
3.2 熔断参数怎么算:别让拍脑袋毁了整套机制
熔断器的参数设置,直接决定它是保护系统还是误伤系统。我总结过一套可行的计算路子,分享出来供大家参考。
首先看请求量阈值。熔断器不是一开始就统计错误率,而是要等请求数达到一定数量才会触发判定。这个阈值的作用是避免流量很小时,一两个错误就导致熔断。比如某个接口每分钟只有10次调用,有一次超时,错误率就是10%,如果这时候触发熔断,反而得不偿失。一般建议请求量阈值设为接口正常流量的几个百分点以上,比如正常每分钟1000次,那就设为50到100次。
然后是错误率阈值。常见的默认值是50%,但我认为要根据业务容忍度调整。核心链路建议设低一些,比如30%;非核心链路可以设高一些。错误率阈值定得太低,依赖一抖动就熔断,影响面太大;定得太高,又起不到保护作用。
最关键的参数是熔断休眠期(sleepWindow)。它决定熔断器打开后,要等多久进入半开状态。太短,比如5秒,下游还没有恢复,半开的试探请求一进来马上又触发熔断,熔断器会反复抖动,系统震荡;太长,比如5分钟,下游可能早就恢复了,但流量一直被快速失败,白白损失可用性。我的经验是,先设置30秒,再根据下游恢复的平均时间动态调整。
还有一个必须说的参数是超时时间。熔断器触发的前提是“调用失败”,而超时是最常见的失败原因。如果超时时间设置得比下游正常RT大太多,比如下游正常200ms,你设置了5秒超时,那么在下游故障时,线程会被大量占用等待超时,很快把线程池打满。超时时间一般设为下游P99 RT的2到3倍,这样既能容忍正常抖动,又不会让线程长时间挂在故障请求上。
3.3 开源的熔断方案怎么选
现在做熔断,绝大多数情况不需要自己造轮子。常用的开源方案有Hystrix、Resilience4j、Sentinel,我简单做个对比。
| 框架 | 特点 | 适用场景 |
|---|---|---|
| Hystrix | 功能全面,线程池隔离,但已停更 | 老项目维护 |
| Resilience4j | 轻量级,基于Hystrix设计,支持多种容错机制 | Spring Boot应用 |
| Sentinel | 阿里开源,功能丰富,控制台强大,支持流控/熔断/系统保护 | 微服务分布式场景 |
我个人的经验是,没有绝对最好的框架,只有最合适的。如果你用的是Spring Cloud Gateway和Spring Boot生态,Resilience4j集成起来很顺;如果你需要图形化配置流控规则、实时监控,Sentinel的控制台明显更有优势。Hystrix我建议新项目不要再引入了,它已经进入维护模式,社区不活跃,而且线程池隔离方案本身开销很大。
我在一个项目里用过Hystrix的线程池隔离,每个依赖都分配一个线程池,保护效果确实好,但线程池数量一多,内存和线程开销就很可观。后来换成信号量隔离,才把资源开销降下来。这里提一句,线程池隔离适合耗时长、容易阻塞的调用,信号量隔离适合耗时短、并发高的调用。很多人在Hystrix里默认用线程池,其实要根据依赖的特性来选。
4. 降级:关键时刻敢于“舍弃”
4.1 主动降级和被动降级的区别
降级这件事,很多团队都犯过一个错误:以为降级就是“系统挂了之后被动的兜底”。实际上,降级分为主动降级和被动降级,两者使用时机完全不同。
主动降级,是在系统触发了一定的规则之后,主动降低部分功能的可用性。比如大促期间,把评论列表功能降级为“只显示缓存内容,不实时入库”,把商品详情页的某些非核心模块直接隐藏。主动降级是预案,是提前设计好的策略,不是事故发生后的临时抱佛脚。
被动降级,是系统检测到异常后,自动执行的兜底逻辑。比如调用商品服务超时了,框架自动返回默认库存,或者直接走本地缓存。被动降级通常是熔断之后的最后一道保险。
这两种降级并不是互斥的,一个成熟系统里两者都会存在。我建议每个核心接口都至少设计一套被动降级方案(即发生异常时返回什么兜底数据),同时在大促、秒杀等已知流量高峰前,提前配置好主动降级。两手准备,才能真正确保高可用。
4.2 降级怎么分级、怎么设计开关
降级最容易踩的坑,是“一刀切”。所有非核心功能全部降级,结果用户发现核心流程也受到了影响。降级策略应该分级设计,我通常把降级分成三个级别:
- L1级(核心链路):如登录、下单、支付,绝不降级;
- L2级(重要链路):如购物车、库存查询,在极端情况下可以降级,比如库存改为读取缓存,延迟容忍提高到1秒;
- L3级(非核心链路):如推荐、评论、消息通知,在资源紧张时可以整体关闭。
这个分级不是写死在代码里的,而是通过配置中心动态下发。我在项目里使用配置中心统一管理降级开关,每个接口有一个独立的开关key,比如degrade.order.query.switch,值为true表示降级开启,false表示关闭。运维和开发可以通过配置中心一键降级,不需要发版,不需要重启。
这里有一个实操细节需要注意:降级开关的配置项必须足够细分,但也不能过于细碎。我们曾经把每一个接口都独立配置开关,结果接口一多,配置内容多到根本没人愿意维护,最终降级开关形同虚设。经过调整,只为核心依赖、核心接口配置独立开关,其余接口按调用方维度聚合配置,既满足了快速降级的需求,又保证了可维护性。
4.3 降级的典型场景:电商下单链路
拿电商下单这个典型场景来说,一个下单操作会涉及用户校验、库存查询、价格计算、优惠券核销、订单生成、支付单创建、消息通知等多个依赖。如果所有依赖都要实时调用,任何一个下游抖动,下单成功率都会受影响。
我的降级设计思路是这样的:用户校验和订单生成是核心中的核心,绝不降级;库存查询降级为读缓存,即使缓存中没有最新库存,也允许订单创建,在后台异步更新扣减记录;价格计算降级为读取缓存中的商品价格,不实时计算满减和优惠券;优惠券核销降级为不校验优惠券是否可用,直接按用户提交的优惠价下单,事后异步校验;消息通知属于最外层,直接降级为不发送,或者用本地消息表异步补发。
这样一环环降下来,在线下单最差的情况下,也能保证“用户提交订单、系统返回成功”这个核心目标。至于优惠少了、库存超卖、通知延迟,都是事后可以补偿的问题。这就是降级的核心思维:先保核心,再谈完美。
4.4 降级实现时的三个隐藏坑
第一个坑:降级逻辑本身拖垮系统。降级时要返回兜底数据,但这个兜底逻辑里如果又去查数据库、调外部接口,那降级就失去了意义。我的经验是,降级策略必须使用本地缓存或者内存中的默认值,不能再依赖任何外部资源。
第二个坑:降级后没有恢复机制。降级不是永久状态,服务恢复后要能自动回到正常流程。很多团队做了降级开关,但忘了做“自动恢复”的判断,结果依赖已经恢复,业务还一直跑在降级逻辑上,数据出现大量不一致。我建议降级开关不仅支持手动开启,也要支持配置自动探测,比如连续N次依赖调用成功,就自动关闭降级。
第三个坑:降级没有监控。降级最怕的是“降了没人知道”。线上有一段时间大量请求在走降级逻辑,但监控面板没有任何提示,大家以为系统一切正常。我在做降级设计时,会在降级分支里埋一个Metrics埋点,降级次数一旦超过某个阈值,立刻告警。要让降级可见、可数、可告警,否则这个机制就是摆设。
5. 全链路整合:网关、应用、数据层逐层设防
5.1 一次请求从入口到后端经历了哪些防线
全链路稳定性的关键,在于“每一层都有限流的影子,每一个依赖都有熔断和降级预案”。下面我梳理一个典型请求从入口到后端会经过的防线。
第一层是接入层,也就是Nginx、SLB或者API网关。这一层主要做全局维度的流量限制,比如按IP、按用户维度限流,或者按某个接口的总QPS限流。第二层是应用层,服务框架中配置限流、熔断、降级规则,对内部依赖调用进行保护。第三层是数据层,数据库连接池设置最大连接数,Redis设置最大内存和过期策略,防止数据库和缓存被打穿。
这三层之间不是孤立的,而是上下联动。网关把流量控制在系统总容量之内,应用层在单个服务实例维度保护资源,数据层在底层拦截异常流量。就拿我前面说的电商下单链路举例:网关限流保护下单接口总入口,应用层对库存服务、优惠券服务分别配置熔断,数据层对数据库连接池进行严格限制。一旦某个下游依赖出现故障,熔断器快速打开,降级逻辑随即生效,网关的限流保证整体流量不会超过系统承载能力,整个链路就不会雪崩。
5.2 各层配置怎么配合
配置上的配合,我的经验是“自下而上压阈值,自上而下控总量”。什么意思?先通过压测确定数据层能扛多少连接、应用层能扛多少QPS,然后应用层的限流阈值参考数据层容量来设置,网关层的限流阈值参考所有应用实例的总容量来设置,层层类比,确保每一层都不会被上一层打爆。
举一个具体的配置案例:假设有10台应用实例,每台压测容量为500 QPS,那么应用层单机限流可以设为400 QPS(80%容量),数据层连接池设为最多支持4000 QPS的查询量,网关层总限流设为3000 QPS(10台*400 QPS,再打75折作为冗余空间)。这样即使某一台实例宕机,剩余的9台实例(总容量3600 QPS)依然能扛住网关放行过来的3000 QPS流量。
这里还要强调超时配置的一致性。很多故障的根源是各层超时时间配置不匹配。比如网关超时设了3秒,应用层调用下游超时设了5秒,结果下游慢请求大量堆积在应用层,网关早就超时断开了,但应用线程还在傻等。正确的做法是,越往下层超时设置越短。网关超时3秒,应用层调用下游超时1.5秒,数据层查询超时0.5秒,层层收敛,保证请求不会在深层停留过久。
5.3 全链路演练:如何验证防线真的有效
配置再好,不演练永远不知道真实效果。我经历过一次线上事故,限流、熔断、降级都配了,但真出问题时才发现:限流阈值设得太高,没起到保护作用;熔断的错误率判定条件不满足,熔断器半天没打开。所以我强烈建议,每个核心链路都要定期做全链路稳定性演练。
演练的方法并不复杂。准备一套生产环境的镜像测试环境,用压测工具模拟流量高峰,然后人为注入故障。具体可以分几个步骤来做:第一步,只压测正常流量,验证限流阈值是否合理,观测RT和错误率在阈值临界点的表现;第二步,模拟下游服务故障,比如把库存服务关闭,验证熔断器能在预期时间内打开,并验证降级预案是否生效;第三步,模拟流量超出网关限流阈值,验证入口处是否按预期拒绝请求,客户端是否收到合理的错误提示;第四步,检查监控系统,确认限流次数、熔断次数、降级次数都有指标记录,并且告警能正常触发。
演练的意义不光是验证配置,更是验证团队的执行流程。出问题时,值班人员应该从哪里看监控、按什么顺序排查、手动降级开关在哪里,这些都要通过演练熟起来。等线上真正出问题了再去翻文档,时间根本来不及。
5.4 监控与告警:让防线“看得见”
限流、熔断、降级三件事,最怕“隐形”。如果没有任何监控指标,你根本不知道当前系统有多少流量被限流拒之门外、熔断器处于什么状态、有多少请求走了降级逻辑。
我通常会为三大机制分别建立监控大盘。限流指标包括:各接口限流触发次数、被限流的请求占比、当前QPS与限流阈值的比例;熔断指标包括:熔断器当前状态(关闭/打开/半开)、打开次数、半开试探成功率;降级指标包括:降级触发次数、降级比例、降级后核心接口的成功率。
告警规则也要分级。一般性告警,比如限流触发次数开始上升,说明流量在增长,可能接近容量上限了,需要关注;重要告警,比如某个熔断器打开,说明依赖可能故障,需要立即排查;紧急告警,比如多个熔断器同时打开,或者核心接口降级比例超过50%,说明系统正在经历严重故障,需要马上进入应急预案。
监控数据为运维提供了“看得见”的抓手。我见过太多系统,容错机制配置得漂漂亮亮,但真出问题时,运维两眼一抹黑,连系统当前处于什么状态都搞不清楚。没有监控的防线,等于没有防线。
6. 实战中最容易踩的坑
6.1 限流误伤正常用户
限流阈值设置过低,或者限流维度设计不合理,导致大量正常用户被拒绝。比如按IP限流,会出现公司出口IP下所有用户共享一个配额,一个办公室的人多了,集体被限。这个问题在移动网络下尤其明显,出口NAT会把很多用户集中在一个IP上。
我的建议是,限流维度要尽量贴近业务身份。用户维度用userId,不依赖IP;接口维度用接口名,全局统一配额。在进行限流策略设计时,优先考虑业务属性,而不是网络属性。
6.2 熔断参数不合理导致反复抖动
熔断器参数设置不合理,最常见的现象是熔断器打开后又快速半开,半开试探请求又触发失败,熔断器再次打开,如此反复。系统在“熔断-试探-再熔断”之间来回震荡,下游依赖明明已经恢复了,却因为这个抖动周期持续处于不稳定状态。
解决这个问题的关键在于合理设置休眠期,并且给半开状态设置独立的并发限制,比如半开状态最多允许2个试探请求并发执行,避免试探请求一次性涌入太多,再次压垮正在恢复的下游。
6.3 降级策略被绕过
有些团队把降级逻辑写在catch分支里,但调用链路的某个环节根本没有被try-catch覆盖,导致异常直接抛出,降级代码根本没执行。另一种情况是,框架层面做了降级,但业务代码里对降级返回的默认值没有做非空判断,拿到null之后直接NPE,反而引发了更严重的故障。
我的建议是,降级策略要在设计阶段就纳入接口契约。每个核心接口必须明确降级时的返回结构,调用方要对降级返回值做专项测试,确保降级链路本身不会成为新的故障源。
6.4 一个可复用的检查清单
根据我多年的实战经验,整理了一份简单可复用的检查清单,大家在做全链路稳定性改造时可以直接对照使用:
- 每个入口接口是否有网关层分布式限流,阈值是否基于压测结果设定;
- 每个依赖调用是否配置了超时时间,超时时间是否层层收敛;
- 核心依赖是否配置了熔断器,熔断参数是否经过压测验证;
- 每个核心接口是否设计了降级预案,降级分支是否有监控埋点;
- 限流、熔断、降级的指标是否都接入了监控大盘,告警是否配置;
- 是否定期执行全链路稳定性和故障注入演练。
这套清单看着简单,但每一条背后都是一个真实的线上事故教训。技术方案本身不难,难的是把这些细节都落实到位,并且保持长期有效。
最后再分享一个我个人的体会。限流、熔断、降级这三件事,真正难的不是技术实现,而是“敢于舍弃”的决策。熔断敢不敢打开?降级敢不敢砍功能?很多团队在关键时刻犹豫了,总想着“再撑一下”,结果系统全面崩溃。做高可用系统,预案要提前做好,决策权要提前下放。真到流量峰值那一刻,执行预案比临场思考重要一万倍。希望这篇文章能帮大家少踩一些坑,把系统真正打造成“扛得住”的架构。
