Sentinel:2.Sentinel的基本使用(二)降级规则、热点规则

ゝ一纸荒年。 2022-11-19 04:27 726阅读 0赞

文章目录

  • 1.在项目中使用Sentinel:降级规则
    • 1.1 在HelloServiceImpl中新增接口testDegradeRule(),添加注解@SentinelResource
    • 1.2 新建目录fallbackhandler,并创建熔断降级类FallbackHandler
    • 1.3 启动nacos-sample-provider,然后在Sentinel-Dashboard控制台中可以看到对应的菜单
    • 1.4 为接口testDegradeRule()添加一条降级规则
  • 2.在项目中使用Sentinel:热点规则
    • 2.1 在HelloServiceImpl中新增接口getJson()和getHtml(),添加注解@SentinelResource
    • 2.2 新建NacosSamplepProviderConstants.java,作为请求资源
    • 2.3 启动nacos-sample-provider,然后在Sentinel-Dashboard控制台中可以看到对应的菜单
    • 2.4 测试热点规则(基础设置):为接口getJson()添加一条热点规则
    • 2.5 测试热点规则(高级设置):为接口getHtml()添加一条热点规则
  • 3.小练习
      • 本文示例源码:

继续沿用上一篇中的项目:module:nacos-sample-provider,以它为例来演示Sentinel的降级规则和热点规则的使用。

1.在项目中使用Sentinel:降级规则

1.1 在HelloServiceImpl中新增接口testDegradeRule(),添加注解@SentinelResource

HelloServiceImpl.java

  1. package org.wy.provider;
  2. import com.alibaba.csp.sentinel.annotation.SentinelResource;
  3. import org.springframework.beans.factory.annotation.Value;
  4. import org.springframework.cloud.context.config.annotation.RefreshScope;
  5. import org.springframework.web.bind.annotation.GetMapping;
  6. import org.springframework.web.bind.annotation.RequestParam;
  7. import org.springframework.web.bind.annotation.RestController;
  8. import org.wy.provider.blockhandler.BlockHandler;
  9. import org.wy.provider.fallbackhandler.FallbackHandler;
  10. @RestController
  11. @RefreshScope
  12. public class HelloServiceImpl {
  13. // @Value可以从Nacos配置中心的配置文件中读取对应的配置变量值
  14. // ${}中的key要与配置文件中的key一致,否则无法读取
  15. @Value("${testValue}")
  16. private String testValue;
  17. // 记录访问次数
  18. private static int count = 0;
  19. @GetMapping(value = "/hi")
  20. // value 是资源名称,要确保与Sentinel服务中设置的一致且唯一,与Spring的AOP中的切点概念很相似
  21. // blockHandler 是处理BlockException的接口名称,接口默认需要和原方法在同一个类中
  22. // 如果希望使用其他类的函数,需要指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
  23. @SentinelResource(value = "sayHello", blockHandlerClass = BlockHandler.class, blockHandler = "blockHandlerForSayHello")
  24. public String sayHello(@RequestParam(name = "name") String name) {
  25. return "Hello World: " + name;
  26. }
  27. // 新增一个接口,用于验证"@Value的功能"
  28. @GetMapping(value = "/testValue")
  29. // value 是资源名称,要确保与Sentinel服务中设置的一致且唯一,与Spring的AOP中的切点概念很相似
  30. // blockHandler 是处理BlockException的接口名称,接口默认需要和原方法在同一个类中
  31. // 如果希望使用其他类的函数,需要指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
  32. @SentinelResource(value = "getValueFromNacosConfigServer", blockHandlerClass = BlockHandler.class, blockHandler = "blockHandlerForGetValueFromNacosConfigServer")
  33. public String getValueFromNacosConfigServer() {
  34. return "testValue is: " + testValue;
  35. }
  36. // 新增一个接口,用于验证降级规则
  37. @GetMapping(value = "/degrade")
  38. // value 是资源名称,要确保与Sentinel服务中设置的一致且唯一,与Spring的AOP中的切点概念很相似
  39. // fallback 是当前资源访问发生降级时的处理接口,接口默认需要和原方法在同一个类中
  40. // 如果希望使用其他类的函数,需要指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
  41. @SentinelResource(value = "testDegradeRule", fallbackClass = FallbackHandler.class, fallback = "fallbakcHandlerForTestDegradeRule")
  42. public String testDegradeRule() {
  43. // 保证count为奇数时异常,偶数时不异常
  44. if ((count++ & 1) == 1) {
  45. throw new RuntimeException("人为制造异常");
  46. } else {
  47. return "降级测试:不发生异常";
  48. }
  49. }
  50. }

1.2 新建目录fallbackhandler,并创建熔断降级类FallbackHandler

FallbackHandler.java

  1. package org.wy.provider.fallbackhandler;
  2. import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
  3. import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
  4. import java.util.logging.Logger;
  5. /** * 定义熔断降级的处理类 * 注意,返回类型和参数要与调用者一致,且都需要添加异常类,并且方法的修饰符必须是public static * 并且可以额外选填一个 Throwable 类型的参数用于接收对应的异常 */
  6. public class FallbackHandler {
  7. private static Logger logger = Logger.getLogger(FallbackHandler.class.toString());
  8. /** * 当testDegradeRule接口访问被降级时,就会调用该接口 * 该函数的传参和返回值类型必须与资源点的传参一样,并且可以额外选填一个 Throwable 类型的参数用于接收对应的异常 * * @param throwable * @return */
  9. public static String fallbakcHandlerForTestDegradeRule(Throwable throwable) {
  10. if (throwable instanceof RuntimeException) {
  11. logger.warning("接口[/degrade]访问失败,原因是:" + throwable.getMessage());
  12. return "接口[/degrade]访问失败,原因是:" + throwable.getMessage();
  13. } else if (throwable instanceof DegradeException) {
  14. DegradeException e = (DegradeException) throwable;
  15. DegradeRule rule = e.getRule();
  16. int time = rule.getTimeWindow();
  17. logger.warning("接口[/degrade]访问被降级,预计[" + time + "]秒内无法访问");
  18. return "接口[/degrade]访问被降级,预计[" + time + "]秒内无法访问";
  19. } else {
  20. return "";
  21. }
  22. }
  23. }

1.3 启动nacos-sample-provider,然后在Sentinel-Dashboard控制台中可以看到对应的菜单

image

【注意】

  1. 启动nacos-sample-provider服务后,需要先访问一下@SentinelResource注册的资源,才能将对应的资源注册到Sentinel,从而对该资源的访问添加各种规则

1.4 为接口testDegradeRule()添加一条降级规则

image

为了方便演示,设置一条“异常数为5”的降级规则, 然后快速点击刷新,即可触发熔断,如下图:

image

2.在项目中使用Sentinel:热点规则

2.1 在HelloServiceImpl中新增接口getJson()和getHtml(),添加注解@SentinelResource

HelloServiceImpl.java

  1. package org.wy.provider;
  2. import com.alibaba.csp.sentinel.annotation.SentinelResource;
  3. import org.springframework.beans.factory.annotation.Value;
  4. import org.springframework.cloud.context.config.annotation.RefreshScope;
  5. import org.springframework.web.bind.annotation.GetMapping;
  6. import org.springframework.web.bind.annotation.PathVariable;
  7. import org.springframework.web.bind.annotation.RequestParam;
  8. import org.springframework.web.bind.annotation.RestController;
  9. import org.wy.provider.blockhandler.BlockHandler;
  10. import org.wy.provider.fallbackhandler.FallbackHandler;
  11. @RestController
  12. @RefreshScope
  13. public class HelloServiceImpl {
  14. // @Value可以从Nacos配置中心的配置文件中读取对应的配置变量值
  15. // ${}中的key要与配置文件中的key一致,否则无法读取
  16. @Value("${testValue}")
  17. private String testValue;
  18. // 记录访问次数
  19. private static int count = 0;
  20. @GetMapping(value = "/hi")
  21. // value 是资源名称,要确保与Sentinel服务中设置的一致且唯一,与Spring的AOP中的切点概念很相似
  22. // blockHandler 是处理BlockException的接口名称,接口默认需要和原方法在同一个类中
  23. // 如果希望使用其他类的函数,需要指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
  24. @SentinelResource(value = "sayHello", blockHandlerClass = BlockHandler.class, blockHandler = "blockHandlerForSayHello")
  25. public String sayHello(@RequestParam(name = "name") String name) {
  26. return "Hello World: " + name;
  27. }
  28. // 新增一个接口,用于验证"@Value的功能"
  29. @GetMapping(value = "/testValue")
  30. // value 是资源名称,要确保与Sentinel服务中设置的一致且唯一,与Spring的AOP中的切点概念很相似
  31. // blockHandler 是处理BlockException的接口名称,接口默认需要和原方法在同一个类中
  32. // 如果希望使用其他类的函数,需要指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
  33. @SentinelResource(value = "getValueFromNacosConfigServer", blockHandlerClass = BlockHandler.class, blockHandler = "blockHandlerForGetValueFromNacosConfigServer")
  34. public String getValueFromNacosConfigServer() {
  35. return "testValue is: " + testValue;
  36. }
  37. // 新增一个接口,用于验证降级规则
  38. @GetMapping(value = "/degrade")
  39. // value 是资源名称,要确保与Sentinel服务中设置的一致且唯一,与Spring的AOP中的切点概念很相似
  40. // fallback 是当前资源访问发生降级时的处理接口,接口默认需要和原方法在同一个类中
  41. // 如果希望使用其他类的函数,需要指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
  42. @SentinelResource(value = "testDegradeRule", fallbackClass = FallbackHandler.class, fallback = "fallbakcHandlerForTestDegradeRule")
  43. public String testDegradeRule() {
  44. // 保证count为奇数时异常,偶数时不异常
  45. if ((count++ & 1) == 1) {
  46. throw new RuntimeException("人为制造异常");
  47. } else {
  48. return "降级测试:不发生异常";
  49. }
  50. }
  51. // 新增一个接口,用于验证热点规则:基础设置
  52. @GetMapping(value = "/json")
  53. // value 是资源名称,要确保与Sentinel服务中设置的一致且唯一,与Spring的AOP中的切点概念很相似
  54. @SentinelResource(value = "getJson")
  55. // 这里就不要使用@RequestParam了,否则不管是否在url中填写,入参会一直是被访问状态,这样无法测试热点规则
  56. public String getJson(Boolean json1, Boolean json2) {
  57. if (json1 != null && json1) {
  58. return NacosSamplepProviderConstants.json1;
  59. }
  60. if (json2 != null && json2) {
  61. return NacosSamplepProviderConstants.json2;
  62. }
  63. return NacosSamplepProviderConstants.json3;
  64. }
  65. // 新增一个接口,用于验证热点规则:高级设置
  66. @GetMapping(value = "/html/{id}")
  67. // value 是资源名称,要确保与Sentinel服务中设置的一致且唯一,与Spring的AOP中的切点概念很相似
  68. @SentinelResource(value = "getHtml")
  69. // 这里就不要使用@RequestParam了,否则不管是否在url中填写,入参会一直是被访问状态,这样无法测试热点规则
  70. public String getHtml(@PathVariable int id) {
  71. if (id <= 0 || id > 3) {
  72. return NacosSamplepProviderConstants.errorHtml;
  73. }
  74. return NacosSamplepProviderConstants.html[id - 1];
  75. }
  76. }

2.2 新建NacosSamplepProviderConstants.java,作为请求资源

NacosSamplepProviderConstants.java

  1. package org.wy.provider;
  2. public class NacosSamplepProviderConstants {
  3. public static String json1 = "{\"name\":\"god\",\"age\":\"25\"}";
  4. public static String json2 = "{\"name\":\"godness\",\"age\":\"18\"}";
  5. public static String json3 = "{\"name\":\"me\",\"age\":\"3\"}";
  6. public static String[] html = {
  7. "<html>\n" + "\n" + "<head>\n" + "<title>测试热点规则</title>\n" + "</head>\n" + "\n" + "<body>\n" + "<p> 第1个 HTML 页面 </p>\n" + "</body>\n" + "\n" + "</html>",
  8. "<html>\n" + "\n" + "<head>\n" + "<title>测试热点规则</title>\n" + "</head>\n" + "\n" + "<body>\n" + "<p> 第2个 HTML 页面 </p>\n" + "</body>\n" + "\n" + "</html>",
  9. "<html>\n" + "\n" + "<head>\n" + "<title>测试热点规则</title>\n" + "</head>\n" + "\n" + "<body>\n" + "<p> 第3个 HTML 页面 </p>\n" + "</body>\n" + "\n" + "</html>"
  10. };
  11. public static String errorHtml = "<html>\n" + "\n" + "<head>\n" + "<title>测试热点规则</title>\n" + "</head>\n" + "\n" + "<body>\n" + "<p> 404!!! </p>\n" + "</body>\n" + "\n" + "</html>";
  12. }

2.3 启动nacos-sample-provider,然后在Sentinel-Dashboard控制台中可以看到对应的菜单

image

【注意】

  1. 启动nacos-sample-provider服务后,需要先访问一下@SentinelResource注册的资源,才能将对应的资源注册到Sentinel,从而对该资源的访问添加各种规则

2.4 测试热点规则(基础设置):为接口getJson()添加一条热点规则

image

  1. 参数索引:0对应第一个参数,1对应第二个参数,以此类推;
  2. 参数索引:从0开始,到该值为止的区间内的参数被访问时,会受该条规则限制。

image

image

image

2.5 测试热点规则(高级设置):为接口getHtml()添加一条热点规则

image

  1. 高级设置:需要先添加一个基础的热点规则,对资源名下的所有资源有一个统一的限制;
  2. 高级设置:然后在高级设置中,单独对某个或多个资源再做具体的限制(高级设置中的阈值可以比基础设置中的大)。

image

image

image

3.小练习

读者可以在热点规则(高级设置)中,尝试一下总规则阈值小于特例阈值的效果,如下图:

image


本文示例源码:

GitHub:WangYe8613/scanacos

降级规则:
[commit id:c058d158bfe212d8ae37411dcc436d66bfb87620]

热点规则:
[commit id:3819be0c09c16c4e1b73f97c3e4dce3b44e19fd9]

发表评论

表情:
评论列表 (有 0 条评论,726人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Sentinel热点规则

    [完整目录清单页面(必看)][Link 1] 何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:

    相关 Sentinel熔断降级规则

    [完整目录清单页面(必看)][Link 1] 概述 除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。一个服务常常会调用别的模块,