Spring Cloud Alibaba | Sentinel: 服务限流基础篇
Spring Cloud Alibaba | Sentinel: 服务限流基础篇
Springboot: 2.1.6.RELEASE
SpringCloud: Greenwich.SR1
如无特殊说明,本系列文章全采用以上版本
上一篇《Spring Cloud Alibaba | Sentinel: 分布式系统的流量防卫兵初探》我们介绍了Sentinel是什么,并且做了一个简单的Demo来验证服务限流。
这一篇,我们主要讲什么是服务限流,包括Sentinel支持的限流方式。
在讲服务限流之前,我们先了解什么是资源。
1. 简介
资源:可以是任何东西,服务,服务里的方法,甚至是一段代码。使用 Sentinel 来进行资源保护,主要分为几个步骤:
- 定义资源 
- 定义规则 
- 检验规则是否生效 
先把可能需要保护的资源定义好,之后再配置规则。也可以理解为,只要有了资源,我们就可以在任何时候灵活地定义各种流量控制规则。在编码的时候,只需要考虑这个代码是否需要保护,如果需要保护,就将之定义为一个资源。
2. 定义资源
2.1 主流框架的默认适配
为了减少开发的复杂程度,Sentinel对大部分的主流框架,例如 Web Servlet、Dubbo、Spring Cloud、gRPC、Spring WebFlux、Reactor 等都做了适配。
2.1.1 Web Servlet
Sentinel 提供与 Servlet 的整合,可以对 Web 请求进行流量控制。使用时需引入以下模块(以 Maven 为例):
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-web-servlet</artifactId>
    <version>x.y.z</version>
</dependency>
仅需要在 Web 容器中的 web.xml 配置文件中进行如下配置即可开启 Sentinel 支持:
<filter>
	<filter-name>SentinelCommonFilter</filter-name>
	<filter-class>com.alibaba.csp.sentinel.adapter.servlet.CommonFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>SentinelCommonFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>
若是 Spring 应用可以通过 Spring 进行配置,例如:
@Configuration
public class FilterConfig {
  @Bean
  public FilterRegistrationBean sentinelFilterRegistration() {
    FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
    registration.setFilter(new CommonFilter());
    registration.addUrlPatterns("/*");
    registration.setName("sentinelFilter");
    registration.setOrder(1);
    return registration;
  }
}
默认情况下,当请求被限流时会返回默认的提示页面。您也可以通过 WebServletConfig.setBlockPage(blockPage) 方法设定自定义的跳转 URL,当请求被限流时会自动跳转至设定好的 URL。同样也可以实现 UrlBlockHandler 接口并编写定制化的限流处理逻辑,然后将其注册至 WebCallbackManager 中。
注意: Sentinel Web Filter 会将每个到来的不同的 URL 都作为不同的资源处理,因此对于 REST 风格的 API,需要自行实现 UrlCleaner 接口清洗一下资源(比如将满足 /foo/:id 的 URL 都归到 /foo/* 资源下),然后将其注册至 WebCallbackManager 中。否则会导致资源数量过多,超出资源数量阈值(目前是 6000)时多出的资源的规则将 不会生效。
2.1.2 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 为例):
<dependency>
  <groupId>com.alibaba.csp</groupId>
  <artifactId>sentinel-apache-dubbo-adapter</artifactId>
  <version>x.y.z</version>
</dependency>
对于 Dubbo 2.6.x 及以下版本,使用时需引入以下模块(以 Maven 为例):
<dependency>
  <groupId>com.alibaba.csp</groupId>
  <artifactId>sentinel-dubbo-adapter</artifactId>
  <version>x.y.z</version>
</dependency>
引入此依赖后,Dubbo 的服务接口和方法(包括调用端和服务端)就会成为 Sentinel 中的资源,在配置了规则后就可以自动享受到 Sentinel 的防护能力。
若不希望开启 Sentinel Dubbo Adapter 中的某个 Filter,可以手动关闭对应的 Filter,比如:
<!-- 关闭 Sentinel 对应的 Service Consumer Filter -->
<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) 
2.1.3 Spring Cloud
引入依赖:
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
下面这个例子就是一个最简单的使用 Sentinel 的例子:
@SpringBootApplication
public class Application {
  public static void main(String[] args) {
    SpringApplication.run(ServiceApplication.class, args);
  }
}
@RestController
public class TestController {
  @GetMapping(value = "/hello")
  @SentinelResource("hello")
  public String hello() {
    return "Hello Sentinel";
  }
}
@SentinelResource 注解用来标识资源是否被限流、降级。上述例子上该注解的属性 'hello' 表示资源名。
@SentinelResource 用于定义资源,并提供可选的异常处理和 fallback 配置项。 @SentinelResource 注解包含以下属性:
- value:资源名称,必需项(不能为空)
- entryType:- entry类型,可选项(默认为- EntryType.OUT)
- blockHandler/- blockHandlerClass:- blockHandler对应处理- BlockException的函数名称,可选项。- blockHandler函数访问范围需要是- public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为- BlockException。- blockHandler函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定- blockHandlerClass为对应的类的- Class对象,注意对应的函数必需为- static函数,否则无法解析。
- fallback:- fallback函数名称,可选项,用于在抛出异常的时候提供- fallback处理逻辑。- fallback函数可以针对所有类型的异常(除了- exceptionsToIgnore里面排除掉的异常类型)进行处理。- fallback函数签名和位置要求:- 返回值类型必须与原函数返回值类型一致; 
- 方法参数列表需要和原函数一致,或者可以额外多一个 - Throwable类型的参数用于接收对应的异常;
- fallback函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定- fallbackClass为对应的类的- Class对象,注意对应的函数必需为- static函数,否则无法解析。
 
- defaultFallback(since 1.6.0):默认的- fallback函数名称,可选项,通常用于通用的- fallback逻辑(即可以用于很多服务或方法)。默认- fallback函数可以针对所有类型的异常(除了- exceptionsToIgnore里面排除掉的异常类型)进行处理。若同时配置了- fallback和- defaultFallback,则只有- fallback会生效。- defaultFallback函数签名要求:- 返回值类型必须与原函数返回值类型一致; 
- 方法参数列表需要为空,或者可以额外多一个 - Throwable类型的参数用于接收对应的异常。
- defaultFallback函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定- fallbackClass为对应的类的- Class对象,注意对应的函数必需为- static函数,否则无法解析。
 
- exceptionsToIgnore(since 1.6.0):用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。
特别地,若 blockHandler 和 fallback 都进行了配置,则被限流降级而抛出 BlockException 时只会进入 blockHandler 处理逻辑。若未配置 blockHandler、fallback 和 defaultFallback,则被限流降级时会将 BlockException 直接抛出。
示例:
public class TestService {
  // 对应的 `handleException` 函数需要位于 `ExceptionUtil` 类中,并且必须为 static 函数.
  @SentinelResource(value = "test", blockHandler = "handleException", blockHandlerClass = {ExceptionUtil.class})
  public void test() {
    System.out.println("Test");
  }
  // 原函数
  @SentinelResource(value = "hello", blockHandler = "exceptionHandler", fallback = "helloFallback")
  public String hello(long s) {
    return String.format("Hello at %d", s);
  }
  // Fallback 函数,函数签名与原函数一致或加一个 Throwable 类型的参数.
  public String helloFallback(long s) {
    return String.format("Halooooo %d", s);
  }
  // Block 异常处理函数,参数最后多一个 BlockException,其余与原函数一致.
  public String exceptionHandler(long s, BlockException ex) {
    // Do some log here.
    ex.printStackTrace();
    return "Oops, error occurred at " + s;
  }
}
从 1.4.0 版本开始,注解方式定义资源支持自动统计业务异常,无需手动调用 Tracer.trace(ex) 来记录业务异常。Sentinel 1.4.0 以前的版本需要自行调用 Tracer.trace(ex) 来记录业务异常。
AspectJ
如果应用直接使用了 AspectJ,那么需要在 aop.xml 文件中引入对应的 Aspect:
<aspects>
  <aspect name="com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect"/>
</aspects>
Spring AOP
如果应用使用了 Spring AOP,需要通过配置的方式将 SentinelResourceAspect 注册为一个 Spring Bean:
@Configuration
public class SentinelAspectConfiguration {
  @Bean
  public SentinelResourceAspect sentinelResourceAspect() {
      return new SentinelResourceAspect();
  }
}
2.1.4 Spring WebFlux
注:从 1.5.0 版本开始支持,需要 Java 8 及以上版本。
Sentinel 提供与 Spring WebFlux 的整合模块,从而 Reactive Web 应用也可以利用 Sentinel 的流控降级来保障稳定性。该整合模块基于 Sentinel Reactor Adapter 实现。
使用时需引入以下模块(以 Maven 为例):
<dependency>
  <groupId>com.alibaba.csp</groupId>
  <artifactId>sentinel-spring-webflux-adapter</artifactId>
  <version>x.y.z</version>
</dependency>
使用时只需注入对应的 SentinelWebFluxFilter 实例以及 SentinelBlockExceptionHandler 实例即可。比如:
@Configuration
public class WebFluxConfig {
  private final List<ViewResolver> viewResolvers;
  private final ServerCodecConfigurer serverCodecConfigurer;
  public WebFluxConfig(ObjectProvider<List<ViewResolver>> viewResolversProvider,
                        ServerCodecConfigurer serverCodecConfigurer) {
    this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
    this.serverCodecConfigurer = serverCodecConfigurer;
  }
  @Bean
  @Order(-1)
  public SentinelBlockExceptionHandler sentinelBlockExceptionHandler() {
    // Register the block exception handler for Spring WebFlux.
    return new SentinelBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
  }
  @Bean
  @Order(-1)
  public SentinelWebFluxFilter sentinelWebFluxFilter() {
    // Register the Sentinel WebFlux filter.
    return new SentinelWebFluxFilter();
  }
}
您可以在 WebFluxCallbackManager 注册回调进行定制:
- setBlockHandler:注册函数用于实现自定义的逻辑处理被限流的请求,对应接口为- BlockRequestHandler。默认实现为- DefaultBlockRequestHandler,当被限流时会返回类似于下面的错误信息:- Blocked by Sentinel: FlowException。
- setUrlCleaner:注册函数用于- Web资源名的归一化。函数类型为- (ServerWebExchange, String) → String,对应含义为- (webExchange, originalUrl) → finalUrl。
- setRequestOriginParser:注册函数用于从请求中解析请求来源。函数类型为- ServerWebExchange → String。
2.1.5 gRPC
Sentinel 提供与 gRPC Java 的整合,以 gRPC ServerInterceptor 和 ClientInterceptor 的形式保护 gRPC 服务资源。
使用时需引入以下模块(以 Maven 为例):
<dependency>
  <groupId>com.alibaba.csp</groupId>
  <artifactId>sentinel-grpc-adapter</artifactId>
  <version>x.y.z</version>
</dependency>
在使用 Sentinel gRPC Adapter 时,只需要将对应的 Interceptor 注册至对应的客户端或服务端中。其中客户端的示例如下:
public class ServiceClient {
  private final ManagedChannel channel;
  ServiceClient(String host, int port) {
    this.channel = ManagedChannelBuilder.forAddress(host, port)
        .intercept(new SentinelGrpcClientInterceptor()) // 在此处注册拦截器
        .build();
    // 在此处初始化客户端 stub 类
  }
}
服务端的示例如下:
import io.grpc.Server;
Server server = ServerBuilder.forPort(port)
     .addService(new MyServiceImpl()) // 添加自己的服务实现
     .intercept(new SentinelGrpcServerInterceptor()) // 在此处注册拦截器
     .build();
注意:由于 gRPC 拦截器中 ClientCall/ServerCall 以回调的形式进行请求响应信息的获取,每次 gRPC 服务调用计算出的 RT 可能会不准确。Sentinel gRPC Adapter 目前只支持 unary call。
2.1.6 Reactive
注:从 1.5.0 版本开始支持,需要 Java 8 及以上版本。
Sentinel 提供 Reactor 的适配,可以方便地在 reactive 应用中接入 Sentinel。
使用时需引入以下模块(以 Maven 为例):
<dependency>
  <groupId>com.alibaba.csp</groupId>
  <artifactId>sentinel-reactor-adapter</artifactId>
  <version>x.y.z</version>
</dependency>
Sentinel Reactor Adapter 分别针对 Mono 和 Flux 实现了对应的 Sentinel Operator,从而在各种事件触发时汇入 Sentinel 的相关逻辑。同时 Sentinel 在上层提供了 SentinelReactorTransformer 用于在组装期装入对应的 operator,用户使用时只需要通过 transform 操作符来进行变换即可。
接入示例:
someService.doSomething() // return type: Mono<T> or Flux<T>
   .transform(new SentinelReactorTransformer<>(resourceName)) // 在此处进行变换
   .subscribe();
2.1.7 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 为例):
<dependency>
  <groupId>com.alibaba.csp</groupId>
  <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
  <version>x.y.z</version>
</dependency>
使用时只需注入对应的 SentinelGatewayFilter 实例以及 SentinelGatewayBlockExceptionHandler 实例即可。比如:
@Configuration
public class GatewayConfiguration {
    private final List<ViewResolver> viewResolvers;
    private final ServerCodecConfigurer serverCodecConfigurer;
    public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,
                                ServerCodecConfigurer serverCodecConfigurer) {
        this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
        this.serverCodecConfigurer = serverCodecConfigurer;
    }
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
        // Register the block exception handler for Spring Cloud Gateway.
        return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    }
    @Bean
    @Order(-1)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }
}
因为Sentinel暂时只支持了Zuul1.x,具体用发这里暂不介绍。
2.1.8 Apache RocketMQ
在 Apache RocketMQ 中,当消费者去消费消息的时候,无论是通过 pull 的方式还是 push 的方式,都可能会出现大批量的消息突刺。如果此时要处理所有消息,很可能会导致系统负载过高,影响稳定性。但其实可能后面几秒之内都没有消息投递,若直接把多余的消息丢掉则没有充分利用系统处理消息的能力。我们希望可以把消息突刺均摊到一段时间内,让系统负载保持在消息处理水位之下的同时尽可能地处理更多消息,从而起到“削峰填谷”的效果:

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

RocketMQ 用户可以根据不同的 group 和不同的 topic 分别设置限流规则,限流控制模式设置为匀速器模式(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER),比如:
private void initFlowControlRule() {
    FlowRule rule = new FlowRule();
    rule.setResource(KEY); // 对应的 key 为 `groupName:topicName`
    rule.setCount(5);
    rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
    rule.setLimitApp("default");
    // 匀速器模式下,设置了 QPS 为 5,则请求每 200 ms 允许通过 1 个
    rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER);
    // 如果更多的请求到达,这些请求会被置于虚拟的等待队列中。等待队列有一个 max timeout,如果请求预计的等待时间超过这个时间会直接被 block
    // 在这里,timeout 为 5s
    rule.setMaxQueueingTimeMs(5 * 1000);
    FlowRuleManager.loadRules(Collections.singletonList(rule));
}
2.2 抛出异常的方式定义资源
SphU 包含了 try-catch 风格的 API。用这种方式,当资源发生了限流之后会抛出 BlockException。这个时候可以捕捉异常,进行限流之后的逻辑处理。示例代码如下:
// 1.5.0 版本开始可以利用 try-with-resources 特性
// 资源名可使用任意有业务语义的字符串,比如方法名、接口名或其它可唯一标识的字符串。
try (Entry entry = SphU.entry("resourceName")) {
  // 被保护的业务逻辑
  // do something here...
} catch (BlockException ex) {
  // 资源访问阻止,被限流或被降级
  // 在此处进行相应的处理操作
}
特别地 ,若 entry 的时候传入了热点参数,那么 exit 的时候也一定要带上对应的参数(exit(count, args)),否则可能会有统计错误。这个时候不能使用 try-with-resources 的方式。另外通过 Tracer.trace(ex) 来统计异常信息时,由于 try-with-resources 语法中 catch 调用顺序的问题,会导致无法正确统计异常数,因此统计异常信息时也不能在 try-with-resources 的 catch 块中调用 Tracer.trace(ex)。
1.5.0 之前的版本的示例:
Entry entry = null;
// 务必保证finally会被执行
try {
  // 资源名可使用任意有业务语义的字符串
  entry = SphU.entry("自定义资源名");
  // 被保护的业务逻辑
  // do something...
} catch (BlockException e1) {
  // 资源访问阻止,被限流或被降级
  // 进行相应的处理操作
} finally {
  if (entry != null) {
    entry.exit();
  }
}
注意 : SphU.entry(xxx) 需要与 entry.exit() 方法成对出现,匹配调用,否则会导致调用链记录异常,抛出 ErrorEntryFreeException 异常。
2.3 返回布尔值方式定义资源
SphO 提供 if-else 风格的 API。用这种方式,当资源发生了限流之后会返回 false,这个时候可以根据返回值,进行限流之后的逻辑处理。示例代码如下:
// 资源名可使用任意有业务语义的字符串
if (SphO.entry("自定义资源名")) {
  // 务必保证finally会被执行
  try {
    /**
    * 被保护的业务逻辑
    */
  } finally {
    SphO.exit();
  }
} else {
  // 资源访问阻止,被限流或被降级
  // 进行相应的处理操作
}
2.4 注解方式定义资源
Sentinel 支持通过 @SentinelResource 注解定义资源并配置 blockHandler 和 fallback 函数来进行限流之后的处理。示例:
// 原本的业务方法.
@SentinelResource(blockHandler = "blockHandlerForGetUser")
public User getUserById(String id) {
    throw new RuntimeException("getUserById command failed");
}
// blockHandler 函数,原方法调用被限流/降级/系统保护的时候调用
public User blockHandlerForGetUser(String id, BlockException ex) {
    return new User("admin");
}
注意 blockHandler 函数会在原方法被限流/降级/系统保护的时候调用,而 fallback 函数会针对所有类型的异常。请注意 blockHandler 和 fallback 函数的形式要求。
2.5 异步调用支持
Sentinel 支持异步调用链路的统计。在异步调用中,需要通过 SphU.asyncEntry(xxx) 方法定义资源,并通常需要在异步的回调函数中调用 exit 方法。以下是一个简单的示例:
try {
    AsyncEntry entry = SphU.asyncEntry(resourceName);
    // 异步调用.
    doAsync(userId, result -> {
        try {
            // 在此处处理异步调用的结果.
        } finally {
            // 在回调结束后 exit.
            entry.exit();
        }
    });
} catch (BlockException ex) {
    // Request blocked.
    // Handle the exception (e.g. retry or fallback).
}
SphU.asyncEntry(xxx) 不会影响当前(调用线程)的 Context,因此以下两个 entry 在调用链上是平级关系(处于同一层),而不是嵌套关系:
// 调用链类似于:
// -parent
// ---asyncResource
// ---syncResource
asyncEntry = SphU.asyncEntry(asyncResource);
entry = SphU.entry(normalResource);
若在异步回调中需要嵌套其它的资源调用(无论是 entry 还是 asyncEntry),只需要借助 Sentinel 提供的上下文切换功能,在对应的地方通过 ContextUtil.runOnContext(context, f) 进行 Context 变换,将对应资源调用处的 Context 切换为生成的异步 Context,即可维持正确的调用链路关系。示例如下:
public void handleResult(String result) {
    Entry entry = null;
    try {
        entry = SphU.entry("handleResultForAsync");
        // Handle your result here.
    } catch (BlockException ex) {
        // Blocked for the result handler.
    } finally {
        if (entry != null) {
            entry.exit();
        }
    }
}
public void someAsync() {
    try {
        AsyncEntry entry = SphU.asyncEntry(resourceName);
        // Asynchronous invocation.
        doAsync(userId, result -> {
            // 在异步回调中进行上下文变换,通过 AsyncEntry 的 getAsyncContext 方法获取异步 Context
            ContextUtil.runOnContext(entry.getAsyncContext(), () -> {
                try {
                    // 此处嵌套正常的资源调用.
                    handleResult(result);
                } finally {
                    entry.exit();
                }
            });
        });
    } catch (BlockException ex) {
        // Request blocked.
        // Handle the exception (e.g. retry or fallback).
    }
}
3. 规则的种类
Sentinel 的所有规则都可以在内存态中动态地查询及修改,修改之后立即生效。同时 Sentinel 也提供相关 API,供您来定制自己的规则策略。
Sentinel 支持以下几种规则:流量控制规则 、熔断降级规则 、系统保护规则 、来源访问控制规则 和 热点参数规则 。
3.1 流量控制规则 (FlowRule)
流量规则的定义
重要属性:
| Field | 说明 | 默认值 | 
|---|---|---|
| resource | 资源名,资源名是限流规则的作用对象 | |
| count | 限流阈值 | |
| grade | 限流阈值类型,QPS 或线程数模式 | QPS 模式 | 
| limitApp | 流控针对的调用来源 | default,代表不区分调用来源 | 
| strategy | 判断的根据是资源自身,还是根据其它关联资源 (refResource),还是根据链路入口 | 根据资源本身 | 
| controlBehavior | 流控效果(直接拒绝 / 排队等待 / 慢启动模式) | 直接拒绝 | 
同一个资源可以同时有多个限流规则。
通过代码定义流量控制规则
理解上面规则的定义之后,我们可以通过调用 FlowRuleManager.loadRules() 方法来用硬编码的方式定义流量控制规则,比如:
private void initFlowQpsRule() {
    List<FlowRule> rules = new ArrayList<>();
    FlowRule rule = new FlowRule(resourceName);
    // set limit qps to 20
    rule.setCount(20);
    rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
    rule.setLimitApp("default");
    rules.add(rule);
    FlowRuleManager.loadRules(rules);
}
3.2 熔断降级规则 (DegradeRule)
熔断降级规则包含下面几个重要的属性:
| Field | 说明 | 默认值 | 
|---|---|---|
| resource | 资源名,即限流规则的作用对象 | |
| count | 阈值 | |
| grade | 降级模式,根据 RT 降级还是根据异常比例降级 | |
| timeWindow | 降级的时间,单位为 s | 
同一个资源可以同时有多个降级规则。
理解上面规则的定义之后,我们可以通过调用 DegradeRuleManager.loadRules() 方法来用硬编码的方式定义流量控制规则。
private void initDegradeRule() {
    List<DegradeRule> rules = new ArrayList<>();
    DegradeRule rule = new DegradeRule();
    rule.setResource(KEY);
    // set threshold RT, 10 ms
    rule.setCount(10);
    rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
    rule.setTimeWindow(10);
    rules.add(rule);
    DegradeRuleManager.loadRules(rules);
}
3.3 系统保护规则 (SystemRule)
规则包含下面几个重要的属性:
| Field | 说明 | 默认值 | 
|---|---|---|
| highestSystemLoad | 最大的 load1,参考值 | -1 (不生效) | 
| avgRt | 所有入口流量的平均响应时间 | -1 (不生效) | 
| maxThread | 入口流量的最大并发数 | -1 (不生效) | 
| qps | 所有入口资源的 QPS | -1 (不生效) | 
理解上面规则的定义之后,我们可以通过调用 SystemRuleManager.loadRules() 方法来用硬编码的方式定义流量控制规则。
private void initSystemRule() {
    List<SystemRule> rules = new ArrayList<>();
    SystemRule rule = new SystemRule();
    rule.setHighestSystemLoad(10);
    rules.add(rule);
    SystemRuleManager.loadRules(rules);
}
3.4 访问控制规则 (AuthorityRule)
很多时候,我们需要根据调用方来限制资源是否通过,这时候可以使用 Sentinel 的访问控制(黑白名单)的功能。黑白名单根据资源的请求来源(origin)限制资源是否通过,若配置白名单则只有请求来源位于白名单内时才可通过;若配置黑名单则请求来源位于黑名单时不通过,其余的请求通过。
授权规则,即黑白名单规则(AuthorityRule)非常简单,主要有以下配置项:
- resource:资源名,即限流规则的作用对象 
- limitApp:对应的黑名单/白名单,不同 origin 用 , 分隔,如 appA,appB 
- strategy:限制模式,AUTHORITY_WHITE 为白名单模式,AUTHORITY_BLACK 为黑名单模式,默认为白名单模式 
这一篇先初步的介绍什么是资源,什么是规则,并且介绍了Sentinel对常见主流框架的适配,下一篇,我们详细来聊聊几种服务限流的方式。
参考:
https://github.com/alibaba/Sentinel
Spring Cloud Alibaba | Sentinel: 服务限流基础篇的更多相关文章
- Spring Cloud Alibaba | Sentinel: 服务限流高级篇
		目录 Spring Cloud Alibaba | Sentinel: 服务限流高级篇 1. 熔断降级 1.1 降级策略 2. 热点参数限流 2.1 项目依赖 2.2 热点参数规则 3. 系统自适应限 ... 
- Spring Cloud Alibaba微服务生态的基础实践
		目录 一.背景 二.初识Spring Cloud Alibaba 三.Nacos的基础实践 3.1 安装Nacos并启动服务 3.2 建立微服务并向Nacos注册服务 3.3 建立微服务消费者进行服务 ... 
- Spring Cloud Alibaba | Sentinel:分布式系统的流量防卫兵动态限流规则
		Spring Cloud Alibaba | Sentinel:分布式系统的流量防卫兵动态限流规则 前面几篇文章较为详细的介绍了Sentinel的使用姿势,还没看过的小伙伴可以访问以下链接查看: &l ... 
- 0.9.0.RELEASE版本的spring cloud alibaba sentinel限流、降级处理实例
		先看服务提供方的,我们在原来的sentinel实例(参见0.9.0.RELEASE版本的spring cloud alibaba sentinel实例)上加上限流.降级处理,三板斧只需在最后那一斧co ... 
- Spring Cloud Alibaba | Sentinel:分布式系统的流量防卫兵基础实战
		Spring Cloud Alibaba | Sentinel:分布式系统的流量防卫兵基础实战 Springboot: 2.1.8.RELEASE SpringCloud: Greenwich.SR2 ... 
- Spring Cloud Alibaba | Sentinel:分布式系统的流量防卫兵进阶实战
		Spring Cloud Alibaba | Sentinel:分布式系统的流量防卫兵进阶实战 在阅读本文前,建议先阅读<Spring Cloud Alibaba | Sentinel:分布式系 ... 
- Spring Cloud Alibaba | Sentinel: 分布式系统的流量防卫兵初探
		目录 Spring Cloud Alibaba | Sentinel: 分布式系统的流量防卫兵初探 1. Sentinel 是什么? 2. Sentinel 的特征: 3. Sentinel 的开源生 ... 
- Spring Cloud Alibaba Sentinel对Feign的支持
		Spring Cloud Alibaba Sentinel 除了对 RestTemplate 做了支持,同样对于 Feign 也做了支持,如果我们要从 Hystrix 切换到 Sentinel 是非常 ... 
- Spring Cloud Alibaba Sentinel对RestTemplate的支持
		Spring Cloud Alibaba Sentinel 支持对 RestTemplate 的服务调用使用 Sentinel 进行保护,在构造 RestTemplate bean的时候需要加上 @S ... 
随机推荐
- 基于X.509证书和SSL协议的身份认证过程实现(OpenSSL可以自己产生证书,有TCP通过SSL进行实际安全通讯的实际编程代码)good
			上周帮一个童鞋做一个数字认证的实验,要求是编程实现一个基于X.509证书认证的过程,唉!可怜我那点薄弱的计算机网络安全的知识啊!只得恶补一下了. 首先来看看什么是X.509.所谓X.509其实是一种非 ... 
- 求 1-2+3-4+5-6+7-8....M 的结果算法
			static void Main(string[] args) { /** * 算法题: * 求 1-2+3-4+5-6+7-8....M 的结果. * */ //存储运算结果. ; //记号. ; ... 
- LINQ学习笔记(一)
			LINQ,语言集成查询(Language Integrated Query)是一组用于C#和Visual Basic语言的扩展. 它允许编写C#或Visual Basic代码以查询数据库相同的方法操作 ... 
- postgresql Java JDBC 一次性传入多个参数到 in ( ?) -  multple/list parameters
			经常不清楚需要传入多少个参数到 IN () 里面,下面是简单方法: 方法 1 - in ( SELECT * FROM unnest(?)) ) Integer[] ids={1,2,3}; ... 
- 可视化文件消息收发一体化Socket实现V0.1
			http://blog.csdn.net/laoyang360/article/details/8681918 
- Qt for Android之Hello World
			Qt for Android (Hello World APK 创建)Qt是跨平台的,如桌面.移动.嵌入式平台.Qt for Android可以在Android v2.3.3 (API level 1 ... 
- Matlab与.Net混合编程-多维数组赋值出错的问题
			问题描述:Matlab可编译供.net调用的dll.两种不同环境对数据类型的定义相差较大,因此在C#中调用Matlab编译的函数时,首先要将C#中的变量类型转换成与Matlab对应的中转类型.Matl ... 
- myeclipse2018的下载安装教程
			首先注意事项!!!!!!! 在安装破解前是不可以打开软件的 jdk版本不能是10版本,1.8或1.9都可以 附上MyEclipse2018的百度云下载链接: 链接:https://pan.baidu. ... 
- Nio编程模型总结
			终于,这两天的考试熬过去了, 兴致冲冲的来整理笔记来, 这篇博客是我近几天的NIO印象笔记汇总,记录了对Selector及Selector的重要参数的理解,对Channel的理解,常见的Channel ... 
- Linux字体显示不同颜色
			功能介绍哦:让echo输出字符串显示不同颜色 一.字体颜色(范围:30-37) echo -e "\033[30m oldboy trainning \033[0m" 黑色字(黑色 ... 
