https://github.com/alibaba/Sentinel/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8
    在官方文档中,定义的Sentinel进行资源保护的几个步骤:

    1. 定义资源
    2. 定义规则
    3. 检验规则是否生效

      1. Entry entry = null;
      2. // 务必保证 finally 会被执行
      3. try {
      4. // 资源名可使用任意有业务语义的字符串 开启资源的保护
      5. entry = SphU.entry("自定义资源名");
      6. // 被保护的业务逻辑 method
      7. // do something...
      8. } catch (BlockException ex) {
      9. // 资源访问阻止,被限流或被降级 Sentinel定义异常 流控规则,降级规则,热点参数规则。。。。 服务降级(降级规则)
      10. // 进行相应的处理操作
      11. } catch (Exception ex) {
      12. // 若需要配置降级规则,需要通过这种方式记录业务异常 RuntimeException 服务降级 mock feign:fallback
      13. Tracer.traceEntry(ex, entry);
      14. } finally {
      15. // 务必保证 exit,务必保证每个 entry 与 exit 配对
      16. if (entry != null) {
      17. entry.exit();
      18. }

      Sentinel资源保护的方式
      API实现

    4. 引入依赖

      1. <dependency>
      2. <groupId>com.alibaba.csp</groupId>
      3. <artifactId>sentinel-core</artifactId>
      4. <version>1.8.0</version>
      5. </dependency>
    5. 编写测试逻辑

      1. @RestController
      2. @Slf4j
      3. public class HelloController {
      4. private static final String RESOURCE_NAME = "hello";
      5. @RequestMapping(value = "/hello")
      6. public String hello() {
      7. Entry entry = null;
      8. try {
      9. // 资源名可使用任意有业务语义的字符串,比如方法名、接口名或其它可唯一标识的字符串。
      10. entry = SphU.entry(RESOURCE_NAME);
      11. // 被保护的业务逻辑
      12. String str = "hello world";
      13. log.info("====="+str);
      14. return str;
      15. } catch (BlockException e1) {
      16. // 资源访问阻止,被限流或被降级
      17. //进行相应的处理操作
      18. log.info("block!");
      19. } catch (Exception ex) {
      20. // 若需要配置降级规则,需要通过这种方式记录业务异常
      21. Tracer.traceEntry(ex, entry);
      22. } finally {
      23. if (entry != null) {
      24. entry.exit();
      25. }
      26. }
      27. return null;
      28. }
      29. /**
      30. * 定义流控规则
      31. */
      32. @PostConstruct
      33. private static void initFlowRules(){
      34. List<FlowRule> rules = new ArrayList<>();
      35. FlowRule rule = new FlowRule();
      36. //设置受保护的资源
      37. rule.setResource(RESOURCE_NAME);
      38. // 设置流控规则 QPS
      39. rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
      40. // 设置受保护的资源阈值
      41. // Set limit QPS to 20.
      42. rule.setCount(1);
      43. rules.add(rule);
      44. // 加载配置好的规则
      45. FlowRuleManager.loadRules(rules);
      46. }
      47. }

      测试效果:

    • 业务侵入性很强,需要在controller中写入非业务代码.
    • 配置不灵活 若需要添加新的受保护资源 需要手动添加 init方法来添加流控规则

    @SentinelResource注解实现
    @SentinelResource 注解用来标识资源是否被限流、降级。
    blockHandler: 定义当资源内部发生了BlockException应该进入的方法(捕获的是Sentinel定义的异常)
    fallback: 定义的是资源内部发生了Throwable应该进入的方法
    exceptionsToIgnore:配置fallback可以忽略的异常
    源码入口:com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect
    1.引入依赖

    1. <dependency>
    2. <groupId>com.alibaba.csp</groupId>
    3. <artifactId>sentinel-annotation-aspectj</artifactId>
    4. <version>1.8.0</version>
    5. </dependency>

    2.配置切面支持

    1. @Configuration
    2. public class SentinelAspectConfiguration {
    3. @Bean
    4. public SentinelResourceAspect sentinelResourceAspect() {
    5. return new SentinelResourceAspect();
    6. }
    7. }

    3.UserController中编写测试逻辑,添加@SentinelResource,并配置blockHandler和fallback

    1. @RequestMapping(value = "/findOrderByUserId/{id}")
    2. @SentinelResource(value = "findOrderByUserId",
    3. fallback = "fallback",fallbackClass = ExceptionUtil.class,
    4. blockHandler = "handleException",blockHandlerClass = ExceptionUtil.class
    5. )
    6. public R findOrderByUserId(@PathVariable("id") Integer id) {
    7. //ribbon实现
    8. String url = "http://mall-order/order/findOrderByUserId/"+id;
    9. R result = restTemplate.getForObject(url,R.class);
    10. if(id==4){
    11. throw new IllegalArgumentException("非法参数异常");
    12. }
    13. return result;
    14. }

    4.编写ExceptionUtil,注意如果指定了class,方法必须是static方法

    1. public class ExceptionUtil {
    2. public static R fallback(Integer id,Throwable e){
    3. return R.error(-2,"===被异常降级啦===");
    4. }
    5. public static R handleException(Integer id, BlockException e){
    6. return R.error(-2,"===被限流啦===");
    7. }
    8. }

    5.流控规则设置可以通过Sentinel dashboard配置
    客户端需要引入 Transport 模块来与 Sentinel 控制台进行通信

    1. <dependency>
    2. <groupId>com.alibaba.csp</groupId>
    3. <artifactId>sentinel-transport-simple-http</artifactId>
    4. <version>1.8.0</version>
    5. </dependency>
    1. -Dcsp.sentinel.dashboard.server=consoleIp:port

    5. 启动 Sentinel 控制台
    下载控制台 jar 包并在本地启动:可以参见 此处文档
    https://github.com/alibaba/Sentinel/releases

    1. #启动控制台命令
    2. java -jar sentinel-dashboard-1.8.0.jar

    用户可以通过如下参数进行配置:
    -Dsentinel.dashboard.auth.username=sentinel 用于指定控制台的登录用户名为 sentinel;
    -Dsentinel.dashboard.auth.password=123456 用于指定控制台的登录密码为 123456;如果省略这两个参数,默认用户和密码均为 sentinel;
    -Dserver.servlet.session.timeout=7200 用于指定 Spring Boot 服务端 session 的过期时间,如 7200 表示 7200 秒;60m 表示 60 分钟,默认为 30 分钟;

    java -Dserver.port=8858 -Dsentinel.dashboard.auth.username=xushu -Dsentinel.dashboard.auth.password=123456 -jar sentinel-dashboard-1.8.0.jar
    为了方便快捷启动可以在桌面创建.bat文件

    1. java -Dserver.port=8858 -Dsentinel.dashboard.auth.username=xushu -Dsentinel.dashboard.auth.password=123456 -jar D:\server\sentinel-dashboard-1.8.0.jar
    2. pause

    访问http://localhost:8080/#/login ,默认用户名密码: sentinel/sentinel

    6、 Spring Cloud Alibaba整合Sentinel
    1.引入依赖

    1. <dependency>
    2. <groupId>com.alibaba.cloud</groupId>
    3. <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    4. </dependency>

    2.添加yml配置,为微服务设置sentinel控制台地址
    添加Sentinel后,需要暴露/actuator/sentinel端点,而Springboot默认是没有暴露该端点的,所以需要设置,测试http://localhost:8800/actuator/sentinel

    1. server:
    2. port: 8800
    3. spring:
    4. application:
    5. name: mall-user-sentinel-demo
    6. cloud:
    7. nacos:
    8. discovery:
    9. server-addr: 127.0.0.1:8848
    10. sentinel:
    11. transport:
    12. # 添加sentinel的控制台地址
    13. dashboard: 127.0.0.1:8080
    14. # 指定应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用的HttpServer
    15. # port: 8719

    3.在sentinel控制台中设置流控规则

    • 资源名: 接口的API
    • 针对来源: 默认是default,当多个微服务都调用这个资源时,可以配置微服务名来对指定的微服务设置阈值
    • 阈值类型: 分为QPS和线程数 假设阈值为10
    • QPS类型: 只得是每秒访问接口的次数>10就进行限流
    • 线程数: 为接受请求该资源分配的线程数>10就进行限流

    image.png
    测试: 因为QPS是1,所以1秒内多次访问会出现如下情形:
    image.png
    访问http://localhost:8800/actuator/sentinel, 可以查看flowRules
    image.png
    微服务和Sentinel Dashboard通信原理
    Sentinel控制台与微服务端之间,实现了一套服务发现机制,集成了Sentinel的微服务都会将元数据传递给Sentinel控制台,架构图如下所示:
    image.png
    流控针对privoder 熔断降级 针对consumer