Skip to content
xiaoyuuuuuupeng
Go back

1.2 基于 sqg-env-config 的业务服务韧性支持方案

状态:方案草案

更新日期:2026-08-14

能力载体:sqg-env-config 基础框架

适用对象:所有接入 sqg-env-config 的 Spring Boot 业务服务

1. 背景

sqg-env-config 当前定位是业务服务的基础框架,通过切面、拦截器和中间件扩展点,对 Redis、MySQL、HTTP、Dubbo、Kafka、RabbitMQ、Elasticsearch 等调用进行统一日志记录。

本方案不是为 sqg-env-config 自身增加业务层面的熔断或降级,而是把它建设成服务韧性能力的统一承载框架:任何接入 sqg-env-config 的业务服务,都可以低成本获得针对自身入口流量和外部依赖调用的保护能力。

职责边界如下:

层次对象职责
被治理主体接入 sqg-env-config 的业务服务承载业务请求,调用 Redis、MySQL、HTTP、RPC、MQ 等资源
能力承载层sqg-env-config自动识别资源、接入调用边界、提供注解/config/fallback/异常分类和统一可观测性
规则执行层Sentinel Core完成统计、限流判断、熔断状态机、半开探测和系统保护
业务扩展层具体业务应用仅在需要业务语义时声明资源名称、覆盖规则或提供 fallback 策略

因此,文档中所称的“服务保护”“入口保护”“外部资源保护”,其保护对象始终是接入框架的业务服务;sqg-env-config 是实现和分发这些能力的基础设施。

现阶段 sqg-env-config 已能为业务服务提供中间件可观测能力,但还不能为这些业务服务提供以下保障:

本方案参考 go-zero 的“稳定性能力默认内建”思路,但不直接照搬其 Go 代码;Java 侧优先采用 Sentinel Core 作为可靠的规则执行与状态管理内核,由 sqg-env-config 将这些能力透明地提供给接入它的业务服务。

2. 建设目标

2.1 目标

  1. 接入 sqg-env-config 的业务服务,其已被框架拦截的中间件原则上无需额外编码即可获得指标采集和可选保护。

  2. 业务自定义外部资源只需增加一个 sqg 注解,并在需要时指定 fallback。

  3. 默认采用安全的 observe 模式,不直接拒绝线上请求。

  4. 保护规则提供内置默认值,并允许通过 YAML 按资源覆盖。

  5. Sentinel 只作为内部引擎,不向业务暴露 Sentinel 注解和异常。

  6. 为未来接入 Nacos、Dashboard 或替换其他引擎保留扩展点。

  7. 支持同步、CompletableFuture 以及常用异步中间件的正确生命周期统计。

  8. 同一套基础框架能力可在不同业务服务中复用,但每个服务实例独立统计、独立熔断并支持独立规则覆盖。

2.2 非目标

第一阶段暂不包括:

3. 概念边界

服务韧性需要区分以下能力,避免统一称为“限流”后产生错误设计。

能力保护对象触发信号典型结果
熔断 Circuit Breaker不健康的外部依赖异常比例、异常数、慢调用比例暂停调用并快速失败
限流 Rate Limit指定资源的调用速率QPS 或固定配额拒绝或匀速排队
并发隔离 Bulkhead线程、连接和资源池同时执行数量超限快速失败
自适应降载 Load Shedding当前应用实例CPU、load、RT、吞吐、入口并发拒绝部分入口流量
超时 Timeout单次调用调用持续时间中止等待并返回超时
降级 Fallback被阻断或失败的调用熔断、限流、超时或业务指定异常缓存、默认值、排队或友好错误
重试 Retry短暂性故障可重试错误再次调用,可能放大流量

下游熔断解决“不要继续调用已经不健康的依赖”,入口降载解决“不要让当前应用自身被压垮”,二者不能互相替代。

4. go-zero 实现调研结论

4.1 下游自适应熔断

go-zero 的 breaker 基于 Google SRE 客户端自适应节流思想。当前代码的主要特征是:

核心拒绝概率可以抽象为:

dynamicK = f(连续失败 bucket 数量)

dropRatio =
    (total - protection - dynamicK * accepts)
    / (total + 1)

算法代码本身规模不大,但它依赖线程安全滑动窗口、时间处理、随机概率、上下文取消识别、指标记录以及各组件的异常分类。

4.2 入口自适应降载

go-zero 的 load shedder 是独立于 breaker 的另一套实现,主要根据以下条件决定是否丢弃新请求:

其容量估算思想可简化为:

maxFlight ≈ maxQPS × minRT

只有系统过载并且当前并发超过估算容量时才降载,避免仅凭 CPU 瞬时尖峰直接拒绝流量。

4.3 go-zero 自动应用范围

go-zero 的 breaker 已集成到 zRPC、HTTP 客户端/服务端、Redis、sqlx/MySQL、Mongo 等组件。但“自动集成”并不等于所有调用路径都必然经过熔断器:raw client、自定义连接、事务内部调用或绕开框架封装的 API 仍可能绕过保护。

4.4 是否建议直接重写

只实现 breaker 算法原型并不重;将其建设成基础框架生产能力较重。

范围粗略成本说明
Java breaker 原型3~5 人日证明公式可运行
生产级 breaker 内核10~20 人日并发窗口、时间、恢复、事件和测试
再实现自适应 load shedder增加 10~20 人日JVM/容器指标和容量校准风险更高
通过 sqg-env-config 完整赋能业务服务总计 40~70 人日包含全部中间件、fallback、配置、可观测和灰度

手写方案的长期风险主要来自算法外围,而不是拒绝概率公式本身。

5. Java 方案对比

5.1 Sentinel

Sentinel 的定位是以 Resource 为中心的流量治理和服务保护引擎,核心能力包括:

注意事项:

5.2 Resilience4j

Resilience4j 的定位是轻量级、可组合的容错策略库,优势包括:

其不足是:

5.3 综合对比

维度自研 go-zero 风格Sentinel CoreResilience4j
核心定位自适应熔断/降载算法资源级流量治理引擎应用内容错策略库
维护状态由团队自行负责活跃开源项目活跃开源项目
初期依赖无第三方治理依赖仅 sentinel-core 可很轻可按模块引入
熔断模型概率式逐步拒绝明确状态机明确状态机,配置细致
慢调用保护需要自建慢调用比例熔断慢调用比例熔断
QPS 流控需要自建支持支持
并发隔离需要自建并发线程数控制Semaphore/ThreadPool Bulkhead
Retry需要自建非核心能力原生支持
Timeout需要自建由调用组件负责原生 TimeLimiter
自适应系统保护可复制 go-zero支持入口系统规则无对应能力
调用链/来源规则需要自建支持不突出
动态规则体系需要自建支持并可扩展数据源以 Registry/配置为主
Dashboard需要自建可选无对应官方治理台
Java 8 适配可自行控制支持需使用旧版本
Spring 事务兼容可自行设计同线程调用,适配相对自然信号量模式自然,线程池模式需传播上下文
自动中间件治理全部自行建设sqg 适配后适合sqg 适配后可实现
初期开发成本
长期维护风险中,受 Java 版本约束

5.4 方案结论

当前推荐:

Sentinel Core + sqg-env-config 自有适配层

不推荐:

如果未来升级至 Java 17,并且目标收缩为“显式的熔断、重试、超时、隔离策略组合”,可以重新评估 Resilience4j。

6. 面向业务服务的推荐总体架构

flowchart TD
    A["业务方法或中间件调用"] --> B["sqg 自动切面/拦截器"]
    A --> C["@SqgResource"]
    B --> D["ResourceResolver"]
    C --> D
    D --> E["SqgResilienceEngine"]
    E --> F["SentinelResilienceEngine"]
    F --> G["sentinel-core"]
    H["YAML 默认规则与资源覆盖"] --> I["SqgRuleManager"]
    I --> E
    J["SqgFailureClassifier"] --> E
    E --> K["SqgFallbackResolver"]
    E --> L["日志/指标/事件"]
    K --> M["fallbackMethod"]
    K --> N["SqgFallbackStrategy Bean"]

6.1 引擎隔离

业务层和 sqg 自动切面只能依赖 sqg 接口:

public interface SqgResilienceEngine {
    SqgEntry acquire(SqgResourceContext context);

    void complete(SqgEntry entry, SqgInvocationResult result);

    void updateRules(SqgRuleSnapshot rules);
}

第一版实现:

SentinelResilienceEngine

未来可扩展:

GoogleAdaptiveBreakerEngine
Resilience4jEngine
NoopResilienceEngine

这样可以避免 sqg 的注解、异常和配置结构与 Sentinel API 强耦合。

7. 对外 API 设计

7.1 注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SqgResource {
    String value();

    SqgEntryType entryType() default SqgEntryType.OUT;

    String fallbackMethod() default "";

    Class<? extends SqgFallbackStrategy> fallbackStrategy()
        default NoopSqgFallbackStrategy.class;

    Class<? extends Throwable>[] exceptionsToIgnore() default {};
}

使用示例:

@SqgResource(
    value = "mysql:user:query",
    fallbackMethod = "queryUserFallback",
    exceptionsToIgnore = EmptyResultDataAccessException.class
)
public User queryUser(long id) {
    return userRepository.queryById(id);
}

private User queryUserFallback(long id, Throwable cause) {
    return User.empty(id);
}

可复用策略示例:

@SqgResource(
    value = "http:user-center:query",
    fallbackStrategy = UserCenterFallbackStrategy.class
)
public UserProfile queryProfile(long userId) {
    return userCenterClient.query(userId);
}

7.2 fallback 接口

public interface SqgFallbackStrategy {
    Object fallback(SqgFallbackContext context) throws Throwable;
}

SqgFallbackContext 至少包含:

7.3 统一异常

业务层不直接接触 Sentinel BlockException,统一转换为:

SqgResourceUnavailableException

异常至少提供:

7.4 fallback 约束

8. 配置设计

8.1 全局模式

env:
  config:
    resilience:
      enabled: true
      mode: observe # off | observe | enforce
      max-resources: 2000

模式语义:

模式采集指标计算规则实际拒绝
off
observe是或影子计算
enforce

默认使用 observe

8.2 建议的初始默认配置

以下数值只是第一轮验证基线,不是未经压测即可直接全量执行的生产标准。

env:
  config:
    resilience:
      mode: observe
      max-resources: 2000

      defaults:
        circuit-breaker:
          enabled: true
          strategy: exception-ratio
          exception-ratio-threshold: 0.50
          minimum-request-amount: 20
          statistical-window: 10s
          open-duration: 10s
          slow-call-enabled: false

        flow:
          enabled: false

        system:
          enabled: true
          cpu-usage-threshold: 0.90

      resources:
        "http:user-center:query":
          circuit-breaker:
            strategy: slow-request-ratio
            slow-call-duration: 800ms
            slow-call-ratio-threshold: 0.60
            minimum-request-amount: 30
            open-duration: 15s

        "redis:default:read":
          circuit-breaker:
            exception-ratio-threshold: 0.70

        "web:/api/order/create":
          flow:
            enabled: true
            qps: 500

8.3 默认规则原则

9. 资源模型

9.1 资源粒度

默认采用:

依赖实例 + 操作分组

不能过粗,否则一个操作故障导致整个依赖全部熔断;也不能过细,否则资源数量失控。

9.2 建议资源名称

中间件建议名称EntryType
Spring MVCweb:{normalizedRoute}IN
RestTemplatehttp:{host}:{operation}OUT
Redisredis:{connectionFactory}:read/write/scriptOUT
MyBatismysql:{datasource}:query/updateOUT
JdbcTemplatejdbc:{datasource}:query/update/batchOUT
Dubbo Consumerdubbo:{interface}:{method}:consumerOUT
Dubbo Providerdubbo:{interface}:{method}:providerIN
Kafka Producerkafka:{cluster}:{topic}:sendOUT
Kafka Consumerkafka:{cluster}:{topic}:consumeIN
Rabbit Producerrabbit:{connection}:{exchange}:sendOUT
Rabbit Consumerrabbit:{connection}:{queue}:consumeIN
Elasticsearchelasticsearch:{cluster}:search/writeOUT
Graphgraph:{cluster}:query/writeOUT

9.3 高基数保护

资源名称中禁止包含:

超过 max-resources 后:

  1. 不再创建新资源。

  2. 降级到对应中间件的聚合资源。

  3. 输出限频告警。

  4. 记录资源超限指标。

10. 异常分类

统一扩展点:

public interface SqgFailureClassifier {
    boolean supports(SqgResourceContext context);

    SqgFailureDecision classify(
        SqgResourceContext context,
        Object result,
        Throwable error
    );
}

决策类型:

SUCCESS
FAILURE
IGNORED
SLOW_SUCCESS
SLOW_FAILURE

10.1 初始分类原则

场景建议分类
Redis nil / cache missSUCCESS
Redis 连接异常、读写超时FAILURE
MySQL empty resultIGNORED 或 SUCCESS
MySQL 连接异常、查询超时FAILURE
MySQL 唯一键冲突默认 IGNORED,允许覆盖
MySQL 死锁FAILURE,可由上层决定有限重试
HTTP 2xx/3xxSUCCESS
HTTP 4xx默认 IGNORED,429 可按依赖约定覆盖
HTTP 5xx、连接失败、超时FAILURE
调用方主动取消默认 IGNORED
Kafka/Rabbit broker 不可用FAILURE
MQ 业务反序列化失败默认 IGNORED 或业务资源失败
Sentinel/sqg 主动阻断不重复计为下游失败

异常分类应支持以下优先级:

注解 exceptionsToIgnore
    > 资源级配置
    > 中间件专用分类器
    > 全局默认分类器

11. 关键执行流程

11.1 同步调用

image.png

11.2 异步调用

异步方法不能在方法返回时立即结束 Entry,必须:

  1. 调用前申请异步 Entry。

  2. CompletionStage 注册完成回调。

  3. 在完成回调中分类成功、失败、取消和超时。

  4. finally 语义下关闭 Entry,且只能关闭一次。

  5. 处理 fallback 返回同步值或异步值的类型兼容问题。

Kafka/Rabbit 异步发送也应在 broker acknowledgement 或发送 future 完成时记录结果,而不是在调用 send 返回时记录成功。

11.3 AOP 与事务顺序

韧性切面应位于事务切面外层:

SqgResilienceAspect
    → TransactionAspect
        → Repository / MyBatis / JdbcTemplate
    → 事务提交或回滚完成
→ fallback

目标是保证数据库异常触发事务回滚后再进入 fallback,避免 fallback 运行在已经标记 rollback-only 的事务中。

同时需要明确:

12. 业务服务的自动接入范围

利用 sqg-env-config 已有拦截点,为接入框架的业务服务自动增加保护:

第一优先级

第二优先级

每个适配器必须确认:

13. 可观测性

13.1 指标

建议至少提供:

sqg_resilience_requests_total{resource,result}
sqg_resilience_blocked_total{resource,reason}
sqg_resilience_fallback_total{resource,result}
sqg_resilience_state_transition_total{resource,from,to}
sqg_resilience_request_duration_seconds{resource}
sqg_resilience_resources_current{type}
sqg_resilience_resource_overflow_total{type}
sqg_resilience_shadow_block_total{resource,reason}

生产指标需要控制 resource label 基数,并允许关闭明细资源指标、仅保留聚合指标。

13.2 日志

以下事件记录结构化日志:

不能逐请求打印限流日志,需要按资源和原因限频。

13.3 事件扩展点

public interface SqgResilienceEventListener {
    void onEvent(SqgResilienceEvent event);
}

第一版用于日志和指标,未来可用于告警、审计和 Dashboard 推送。

14. 规则管理

第一阶段规则来源:

内置默认值
    < application.yml
    < 资源级 YAML 覆盖

未来扩展:

SqgRuleSource SPI
    ├── YamlRuleSource
    ├── NacosRuleSource
    ├── ApolloRuleSource
    └── DashboardRuleSource

动态规则必须满足:

15. 手写实现的主要风险

15.1 算法正确性

15.2 误判风险

15.3 自适应降载风险

15.4 框架接入风险

15.5 运维风险

16. 实施阶段

阶段 0:基线整理

阶段 1:核心骨架与 observe

阶段 2:熔断与 fallback

阶段 3:入口与异步资源

阶段 4:动态治理

阶段 5:可选算法扩展

只有在生产数据证明 Sentinel 状态机恢复过于生硬时,再实现:

GoogleAdaptiveBreakerEngine

并仅针对显式配置的资源启用,不替换默认 Sentinel 引擎。

17. 测试与验收

17.1 单元测试

17.2 并发与异步测试

17.3 故障注入

17.4 验收条件

18. 当前决策

已形成的建议:

  1. 第一版采用 Sentinel Core,不采用完整 Spring Cloud Alibaba Starter。

  2. 对业务暴露 sqg 自有注解和 SPI,不暴露 @SentinelResource

  3. 默认 observe,显式切换 enforce 后才拒绝。

  4. 通过 sqg-env-config 自动覆盖业务服务中已受支持的中间件调用。

  5. 资源粒度采用“依赖实例 + 操作分组”。

  6. fallback 同时支持同类方法和策略 Bean,两者互斥。

  7. 基础设施自动保护默认快速失败,业务返回值降级放在外围 Facade。

  8. OUT 资源优先熔断,IN 资源用于系统保护和显式流控。

  9. QPS、并发和慢调用阈值不设置跨业务的强制生产默认值。

  10. 第一版不默认重试,不接 Dashboard/Nacos/集群限流。

  11. 抽象 SqgResilienceEngine,为未来 go-zero 风格算法保留扩展能力。

19. 待进一步确认

20. 参考资料与核心代码

go-zero

Sentinel

Resilience4j


Share this post:

Next Post
一次 Harness Shell 管道死锁 PR 的排查与 Review 实录