【Spring Cloud Alibaba】Sentinel 流量控制
Sentinel是面向分布式服务架构的流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统自适应保护等多个维度来帮助您保障微服务的稳定性
SpringCloud Alibaba Sentinel流量控制方向
- 资源的调用关系,例如资源的调用链路,资源和资源之间的关系
- 运行指标,例如QPS、线程池、系统负载等
- 控制的效果,例如直接限流、冷启动、排队等
1 搭建SpringCloud Alibaba Sentinel控制台
Sentinel提供一个轻量级的开源控制台,它提供机器发现以及健康情况管理、监控(单机和集群),规则管理和推送的功能
获取并启动Sentinel Dashboard(控制台)
1.下载控制台Jar包: https://github.com/alibaba/Sentinel/releases
2. java -Dserver.port=7777 -Dcsp.sentinel.dashboard.server=localhost:7777 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.1.jar
3.从 Sentinel 1.6.0起,Sentinel Dashboard引入了基本的登录功能,默认的用
户名密码都是sentinel
2 项目集成
创建子模块,配置maven
<artifactId>e-commerce-sentinel-client</artifactId>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<!-- 模块名及描述信息 -->
<name>e-commerce-sentinel-client</name>
<description>Sentinel Client</description>
<dependencies>
<!-- 创建工程需要的两个依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- Sentinel 适配了 Feign, 可以实现服务间调用的保护 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- Sentinel 使用 Nacos 存储规则 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!-- web 工程 -->
<dependency>
<groupId>cn.flowboot.e.commerce</groupId>
<artifactId>e-commerce-common</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<!--
SpringBoot的Maven插件, 能够以Maven的方式为应用提供SpringBoot的支持,可以将
SpringBoot应用打包为可执行的jar或war文件, 然后以通常的方式运行SpringBoot应用
-->
<build>
<finalName>${artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
3 降级
SpringCloud Alibaba Sentinel对降级功能的支持
3.1 接口降级
3.1.2 硬编码限流
FlowRuleCodeController
package cn.flowboot.e.commerce.controller;
import cn.flowboot.e.commerce.block.handler.MyBlockHandler;
import cn.flowboot.e.commerce.vo.CommonResponse;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
/**
* <h1>流控规则硬编码</h1>
*
* @version 1.0
* @author: Vincent Vic
* @since: 2022/03/17
*/
@Slf4j
@RestController
@RequestMapping("/code")
public class FlowRuleCodeController {
/**
* 初始化流控规则
*/
@PostConstruct
public void init(){
//流控规则集合
List<FlowRule> flowRules = new ArrayList<>();
//创建流控规则
FlowRule flowRule = new FlowRule();
//设置流控规则QPS,限流阈值类型CQPS,并发线程数
flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
//流量控制手段
flowRule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
//设置受保护的资源
flowRule.setResource("flowRuleCode");
//设置受保护的资源的阈值
flowRule.setCount(1);
flowRules.add(flowRule);
//加载配置好的规则
FlowRuleManager.loadRules(flowRules);
}
/**
* <h1>采用硬编码的限流规则的Controller方法</h1>
* @return
*/
@GetMapping("/flow-rule")
//@SentinelResource(value = "flowRuleCode")
//@SentinelResource(value = "flowRuleCode",blockHandler = "handleException")
@SentinelResource(value = "flowRuleCode",blockHandler = "myHandleException",blockHandlerClass = MyBlockHandler.class)
public CommonResponse<String> flowRuleCode(){
log.info("request flowRuleCode");
return CommonResponse.success();
}
/**
* <h2>当限流异常抛出时,指定调用的方法</h2>
* 是一个兜底策略
*/
public CommonResponse handleException(BlockException e){
log.error("has block exception : [{}]", JSONObject.toJSONString(e.getRule()));
return CommonResponse.fail("flow rule exception",e.getClass().getCanonicalName());
}
}
上文flowRuleCode方法注解使用到通用限流处理MyBlockHandler ,可切换注释使用不同使用策略
package cn.flowboot.e.commerce.block.handler;
import cn.flowboot.e.commerce.vo.CommonResponse;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
/**
* <h1>自定义通用处理逻辑</h1>
*
* @version 1.0
* @author: Vincent Vic
* @since: 2022/03/17
*/
@Slf4j
public class MyBlockHandler {
/**
* <h2>通用限流处理方法</h2>
* 这个方法必须是static的
**/
public static CommonResponse<String> myHandleException(BlockException e){
log.error("has block exception : [{}], [{}]", JSONObject.toJSONString(e.getRule()),e.getRuleLimitApp());
return CommonResponse.fail("trigger flow rule exception",e.getClass().getCanonicalName());
}
}
3.1.2 控制面板限流
RateLimitController
package cn.flowboot.e.commerce.controller;
import cn.flowboot.e