介绍

分布式系统的流量防卫兵

  • Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。所以主要功能就是出入口流量控制

功能

流量控制

对于系统来说,任意时间到来的请求往往是随机不可控的,而系统的处理能力是有限的。我们需要根据系统的处理能力对流量进行控制

  • 角度
    • 资源的调用关系,例如资源的调用链路,资源和资源之间的关系
    • 运行指标,例如 QPS、线程池、系统负载等
    • 控制的效果,例如直接限流、冷启动、排队等

熔断降级

当检测到调用链路中某个资源出现不稳定的表现,例如请求响应时间长或异常比例升高的时候,则对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联故障。

  • 手段
    • 通过并发线程数进行限制 :当线程数在特定资源上堆积到一定的数量之后,对该资源的新请求就会被拒绝。堆积的线程完成任务后才开始继续接收请求。
    • 通过响应时间对资源进行降级:当依赖的资源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,直到过了指定的时间窗口之后才重新恢复。

系统负载保护

  • 系统自适应限流

配置环境

gradle依赖

  • 基于Spring cloud、AOP,使用注解
  • compile'com.alibaba.cloud:spring-cloud-starter-alibaba-sentinel:2.1.0.RELEASE'
  • compile group: 'com.alibaba.csp', name: 'sentinel-transport-simple-http', version: '1.6.3'

控制台

一个轻量级的开源控制台,它提供机器发现以及健康情况管理、监控(单机和集群),规则管理和推送的功能。

熔断降级使用

使用注解

Sentinel 提供了 @SentinelResource 注解用于定义资源,并提供了 AspectJ 的扩展用于自动定义资源、处理 BlockException等

  • 应用使用 Spring AOP,通过配置的方式将 SentinelResourceAspect 注册为一个 Spring Bean
  1. @Configuration
  2. public class SentinelAspectConfiguration {
  3. @Bean
  4. public SentinelResourceAspect sentinelResourceAspect() {
  5. return new SentinelResourceAspect();
  6. }
  7. }

@SentinelResource 用于定义资源,并提供可选的异常处理和 fallback 配置项 @SentinelResource 注解包含以下属性

  • value:资源名称,必需项(不能为空)
  • entryType:entry 类型,可选项EntryType.OUT/EntryType.IN(默认为 EntryType.OUT),对应入口控制/出口控制
  • blockHandler / blockHandlerClass: blockHandler 对应处理 BlockException 的函数名称。
  • fallback:fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理
    • 返回值类型必须与原函数返回值类型一致
    • fllback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
  • defaultFallback(since 1.6.0):默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。函数签名和fallback一致
  • exceptionsToIgnore(since 1.6.0):用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。
  • 示例
  1. // 对应的 `handleException` 函数需要位于 `ExceptionUtil` 类中,并且必须为 static 函数
  2. @Override
  3. @SentinelResource(value = "test", blockHandler = "handleException", blockHandlerClass = {
  4. ExceptionUtil.class})
  5. public void test() {
  6. log.info("Test");
  7. }
  8. @Override
  9. @SentinelResource(value = "sayHi",blockHandler = "exceptionHandler", fallback = "helloFallback")
  10. public String sayHi(long time) {
  11. if (time < 0) {
  12. throw new IllegalArgumentException("invalid arg");
  13. }
  14. try {
  15. Thread.sleep(time);
  16. } catch (InterruptedException e) {
  17. throw new IllegalArgumentException("inter arg");
  18. }
  19. return String.format("Hello time %d", time);
  20. }
  21. @Override
  22. @SentinelResource(value = "helloAnother", defaultFallback = "defaultFallback",
  23. exceptionsToIgnore = {IllegalStateException.class})
  24. public String helloAnother(String name) {
  25. if (name == null || "bad".equals(name)) {
  26. throw new IllegalArgumentException("oops");
  27. }
  28. if ("foo".equals(name)) {
  29. throw new IllegalStateException("oops");
  30. }
  31. return "Hello, " + name;
  32. }
  33. // Fallback 函数,函数签名与原函数一致或加一个 Throwable 类型的参数.
  34. public String helloFallback(long s, Throwable ex) {
  35. log.error("fallbackHandler:" + s);
  36. return "Oops fallbackHandler, error occurred at " + s;
  37. }
  38. public String defaultFallback() {
  39. log.info("Go to default fallback");
  40. return "default_fallback";
  41. }
  42. // Block 异常处理函数,参数最后多一个 BlockException,其余与原函数一致.
  43. public String exceptionHandler(long s, BlockException ex) {
  44. // Do some log here.
  45. return "Oops,exceptionHandler, error occurred at " + s;
  46. }

降级策略

  • 平均响应时间 (DEGRADE_GRADE_RT):当 1s 内持续进入 5 个请求,对应时刻的平均响应时间(秒级)均超过阈值(count,以 ms 为单位),那么在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地熔断(抛出 DegradeException)。注意 Sentinel 默认统计的 RT 上限是 4900 ms,超出此阈值的都会算作 4900 ms,若需要变更此上限可以通过启动配置项 -Dcsp.sentinel.statistic.max.rt=xxx 来配置。
  • 异常比例 (DEGRADE_GRADE_EXCEPTION_RATIO):当资源的每秒请求量 >= 5,并且每秒异常总数占通过量的比值超过阈值(DegradeRule 中的 count)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
  • 异常数 (DEGRADE_GRADE_EXCEPTION_COUNT):当资源近 1 分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若 timeWindow 小于 60s,则结束熔断状态后仍可能再进入熔断状态。
  • 可以直接接了Sentinel 控制台,在控制台上直接配置熔断降级规则。
    • 打开控制台界面,点击簇点链路,选择程序里的埋点,点击降级
    • 配置降级规则

sentinel_dashbord.jpg

  • 使用
    • 配置RT模式测试,控制台输入RT和窗口时间
      • url:ip:port/sayHi?t=delayTime, 当 1s 内持续进入 5 个请求 平均delayTime>RT 进入降级服务
    • 配置异常比例,控制台输入异常比例
      • url:ip:port/baz/bad, 当资源的每秒请求量 >= 5,并且每秒异常总数占通过量的比值设定的异常比例 将在接下来设置的窗口时间内进入降级服务