高并发场景下的限流、降级、熔断与隔离

对应简历段落

在保险销售活动和月底结算高峰场景中,负责构建稳定性治理方案,包括 Sentinel 限流、接口降级、下游熔断、线程池隔离、MQ 削峰和核心链路监控告警。针对活动秒级流量突增、保司接口抖动、CRM 同步慢、结算任务集中触发等问题,保障核心投保和商机流转链路在资源有限的情况下稳定运行。

这段简历的关键在“治理”而不是“组件”。面试官会追问:限流保护谁?降级牺牲什么?熔断依据是什么?隔离隔的是什么资源?如果只能背 Sentinel 规则,很难通过资深面试。优秀回答必须把业务优先级、资源预算、失败策略和监控闭环讲清楚。

业务背景

保险销售活动高峰具备突发性。活动开始、产品停售、月底冲刺、代理人集中触达都会让投保提交、保费试算、商机查询、客户画像接口瞬间升高。系统资源却是有限的:Tomcat 线程有限,业务线程池有限,数据库连接有限,保司接口也有限。

如果没有治理,流量会按最自然的方式冲进系统。入口线程被占满、数据库连接池等待、下游 RPC 超时、MQ 消费堆积、重试流量反复放大。最后结果往往是所有接口一起变慢,而不是核心业务优先成功。

稳定性治理的目标不是让系统处理无限流量,而是在超过承载能力时有控制地失败。核心投保、商机创建、支付或结算状态推进要优先保障;短信通知、运营埋点、推荐标签、报表刷新可以延迟或降级;外部系统慢时要及时切断影响;批处理任务不能挤占在线交易资源。

核心原理

限流是入口控制,解决“流量进来太多”的问题。常见维度包括 QPS、并发数、热点参数、用户维度、活动维度、渠道维度。限流的本质是把超过系统承载能力的请求挡在便宜的位置,避免它们进入数据库、RPC 和复杂业务逻辑。

降级是功能取舍,解决“资源不够时先保什么”的问题。比如活动页可以不展示个性化推荐,客户画像可以返回基础标签,短信通知可以延迟发送。降级不是异常处理的别名,而是提前定义好的业务兜底方案。

熔断是故障隔离,解决“下游持续失败或慢调用拖垮上游”的问题。当保司接口、CRM、客户画像服务出现高错误率或高慢调用比例时,上游短时间内不再持续请求它,而是快速失败、返回缓存或进入异步重试。熔断保护的是调用方线程和整体系统稳定性。

隔离是资源切分,解决“不同业务互相拖垮”的问题。隔离可以是线程池隔离、连接池隔离、部署隔离、队列隔离、数据库表隔离。月底结算和在线投保不能共用同一批核心线程;短信通知不能占用商机分配线程池;外部保司调用要有独立并发预算。

这四者经常组合出现:入口先限流,弱依赖可降级,下游异常时熔断,不同业务用资源隔离控制影响范围。再配合 MQ 削峰和监控告警,形成完整稳定性方案。

项目落地

活动提交流程中,入口先按活动 ID 和接口维度做限流。比如投保提交比活动页查询更核心,但提交接口成本更高,所以限流阈值要基于数据库写入能力和下游消息投递能力评估。被限流的请求返回明确提示,避免用户反复点击造成更大压力。

活动页查询中,推荐标签、权益推荐、客户画像属于可降级能力。正常情况下并行查询并展示个性化内容;当画像服务超时或线程池排队过长时,返回默认推荐或基础产品信息。这样页面仍可打开,用户仍能完成核心投保路径。

保司接口调用中,熔断非常关键。保司慢调用会占住业务线程,还可能导致重试叠加。可以按保司渠道配置慢调用比例和异常比例阈值。熔断打开后,在线请求不再同步等待保司,而是返回“已受理,稍后更新状态”,并通过 MQ 或补偿任务异步查询。

月底结算中,隔离比限流更重要。结算任务数据量大、运行时间长、数据库写入重。如果和在线活动共用线程池、连接池或部署实例,很容易在月底拖慢用户链路。推荐单独线程池、单独消费组、独立调度窗口,必要时独立部署结算 worker。

商机流转中,MQ 削峰和消费限速配合使用。生产端高峰消息先进入 MQ,消费端根据数据库和代理人分配服务承载能力设置消费线程数。消费端线程池满时返回稍后重试,而不是无限堆积本地队列。

关键伪代码或流程

入口限流示意:

public SubmitResult submit(SubmitCommand command) {
    Entry entry = null;
    try {
        entry = SphU.entry("activity-submit-" + command.activityId());
        return submitService.doSubmit(command);
    } catch (BlockException ex) {
        return SubmitResult.busy("活动参与人数较多,请稍后重试");
    } finally {
        if (entry != null) {
            entry.exit();
        }
    }
}

弱依赖降级:

public CustomerTags queryTags(String customerId) {
    try {
        return tagClient.query(customerId, 150);
    } catch (TimeoutException | CircuitOpenException ex) {
        metrics.recordDegrade("customer-tags");
        return CustomerTags.basic();
    }
}

外部保司熔断后的异步受理:

public InsurerSubmitResult submitToInsurer(PolicyDraft draft) {
    if (circuitBreaker.isOpen("insurer-A")) {
        insurerTaskRepository.savePending(draft.id());
        return InsurerSubmitResult.accepted();
    }
    try {
        return insurerClient.submit(draft);
    } catch (Exception ex) {
        circuitBreaker.recordFailure("insurer-A", ex);
        insurerTaskRepository.saveRetry(draft.id(), ex.getMessage());
        return InsurerSubmitResult.accepted();
    }
}

线程池隔离:

ExecutorService submitExecutor = new ThreadPoolExecutor(16, 32, 60, SECONDS,
        new ArrayBlockingQueue<>(1000), new NamedThreadFactory("submit"));

ExecutorService crmExecutor = new ThreadPoolExecutor(4, 8, 60, SECONDS,
        new ArrayBlockingQueue<>(300), new NamedThreadFactory("crm-sync"));

ExecutorService settlementExecutor = new ThreadPoolExecutor(4, 8, 120, SECONDS,
        new ArrayBlockingQueue<>(5000), new NamedThreadFactory("settlement"));

治理流程:容量压测得到核心资源上限;按业务优先级配置限流阈值;弱依赖准备降级数据;外部依赖配置超时和熔断;不同业务拆分线程池和消费组;高峰期间观察 QPS、RT、错误率、线程池、连接池、MQ 积压和熔断次数;高峰后复盘阈值是否合理。

常见坑与排查

第一个坑是限流阈值拍脑袋。阈值过高等于没保护,过低会误伤业务。阈值应来自压测、历史峰值、数据库连接池和下游 SLA。

第二个坑是只限入口不限热点参数。同一个活动、同一个产品、同一个客户反复请求可能形成热点。热点参数限流能避免局部资源被打爆。

第三个坑是降级没有业务确认。技术上返回默认值很容易,但业务上是否允许、展示文案是什么、是否影响合规,都要提前确认。

第四个坑是熔断没有半开探测。熔断打开后如果不探测恢复,下游恢复了上游也可能长期不用。半开状态应允许少量请求试探。

第五个坑是线程池隔离只拆名字不拆资源。多个线程池如果共用同一个数据库连接池,下游资源仍然会互相影响。隔离要看真正瓶颈在哪里。

第六个坑是重试和限流互相打架。大量失败请求快速重试,会让流量超过原始峰值。重试必须有退避、上限和熔断。

面试追问

追问一:限流、熔断、降级有什么区别?

追问二:限流阈值怎么确定?

追问三:哪些功能可以降级?降级如何不影响核心业务?

追问四:熔断后如何恢复?

追问五:线程池隔离和舱壁模式有什么关系?

追问六:高峰期接口大量超时,你怎么定位?

推荐回答

我会先用一句话区分:限流控制入口流量,降级是业务功能取舍,熔断是隔离故障下游,隔离是切分资源边界。它们解决的问题不同,但在高并发场景中要组合使用。

在项目里,我会先做容量评估,确认核心链路数据库写入、MQ 投递、下游接口的承载上限。活动提交按活动维度限流,活动页弱依赖可降级,保司和 CRM 这类外部依赖设置超时和熔断,月底结算使用独立线程池和消费组。超过系统能力时,优先保证用户提交和商机创建,牺牲推荐、通知、报表等非核心能力。

排查超时时,我会从入口 QPS、RT、限流命中、线程池 active 和 queue、数据库连接等待、下游慢调用、MQ 积压、熔断状态逐层看。高并发问题通常不是一个点坏了,而是某个资源先慢,然后通过同步等待和重试扩散。

延伸学习路线

第一阶段,掌握稳定性基本概念:限流、降级、熔断、隔离、超时、重试、幂等。

第二阶段,学习 Sentinel 或 Resilience4j 的规则模型,包括 QPS、并发数、热点参数、慢调用比例、异常比例、半开恢复。

第三阶段,学习容量规划。用压测数据估算接口阈值、线程池大小、连接池大小、MQ 消费能力和最大可接受积压。

第四阶段,学习故障演练。模拟下游超时、数据库慢、MQ 积压、线程池满、缓存失效,观察治理策略是否真的生效。

第五阶段,形成业务优先级矩阵。把每个接口和异步任务标为核心、重要、可降级、可延迟,稳定性设计才会从技术方案变成业务方案。