天天看點

Spring Cloud Alibaba 04:Sentinel 服務限流降級1、流控規則2、流控效果3、降級規則4、熱點規則5、授權規則6 自定義規則異常傳回

雪崩效應

解決方案

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

Spring Cloud Alibaba 04:Sentinel 服務限流降級1、流控規則2、流控效果3、降級規則4、熱點規則5、授權規則6 自定義規則異常傳回

1、流控規則

直接限流:直接對關聯的url資源限流

開啟sentinel,開啟provider服務

對/index資源做流控,設定QPS為1(表示一秒鐘隻允許通路一次)

Spring Cloud Alibaba 04:Sentinel 服務限流降級1、流控規則2、流控效果3、降級規則4、熱點規則5、授權規則6 自定義規則異常傳回

當通路一秒鐘通路http://localhost:8001/index超過一次時,會限制顯示被流控限制阻塞

Spring Cloud Alibaba 04:Sentinel 服務限流降級1、流控規則2、流控效果3、降級規則4、熱點規則5、授權規則6 自定義規則異常傳回
關聯限流:當被通路的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程式,設定流控規則如下:

Spring Cloud Alibaba 04:Sentinel 服務限流降級1、流控規則2、流控效果3、降級規則4、熱點規則5、授權規則6 自定義規則異常傳回

設定完流控規則後啟動測試程式,浏覽器通路http://localhost:8001/list則出現以下情況,表示對index通路超過門檻值,則關聯資源list限流

Spring Cloud Alibaba 04:Sentinel 服務限流降級1、流控規則2、流控效果3、降級規則4、熱點規則5、授權規則6 自定義規則異常傳回
鍊路限流:對更深層次資源限流(不僅僅局限于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不做限流,設定如下

Spring Cloud Alibaba 04:Sentinel 服務限流降級1、流控規則2、流控效果3、降級規則4、熱點規則5、授權規則6 自定義規則異常傳回

一秒鐘通路http://localhost:8081/test1超過一次時,會對service綁定資源限流

Spring Cloud Alibaba 04:Sentinel 服務限流降級1、流控規則2、流控效果3、降級規則4、熱點規則5、授權規則6 自定義規則異常傳回

通路http://localhost:8081/test2則不會

Spring Cloud Alibaba 04:Sentinel 服務限流降級1、流控規則2、流控效果3、降級規則4、熱點規則5、授權規則6 自定義規則異常傳回

2、流控效果

快速失敗

直接抛出異常

Warm UP

給系統一個預熱的時間,預熱時間段内單機門檻值較低,預熱時間過後單機門檻值增加,預熱時間内目前的單機門檻值是設定的門檻值的三分之一,預熱時間過後單機門檻值恢複設定的值。

Spring Cloud Alibaba 04:Sentinel 服務限流降級1、流控規則2、流控效果3、降級規則4、熱點規則5、授權規則6 自定義規則異常傳回
Spring Cloud Alibaba 04:Sentinel 服務限流降級1、流控規則2、流控效果3、降級規則4、熱點規則5、授權規則6 自定義規則異常傳回
排隊等待

當請求調用失敗之後,不會立即抛出異常,等待下一次調用,時間範圍是逾時時間,在時間範圍内如果請求則抛出異常。閥值類型必須設成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;
}
           

對參數num1進行限流

Spring Cloud Alibaba 04:Sentinel 服務限流降級1、流控規則2、流控效果3、降級規則4、熱點規則5、授權規則6 自定義規則異常傳回

效果:

Spring Cloud Alibaba 04:Sentinel 服務限流降級1、流控規則2、流控效果3、降級規則4、熱點規則5、授權規則6 自定義規則異常傳回
Spring Cloud Alibaba 04:Sentinel 服務限流降級1、流控規則2、流控效果3、降級規則4、熱點規則5、授權規則6 自定義規則異常傳回

可以添加例外值:當傳的對應參數值等于例外值的時候,讀取的門檻值為例外設定門檻值

Spring Cloud Alibaba 04:Sentinel 服務限流降級1、流控規則2、流控效果3、降級規則4、熱點規則5、授權規則6 自定義規則異常傳回

5、授權規則

給指定的資源設定流控應用(追加參數),可以對流控應用進行通路權限的設定,具體就是添加白名單和黑名單。

如何給請求指定流控應用,通過實作 RequestOriginParser 接口來完成,代碼如下所示。

package com.godfrey.configuration;

import com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;

/**
 * @author godfrey
 * @since 2020-12-26
 */
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.godfrey.configuration;

import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

/**
 * @author godfrey
 * @since 2020-12-26
 */
@Configuration
public class SentinelConfiguration {

    @PostConstruct
    public void init() {
        WebCallbackManager.setRequestOriginParser(new RequestOriginParserDefinition());
    }
}
           
Spring Cloud Alibaba 04:Sentinel 服務限流降級1、流控規則2、流控效果3、降級規則4、熱點規則5、授權規則6 自定義規則異常傳回
Spring Cloud Alibaba 04:Sentinel 服務限流降級1、流控規則2、流控效果3、降級規則4、熱點規則5、授權規則6 自定義規則異常傳回
Spring Cloud Alibaba 04:Sentinel 服務限流降級1、流控規則2、流控效果3、降級規則4、熱點規則5、授權規則6 自定義規則異常傳回

6 自定義規則異常傳回

建立異常處理類

package com.godfrey.execption;

import com.alibaba.csp.sentinel.adapter.servlet.callback.UrlBlockHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author godfrey
 * @since 2020-12-26
 */
public class ExceptionHandler implements UrlBlockHandler {
    @Override
    public void blocked(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws IOException {
        httpServletResponse.setContentType("text/html;charset=utf-8");
        String msg = null;
        if (e instanceof FlowException) {
            msg = "限流";
        } else if (e instanceof DegradeException) {
            msg = "降級";
        }
        httpServletResponse.getWriter().write(msg);
    }
}
           

進行配置。

@Configuration
public class SentinelConfiguration {

	@PostConstruct
    public void init2() {
        WebCallbackManager.setUrlBlockHandler(new ExceptionHandler());
    }
}
           

繼續閱讀