1. 服务降级与负载均衡概述
说实话,刚入行那几年我总觉得这俩概念是各自独立的。服务降级嘛,出了问题才用;负载均衡,加机器就能搞定。直到有一次线上事故——某个读服务被突发流量打垮,下游写了七个重试链,结果像多米诺骨牌一样全挂了。嗯,从那时起我才真正明白:负载均衡分流量,服务降级控风险,两件事必须绑在一起设计。
1.1 为什么要把这两件事放在一起讲?
你看,一个完整的后端系统就像一家忙碌的餐厅——
- 负载均衡是门口的领位员:把客人均匀分到各个餐口,不让某个餐口排队太长。
- 服务降级是后厨的应急预案:如果某个灶台坏了,立刻关掉它的菜单,保证其他菜能正常出。
领位员只管分发,不管灶台坏没坏;后厨只管自保,顾不上客人等不等。但真正的高可用系统需要两者配合:负载均衡发现某个节点响应慢了,就少给它派活;降级发现上游调用太频繁,就主动拒绝一部分请求。讲白了,一个在“入口”做调度,一个在“内部”做防护,缺一不可。
我在上一家公司接手过一个跨境支付系统,高峰期每秒十几万笔交易。一开始只做了负载均衡,流量是分散了,但数据库连接池被冲垮后所有节点同时报错。后来加上服务降级——先熔断慢查询,再限流非核心业务——负载均衡才能发挥真正作用。那次教训让我把“流控+熔断+降级+负载均衡”写进了团队架构必选项。
1.2 服务降级:主动放弃保核心
服务降级不是等崩溃了才动手,而是提前设好阈值,主动砍掉非核心功能。比如双十一下单页,商品详情可以降级成缓存文本,评论模块直接关掉,只保住支付和库存。常见的降级手段见表:
| 降级类型 | 操作方式 | 典型场景 |
|---|---|---|
| 熔断(Circuit Breaker) | 调用失败率达到阈值后直接拒绝请求 | 外部API超时、数据库慢查询 |
| 限流(Rate Limiting) | 按QPS或并发数约束入口流量 | 秒杀、抢票、突发爬虫 |
| 降级开关(Feature Flag) | 通过配置中心动态关闭非核心模块 | 推荐算法、日志采集、定时任务 |
| 超时/重试策略 | 缩短超时时间,限制重试次数 | 网络抖动、下游临时高延迟 |
| 返回兜底数据(Fallback) | 当调用失败时返回缓存或默认值 | 商品详情、用户画像、库存查询 |
核心原则:降级不是把服务搞坏,而是为了保持大部分用户还能用。宁可损失30%的体验,也要保住100%的核心链路。
我曾经在优化一个物流轨迹查询服务时犯过一个错:把所有外部API的超时都设为3秒,结果上游仓储系统偶尔卡住,导致整个订单查询线程池被活活吃满。后来改成分级降级——物流轨迹降级成“运输中”三个字,订单状态走本地缓存,费用计算直接返回前一次结果。系统瞬间稳了。
1.3 负载均衡:流量分发与节点管理
负载均衡做的事说起来很简单:把请求按某种策略分到多台机器上。但真正到实战中,要考虑的东西不少——节点权重、健康检查、会话保持、动态剔除……我习惯按算法优先级来选:
| 算法 | 特点 | 适合场景 |
|---|---|---|
| 轮询 | 最均匀,不考虑负载 | 所有节点能力相同,请求耗时相近 |
| 最小连接数 | 动态感知节点当前连接数 | 长连接、WebSocket、请求处理时间差异大 |
| IP哈希 | 同一来源IP绑定到固定节点 | 有状态服务(Session)、缓存命中 |
| 加权轮询 | 给高性能节点分配更多请求 | 服务器配置异构、云端竞价实例 |
| 一致性哈希 | 节点增减时仅影响少量请求 | 分布式缓存、数据库分片 |
你想想看,光轮询其实就有很多坑。我记得有一次新上了十台机器做负载均衡,轮询策略下所有请求都平均分,但有几台老机器扛不住,新机器反而空闲。最后改成加权轮询 + 主动健康检查——老机器权重降为1,新机器权重设为3,再加上每5秒探活,这才稳定下来。
特别注意:健康检查不要只用TCP端口探测。端口通了不代表业务正常。我踩过的坑——Nginx配置了端口健康检查,后端Redis进程活着但内存打满了,每次读写都超时,结果Nginx还在继续分发请求,直到手工介入。一定要加上业务探活(比如发一条ping请求,判断返回是否异常)。
1.4 两者共同的目标:高可用与弹性
说到这儿你应该能感觉到:负载均衡让系统“能扛”,服务降级让系统“能活”。只做负载均衡,遇到雪崩时流量再均匀也没用;只做服务降级,节点能力不均衡导致频繁降级也是自残。一套成熟的架构,应该像下面这张图这样运转:
实战小贴士:落地时我一般分三步走:先做好负载均衡的健康检查和降级开关(比如用Nacos动态配置);然后对接监控系统(Prometheus + 告警),设置熔断和限流阈值;最后用故障注入(chaos engineering)验证降级效果。这样一套流程下来,哪怕明天突然百万流量进来,心里也有底。
好了,这是第一章的骨架。后面的章节里,我会带你一步步把每个模块写进代码、配进Nginx/网关、压测验证。记住一点:没有降级的负载均衡是裸奔,没有负载均衡的降级是自闭。两者结合,才能真正谈得上高可用。