• Spring Cloud Alibaba 04:Sentinel 服务限流降级


    雪崩效应

    解决方案

    1、设置线程超时

    2、设置限流

    3、熔断器 Sentinel、Hystrix

    1、pom.xml 引入依赖

    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    

    2、application 配置

    # actuator暴露所有端点
    management:
      endpoints:
        web:
          exposure:
            include: '*'
    # 与Sentinel DashBoard交互地址
    spring:
      cloud:
        sentinel:
          transport:
            dashboard: localhost:8080
    

    3、下载 Sentinel 控制台:https://github.com/alibaba/Sentinel/releases,启动:java -jar sentinel-dashboard-1.8.0.jar 账号密码皆为sentinel,启动nacos,启动provider模块和consumer模块,访问http://localhost:9090/index

    1、流控规则

    直接限流:直接对关联的url资源限流

    开启sentinel,开启provider服务

    对/index资源做流控,设置QPS为1(表示一秒钟只允许访问一次)

    当访问一秒钟访问http://localhost:8001/index超过一次时,会限制显示被流控限制阻塞

    关联限流:当被访问的url资源超过设定的阈值,限流关联的资源

    controller新增list方法:

    @GetMapping("/list")
    public String list() {
        return "list";
    }
    

    添加测试依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    

    需要同时范文资源才能看到效果,测试类对http://localhost:8001/index访问

    @Test
    @DisplayName("测试关联流控模式")
    void test1() throws InterruptedException {
        RestTemplate restTemplate = new RestTemplate();
        for (int i = 0; i < 100; ++i) {
            restTemplate.getForObject("http://localhost:8081/index", String.class);
            System.out.println("provider==>/index=======>" + i);
            //休眠200毫秒
            TimeUnit.MILLISECONDS.sleep(200);
        }
    }
    

    启动provider程序,设置流控规则如下:

    设置完流控规则后启动测试程序,浏览器访问http://localhost:8001/list则出现以下情况,表示对index访问超过阈值,则关联资源list限流

    链路限流:对更深层次资源限流(不仅仅局限于controller)

    1、pom.xml 添加依赖

    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-web-servlet</artifactId>
    </dependency>
    

    2、application.yml

    spring:
    	cloud:
            sentinel:
              filter:
                enabled: false
    

    3、写配置类

    package com.godfrey.configuration;
    
    import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import javax.servlet.Filter;
    
    /**
     * @author godfrey
     * @since 2020-12-07
     */
    @Configuration
    public class FilterConfiguration {
    
        @Bean
        public FilterRegistrationBean<Filter> registrationBean() {
            FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>();
            registrationBean.setFilter(new CommonFilter());
            registrationBean.addUrlPatterns("/*");
            registrationBean.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "false");
            registrationBean.setName("sentinelFilter");
            return registrationBean;
        }
    }
    

    4、Service

    @Service
    public class ProviderService {
    
        @SentinelResource("test")  //test 保护资源名
        public void test() {
            System.out.println("test");
        }
    }
    

    5、Controller

    private final ProviderService providerService;
    
    @Autowired
    public ProviderController(ProviderService providerService) {
        this.providerService = providerService;
    }
    
    @GetMapping("/test1")
    public String test1() {
        this.providerService.test();
        return "test1";
    }
    
    @GetMapping("/test2")
    public String test2() {
        this.providerService.test();
        return "test2";
    }
    

    为了对比,test1做链路限流,对test2不做限流,设置如下

    一秒钟访问http://localhost:8081/test1超过一次时,会对service绑定资源限流

    访问http://localhost:8081/test2则不会

    2、流控效果

    快速失败

    直接抛出异常

    Warm UP

    给系统一个预热的时间,预热时间段内单机阈值较低,预热时间过后单机阈值增加,预热时间内当前的单机阈值是设置的阈值的三分之一,预热时间过后单机阈值恢复设置的值。

    排队等待

    当请求调用失败之后,不会立即抛出异常,等待下一次调用,时间范围是超时时间,在时间范围内如果请求则抛出异常。阀值类型必须设成QPS,否则无效

    3、降级规则

    RT

    单个请求的响应时间超过阈值,则进入准降级状态,接下来 1 S 内连续 5 个请求响应时间均超过阈值,就进行降级,持续时间为时间窗口的值。

    异常比例

    每秒异常数量占通过量的比例大于阈值,就进行降级处理,持续时间为时间窗口的值。

    异常数

    1 分钟内的异常数超过阈值就进行降级处理,时间窗口的值要大于 60S,否则刚结束熔断又进入下一次熔断了。

    4、热点规则

    热点规则是流控规则的更细粒度操作,可以具体到对某个热点参数的限流,设置限流之后,如果带着限流参数的请求量超过阈值,则进行限流,时间为统计窗口时长。

    必须要添加 @SentinelResource,即对资源进行流控。

    @GetMapping("/hot")
    @SentinelResource("hot")
    public String hot(
            @RequestParam(value = "num1",required = false) Integer num1,
            @RequestParam(value = "num2",required = false) Integer num2){
        return num1+"-"+num2;
    }
    

    5、授权规则

    给指定的资源设置流控应用(追加参数),可以对流控应用进行访问权限的设置,具体就是添加白名单和黑名单。

    如何给请求指定流控应用,通过实现 RequestOriginParser 接口来完成,代码如下所示。

    package com.southwind.configuration;
    
    import com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser;
    import org.springframework.util.StringUtils;
    
    import javax.servlet.http.HttpServletRequest;
    
    public class RequestOriginParserDefinition implements RequestOriginParser {
        @Override
        public String parseOrigin(HttpServletRequest httpServletRequest) {
            String name = httpServletRequest.getParameter("name");
            if(StringUtils.isEmpty(name)){
                throw new RuntimeException("name is null");
            }
            return name;
        }
    }
    

    要让 RequestOriginParserDefinition 生效,需要在配置类中进行配置。

    package com.southwind.configuration;
    
    import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager;
    import org.springframework.context.annotation.Configuration;
    
    import javax.annotation.PostConstruct;
    
    @Configuration
    public class SentinelConfiguration {
    
        @PostConstruct
        public void init(){
            WebCallbackManager.setRequestOriginParser(new RequestOriginParserDefinition());
        }
    }
    
  • 相关阅读:
    Spring Boot 2 快速教程:WebFlux Restful CRUD 实践(三)
    Spring Boot 2 快速教程:WebFlux 快速入门(二)
    ES 集群上,业务单点如何优化升级?
    Spring Boot 2.x 系列教程:WebFlux 系列教程大纲(一)
    泥瓦匠想做一个与众不同的技术"匠"
    java编程行业微信群,无论新手老手欢迎加入,会一直更新
    Spring Boot 2.x 系列教程:WebFlux REST API 全局异常处理 Error Handling
    解决方案:如何防止数据重复插入?
    阿里 Java 手册系列教程:为啥强制子类、父类变量名不同?
    品阿里 Java 开发手册有感
  • 原文地址:https://www.cnblogs.com/MessiXiaoMo3334/p/14097978.html
Copyright © 2020-2023  润新知