• Web Servlet
  • Dubbo
  • Spring Cloud
  • Spring WebFlux
  • gRPC
  • Reactive 适配
    • Reactor
  • API Gateway 适配
    • Spring Cloud Gateway
  • Zuul 1.x
  • Apache RocketMQ

    注:适配模块仅提供相应适配功能,若希望接入 Sentinel 控制台,请务必参考 Sentinel 控制台文档。

    Web Servlet

    Sentinel 提供与 Servlet 的整合,可以对 Web 请求进行流量控制。使用时需引入以下模块(以 Maven 为例):

    1. <dependency>
    2. <groupId>com.alibaba.csp</groupId>
    3. <artifactId>sentinel-web-servlet</artifactId>
    4. <version>x.y.z</version>
    5. </dependency>

    您只需要在 Web 容器中的 web.xml 配置文件中进行如下配置即可开启 Sentinel 支持:

    1. <filter>
    2. <filter-name>SentinelCommonFilter</filter-name>
    3. <filter-class>com.alibaba.csp.sentinel.adapter.servlet.CommonFilter</filter-class>
    4. </filter>
    5.  
    6. <filter-mapping>
    7. <filter-name>SentinelCommonFilter</filter-name>
    8. <url-pattern>/*</url-pattern>
    9. </filter-mapping>

    若是 Spring 应用可以通过 Spring 进行配置,例如:

    1. @Configuration
    2. public class FilterConfig {

    3. @Bean
    4. public FilterRegistrationBean sentinelFilterRegistration() {
    5.     FilterRegistrationBean&lt;Filter&gt; registration = new FilterRegistrationBean&lt;&gt;();
    6.     registration.setFilter(new CommonFilter());
    7.     registration.addUrlPatterns(&#34;/*&#34;);
    8.     registration.setName(&#34;sentinelFilter&#34;);
    9.     registration.setOrder(1);
    10.     return registration;
    11. }
    12. }

    限流处理逻辑:默认情况下,当请求被限流时会返回默认的提示页面 Blocked by Sentinel (flow limiting)。您也可以通过 JVM 参数 -Dcsp.sentinel.web.servlet.block.page 或代码中调用 WebServletConfig.setBlockPage(blockPage) 方法设定自定义的跳转 URL,当请求被限流时会自动跳转至设定好的 URL。同样您也可以实现 UrlBlockHandler 接口并编写定制化的限流处理逻辑,然后将其注册至 WebCallbackManager 中。

    提示:1.7.0 版本开始默认的限流页面 HTTP 返回码是 429。您可以通过 csp.sentinel.web.servlet.block.status 配置项自定义限流页面的 HTTP 状态码。

    按来源限流:若希望对 HTTP 请求按照来源限流,则可以自己实现 RequestOriginParser 接口从 HTTP 请求中解析 origin 并注册至 WebCallbackManager 中。注意来源数目不能太多,若太多请自定义埋点作为参数传入并使用热点规则。

    注意:Sentinel Web Filter 会将每个到来的不同的 URL 都作为不同的资源处理,因此对于 REST 风格的 API,需要自行实现 UrlCleaner 接口清洗一下资源(比如将满足 /foo/:id 的 URL 都归到 /foo/ 资源下),然后将其注册至 WebCallbackManager 中。否则会导致资源数量过多,超出资源数量阈值(目前是 6000)时多出的资源的规则将 *不会生效

    从 1.6.3 版本开始,UrlCleaner 还可以来过滤掉不希望统计的 URL,只需要在 UrlCleaner 中将不希望统计的 URL 转换成空字符串("")即可。示例:

    1. WebCallbackManager.setUrlCleaner(new UrlCleaner() {
    2. @Override
    3. public String clean(String originUrl) {
    4. if (originUrl == null || originUrl.isEmpty()) {
    5. return originUrl;
    6. }
    7.  
    8. // 比如将满足 /foo/{id} 的 URL 都归到 /foo/*
    9. if (originUrl.startsWith("/foo/")) {
    10. return "/foo/*";
    11. }
    12. // 不希望统计 *.ico 的资源文件,可以将其转换为 empty string (since 1.6.3)
    13. if (originUrl.endsWith(".ico")) {
    14. return "";
    15. }
    16. return originUrl;
    17. }
    18. });

    如果您正在使用 Spring Boot / Spring Cloud,那么可以通过引入 Spring Cloud Alibaba Sentinel 来更方便地整合 Sentinel,详情请见 Spring Cloud Alibaba 文档。

    Dubbo

    Sentinel 提供 Dubbo 的相关适配 Sentinel Dubbo Adapter,主要包括针对 Service Provider 和 Service Consumer 实现的 Filter。相关模块:

    • sentinel-apache-dubbo-adapter(兼容 Apache Dubbo 2.7.x 及以上版本,自 Sentinel 1.5.1 开始支持)
    • sentinel-dubbo-adapter(兼容 Dubbo 2.6.x 版本) 对于 Apache Dubbo 2.7.x 及以上版本,使用时需引入以下模块(以 Maven 为例):
    1. <dependency>
    2. <groupId>com.alibaba.csp</groupId>
    3. <artifactId>sentinel-apache-dubbo-adapter</artifactId>
    4. <version>x.y.z</version>
    5. </dependency>

    对于 Dubbo 2.6.x 及以下版本,使用时需引入以下模块(以 Maven 为例):

    1. <dependency>
    2. <groupId>com.alibaba.csp</groupId>
    3. <artifactId>sentinel-dubbo-adapter</artifactId>
    4. <version>x.y.z</version>
    5. </dependency>

    引入此依赖后,Dubbo 的服务接口和方法(包括调用端和服务端)就会成为 Sentinel 中的资源,在配置了规则后就可以自动享受到 Sentinel 的防护能力。

    注:若希望接入 Dashboard,请参考 接入控制台的步骤。只引入 Sentinel Dubbo Adapter 无法接入控制台!

    若不希望开启 Sentinel Dubbo Adapter 中的某个 Filter,可以手动关闭对应的 Filter,比如:

    1. <!-- 关闭 Sentinel 对应的 Service Consumer Filter -->
    2. <dubbo:consumer filter="-sentinel.dubbo.consumer.filter"/>

    限流粒度可以是服务接口和服务方法两种粒度:

    • 服务接口:resourceName 为 接口全限定名,如 com.alibaba.csp.sentinel.demo.dubbo.FooService
    • 服务方法:resourceName 为 接口全限定名:方法签名,如 com.alibaba.csp.sentinel.demo.dubbo.FooService:sayHello(java.lang.String) Sentinel Dubbo Adapter 还支持配置全局的 fallback 函数,可以在 Dubbo 服务被限流/降级/负载保护的时候进行相应的 fallback 处理。用户只需要实现自定义的 DubboFallback 接口,并通过 DubboFallbackRegistry 注册即可。默认情况会直接将 BlockException 包装后抛出。同时,我们还可以配合 Dubbo 的 fallback 机制 来为降级的服务提供替代的实现。

    注:一般情况下熔断降级 / fallback 用于调用端(客户端)。

    我们提供了 Dubbo 的相关示例,请见 sentinel-demo-dubbo。

    有关 Sentinel 在 Dubbo 中的最佳实践,请参考 Sentinel: Dubbo 服务的流量哨兵。

    关于 Dubbo Filter 的更多信息,请参考 Dubbo Filter 文档。

    Spring Cloud

    Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。Sentinel 与 Spring Cloud 的整合见 Sentinel Spring Cloud Starter。

    Spring Cloud Alibaba 默认为 Sentinel 整合了 Servlet、RestTemplate、FeignClient 和 Spring WebFlux。Sentinel 在 Spring Cloud 生态中,不仅补全了 Hystrix 在 Servlet 和 RestTemplate 这一块的空白,而且还完全兼容了 Hystrix 在 FeignClient 中限流降级的用法,并且支持运行时灵活地配置和调整限流降级规则。

    Spring Cloud Alibaba Sentinel 的示例可以参考 sentinel-guide-spring-cloud

    Spring WebFlux

    注:从 1.5.0 版本开始支持,需要 Java 8 及以上版本。

    Sentinel 提供与 Spring WebFlux 的整合模块,从而 Reactive Web 应用也可以利用 Sentinel 的流控降级来保障稳定性。该整合模块基于 Sentinel Reactor Adapter 实现。

    使用时需引入以下模块(以 Maven 为例):

    1. <dependency>
    2. <groupId>com.alibaba.csp</groupId>
    3. <artifactId>sentinel-spring-webflux-adapter</artifactId>
    4. <version>x.y.z</version>
    5. </dependency>

    使用时只需注入对应的 SentinelWebFluxFilter 实例以及 SentinelBlockExceptionHandler 实例即可。比如:

    1. @Configuration
    2. public class WebFluxConfig {

    3. private final List&lt;ViewResolver&gt; viewResolvers;
    4. private final ServerCodecConfigurer serverCodecConfigurer;
    5. public WebFluxConfig(ObjectProvider&lt;List&lt;ViewResolver&gt;&gt; viewResolversProvider,
    6.                      ServerCodecConfigurer serverCodecConfigurer) {
    7.     this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
    8.     this.serverCodecConfigurer = serverCodecConfigurer;
    9. }
    10. @Bean
    11. @Order(-1)
    12. public SentinelBlockExceptionHandler sentinelBlockExceptionHandler() {
    13.     // Register the block exception handler for Spring WebFlux.
    14.     return new SentinelBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    15. }
    16. @Bean
    17. @Order(-1)
    18. public SentinelWebFluxFilter sentinelWebFluxFilter() {
    19.     // Register the Sentinel WebFlux filter.
    20.     return new SentinelWebFluxFilter();
    21. }
    22. }

    您可以在 WebFluxCallbackManager 注册回调进行定制:

    • setBlockHandler:注册函数用于实现自定义的逻辑处理被限流的请求,对应接口为 BlockRequestHandler。默认实现为 DefaultBlockRequestHandler,当被限流时会返回类似于下面的错误信息:Blocked by Sentinel: FlowException
    • setUrlCleaner:注册函数用于 Web 资源名的归一化。函数类型为 (ServerWebExchange, String) → String,对应含义为 (webExchange, originalUrl) → finalUrl
    • setRequestOriginParser:注册函数用于从请求中解析请求来源。函数类型为 ServerWebExchange → String。 相关示例:sentinel-demo-spring-webflux

    gRPC

    Sentinel 提供与 gRPC Java 的整合,以 gRPC ServerInterceptor 和 ClientInterceptor 的形式保护 gRPC 服务资源。使用时需引入以下模块(以 Maven 为例):

    1. <dependency>
    2. <groupId>com.alibaba.csp</groupId>
    3. <artifactId>sentinel-grpc-adapter</artifactId>
    4. <version>x.y.z</version>
    5. </dependency>

    在使用 Sentinel gRPC Adapter 时,只需要将对应的 Interceptor 注册至对应的客户端或服务端中。其中客户端的示例如下:

    1. public class ServiceClient {
    2.  
    3. private final ManagedChannel channel;
    4.  
    5. ServiceClient(String host, int port) {
    6. this.channel = ManagedChannelBuilder.forAddress(host, port)
    7. .intercept(new SentinelGrpcClientInterceptor()) // 在此处注册拦截器
    8. .build();
    9. // 在此处初始化客户端 stub 类
    10. }
    11. }

    服务端的示例如下:

    1. import io.grpc.Server;
    2.  
    3. Server server = ServerBuilder.forPort(port)
    4. .addService(new MyServiceImpl()) // 添加自己的服务实现
    5. .intercept(new SentinelGrpcServerInterceptor()) // 在此处注册拦截器
    6. .build();

    注意:由于 gRPC 拦截器中 ClientCall/ServerCall 以回调的形式进行请求响应信息的获取,每次 gRPC 服务调用计算出的 RT 可能会不准确。Sentinel gRPC Adapter 目前只支持 unary call。

    Reactive 适配

    Reactor

    注:从 1.5.0 版本开始支持,需要 Java 8 及以上版本。

    Sentinel 提供 Reactor 的适配,可以方便地在 reactive 应用中接入 Sentinel。使用时需引入以下模块(以 Maven 为例):

    1. <dependency>
    2. <groupId>com.alibaba.csp</groupId>
    3. <artifactId>sentinel-reactor-adapter</artifactId>
    4. <version>x.y.z</version>
    5. </dependency>

    Sentinel Reactor Adapter 分别针对 MonoFlux 实现了对应的 Sentinel Operator,从而在各种事件触发时汇入 Sentinel 的相关逻辑。同时 Sentinel 在上层提供了 SentinelReactorTransformer 用于在组装期装入对应的 operator,用户使用时只需要通过 transform 操作符来进行变换即可。接入示例:

    1. someService.doSomething() // return type: Mono<T> or Flux<T>
    2. .transform(new SentinelReactorTransformer<>(resourceName)) // 在此处进行变换
    3. .subscribe();

    API Gateway 适配

    Sentinel 支持对 Spring Cloud Gateway、Zuul 等主流的 API Gateway 进行限流。

    Spring Cloud Gateway

    从 1.6.0 版本开始,Sentinel 提供了 Spring Cloud Gateway 的适配模块,可以提供两种资源维度的限流:

    • route 维度:即在 Spring 配置文件中配置的路由条目,资源名为对应的 routeId
    • 自定义 API 维度:用户可以利用 Sentinel 提供的 API 来自定义一些 API 分组 使用时需引入以下模块(以 Maven 为例):
    1. <dependency>
    2. <groupId>com.alibaba.csp</groupId>
    3. <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
    4. <version>x.y.z</version>
    5. </dependency>

    使用时只需注入对应的 SentinelGatewayFilter 实例以及 SentinelGatewayBlockExceptionHandler 实例即可。比如:

    1. @Configuration
    2. public class GatewayConfiguration {

    3. private final List&lt;ViewResolver&gt; viewResolvers;
    4. private final ServerCodecConfigurer serverCodecConfigurer;
    5. public GatewayConfiguration(ObjectProvider&lt;List&lt;ViewResolver&gt;&gt; viewResolversProvider,
    6.                             ServerCodecConfigurer serverCodecConfigurer) {
    7.     this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
    8.     this.serverCodecConfigurer = serverCodecConfigurer;
    9. }
    10. @Bean
    11. @Order(Ordered.HIGHEST_PRECEDENCE)
    12. public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
    13.     // Register the block exception handler for Spring Cloud Gateway.
    14.     return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    15. }
    16. @Bean
    17. @Order(-1)
    18. public GlobalFilter sentinelGatewayFilter() {
    19.     return new SentinelGatewayFilter();
    20. }
    21. }

    Demo 示例:sentinel-demo-spring-cloud-gateway

    详细文档可以参考 网关限流 - Spring Cloud Gateway 文档。

    Zuul 1.x

    Sentinel 提供了 Zuul 1.x 的适配模块,可以为 Zuul Gateway 提供两种资源维度的限流:

    • route 维度:即在 Spring 配置文件中配置的路由条目,资源名为对应的 route ID(对应 RequestContext 中的 proxy 字段)
    • 自定义 API 维度:用户可以利用 Sentinel 提供的 API 来自定义一些 API 分组 使用时需引入以下模块(以 Maven 为例):
    1. <dependency>
    2. <groupId>com.alibaba.csp</groupId>
    3. <artifactId>sentinel-zuul-adapter</artifactId>
    4. <version>x.y.z</version>
    5. </dependency>

    详细文档可以参考 网关限流 - Zuul 1.x。

    如果您正在使用 Spring Cloud Zuul Starter,那么可以通过引入 spring-cloud-alibaba-sentinel-zuul 来更方便地整合 Sentinel。请参考 对应文档。

    Apache RocketMQ

    在 Apache RocketMQ 中,当消费者去消费消息的时候,无论是通过 pull 的方式还是 push 的方式,都可能会出现大批量的消息突刺。如果此时要处理所有消息,很可能会导致系统负载过高,影响稳定性。但其实可能后面几秒之内都没有消息投递,若直接把多余的消息丢掉则没有充分利用系统处理消息的能力。我们希望可以把消息突刺均摊到一段时间内,让系统负载保持在消息处理水位之下的同时尽可能地处理更多消息,从而起到“削峰填谷”的效果:

    削峰填谷

    上图中红色的部分代表超出消息处理能力的部分。我们可以看到消息突刺往往都是瞬时的、不规律的,其后一段时间系统往往都会有空闲资源。我们希望把红色的那部分消息平摊到后面空闲时去处理,这样既可以保证系统负载处在一个稳定的水位,又可以尽可能地处理更多消息。Sentinel 专门为这种场景提供了匀速器的特性,可以把突然到来的大量请求以匀速的形式均摊,以固定的间隔时间让请求通过,以稳定的速度逐步处理这些请求,起到“削峰填谷”的效果,从而避免流量突刺造成系统负载过高。同时堆积的请求将会排队,逐步进行处理;当请求排队预计超过最大超时时长的时候则直接拒绝,而不是拒绝全部请求。

    比如在 RocketMQ 的场景下配置了匀速模式下请求 QPS 为 5,则会每 200 ms 处理一条消息,多余的处理任务将排队;同时设置了超时时间为 5 s,预计排队时长超过 5 s 的处理任务将会直接被拒绝。示意图如下图所示:

    Uniform rate

    RocketMQ 用户可以根据不同的 group 和不同的 topic 分别设置限流规则,限流控制模式设置为匀速器模式(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER),比如:

    1. private void initFlowControlRule() {
    2. FlowRule rule = new FlowRule();
    3. rule.setResource(KEY); // 对应的 key 为 `groupName:topicName`
    4. rule.setCount(5);
    5. rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
    6. rule.setLimitApp("default");
    7.  
    8. // 匀速器模式下,设置了 QPS 为 5,则请求每 200 ms 允许通过 1 个
    9. rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER);
    10. // 如果更多的请求到达,这些请求会被置于虚拟的等待队列中。等待队列有一个 max timeout,如果请求预计的等待时间超过这个时间会直接被 block
    11. // 在这里,timeout 为 5s
    12. rule.setMaxQueueingTimeMs(5 * 1000);
    13. FlowRuleManager.loadRules(Collections.singletonList(rule));
    14. }

    结合 RocketMQ Client 使用 Sentinel 时,用户需要在处理消息时手动埋点。详情请见 Sentinel RocketMQ Demo。相关 Blog 见 Sentinel 为 RocketMQ 保驾护航。