第一步:创建maven项目,添加依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>sentinel_demo</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--sentinel核心库-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.8.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.18</version>
</dependency>
<!--如果要使用@SentinelResource-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>1.8.0</version>
</dependency>
</dependencies>
</project>
第二步:添加application.yml
server:
port: 8020
第三步:添加启动类
package com.example.sentinel;
import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class SentinelDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SentinelDemoApplication.class,args);
}
// 注解支持的配置Bean
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
}
第四步:添加控制类
package com.example.sentinel.controller;
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.Tracer;
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.example.sentinel.pojo.User;
import lombok.extern.slf4j.Slf4j;
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;
@RestController
@Slf4j
public class HelloController {
private static final String RESOURCE_NAME = "hello";
private static final String USER_RESOURCE_NAME = "user";
@RequestMapping(value = "/hello")
public String hello() {
Entry entry = null;
try {
// 1.sentinel针对资源进行限制的
entry = SphU.entry(RESOURCE_NAME);
// 被保护的业务逻辑
String str = "hello world";
log.info("====="+str+"=====");
return str;
} catch (BlockException e1) {
// 资源访问阻止,被限流或被降级
//进行相应的处理操作
log.info("block!");
return "被流控了!";
} catch (Exception ex) {
// 若需要配置降级规则,需要通过这种方式记录业务异常
Tracer.traceEntry(ex, entry);
} finally {
if (entry != null) {
entry.exit();
}
}
return null;
}
/**
* 定义规则
*
* spring 的初始化方法
*/
@PostConstruct //相当于init-method
private static void initFlowRules(){
// 流控规则
List<FlowRule> rules = new ArrayList<>();
// 流控
FlowRule rule = new FlowRule();
// 为哪个资源进行流控
rule.setResource(RESOURCE_NAME);
// 设置流控规则 QPS表示每秒请求的次数
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
// 设置受保护的资源阈值
rule.setCount(1);
rules.add(rule);
// 通过@SentinelResource来定义资源并配置降级和流控的处理方法
FlowRule rule2 = new FlowRule();
//设置受保护的资源
rule2.setResource(USER_RESOURCE_NAME);
// 设置流控规则 QPS表示每秒请求的次数
rule2.setGrade(RuleConstant.FLOW_GRADE_QPS);
// 设置受保护的资源阈值
rule2.setCount(1);
rules.add(rule2);
// 加载配置好的规则
FlowRuleManager.loadRules(rules);
}
/**
* @SentinelResource 改善接口中资源定义和被流控降级后的处理方法
* 怎么使用: 1.添加依赖<artifactId>sentinel-annotation-aspectj</artifactId>
* 2.配置bean——SentinelResourceAspect
* value 定义资源
* blockHandler 设置 流控降级后的处理方法(默认该方法必须声明在同一个类)
* 如果不想在同一个类中 blockHandlerClass 但是方法必须是static
* fallback 当接口出现了异常,就可以交给fallback指定的方法进行处理
* 如果不想在同一个类中 fallbackClass 但是方法必须是static
*
* blockHandler 如果和fallback同时指定了,则blockHandler优先级更高
* exceptionsToIgnore 排除哪些异常不处理
* @param id
* @return
*/
@RequestMapping("/user")
@SentinelResource(value = USER_RESOURCE_NAME, /*fallback = "fallbackHandleForGetUser",*/
/*exceptionsToIgnore = {ArithmeticException.class},*/
/*blockHandlerClass = User.class,*/ blockHandler = "blockHandlerForGetUser")
public User getUser(String id) {
return new User("xushu");
}
/**
* 注意:
* 1. 一定要public
* 2. 返回值一定要和源方法保证一致, 包含源方法的参数。
* 3. 可以在参数最后添加BlockException 可以区分是什么规则的处理方法
* @param id
* @param ex
* @return
*/
public User blockHandlerForGetUser(String id, BlockException ex) {
ex.printStackTrace();
return new User("流控!!");
}
}
第五步:启动测试
在一秒里访问两次:http://localhost:8020/userfallback
package com.example.sentinel.controller;
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.Tracer;
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.example.sentinel.pojo.User;
import lombok.extern.slf4j.Slf4j;
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;
@RestController
@Slf4j
public class HelloController {
private static final String RESOURCE_NAME = "hello";
private static final String USER_RESOURCE_NAME = "user";
private static final String DEGRADE_RESOURCE_NAME = "degrade";
@RequestMapping(value = "/hello")
public String hello() {
Entry entry = null;
try {
// 1.sentinel针对资源进行限制的
entry = SphU.entry(RESOURCE_NAME);
// 被保护的业务逻辑
String str = "hello world";
log.info("====="+str+"=====");
return str;
} catch (BlockException e1) {
// 资源访问阻止,被限流或被降级
//进行相应的处理操作
log.info("block!");
return "被流控了!";
} catch (Exception ex) {
// 若需要配置降级规则,需要通过这种方式记录业务异常
Tracer.traceEntry(ex, entry);
} finally {
if (entry != null) {
entry.exit();
}
}
return null;
}
/**
* 定义规则
*
* spring 的初始化方法
*/
@PostConstruct //相当于init-method
private static void initFlowRules(){
// 流控规则
List<FlowRule> rules = new ArrayList<>();
// 流控
FlowRule rule = new FlowRule();
// 为哪个资源进行流控
rule.setResource(RESOURCE_NAME);
// 设置流控规则 QPS表示每秒请求的次数
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
// 设置受保护的资源阈值
rule.setCount(1);
rules.add(rule);
// 通过@SentinelResource来定义资源并配置降级和流控的处理方法
FlowRule rule2 = new FlowRule();
//设置受保护的资源
rule2.setResource(USER_RESOURCE_NAME);
// 设置流控规则 QPS表示每秒请求的次数
rule2.setGrade(RuleConstant.FLOW_GRADE_QPS);
// 设置受保护的资源阈值
rule2.setCount(1);
rules.add(rule2);
// 加载配置好的规则
FlowRuleManager.loadRules(rules);
}
/**
* @SentinelResource 改善接口中资源定义和被流控降级后的处理方法
* 怎么使用: 1.添加依赖<artifactId>sentinel-annotation-aspectj</artifactId>
* 2.配置bean——SentinelResourceAspect
* value 定义资源
* blockHandler 设置 流控降级后的处理方法(默认该方法必须声明在同一个类)
* 如果不想在同一个类中 blockHandlerClass 但是方法必须是static
* fallback 当接口出现了异常,就可以交给fallback指定的方法进行处理
* 如果不想在同一个类中 fallbackClass 但是方法必须是static
*
* blockHandler 如果和fallback同时指定了,则blockHandler优先级更高
* exceptionsToIgnore 排除哪些异常不处理
* @param id
* @return
*/
@RequestMapping("/user")
@SentinelResource(value = USER_RESOURCE_NAME, fallback = "fallbackHandleForGetUser",
/*exceptionsToIgnore = {ArithmeticException.class},*/
/*blockHandlerClass = User.class,*/ blockHandler = "blockHandlerForGetUser")
public User getUser(String id) {
int a=1/0;
return new User("xushu");
}
public User fallbackHandleForGetUser(String id,Throwable e) {
e.printStackTrace();
return new User("异常处理");
}
/**
* 注意:
* 1. 一定要public
* 2. 返回值一定要和源方法保证一致, 包含源方法的参数。
* 3. 可以在参数最后添加BlockException 可以区分是什么规则的处理方法
* @param id
* @param ex
* @return
*/
public User blockHandlerForGetUser(String id, BlockException ex) {
ex.printStackTrace();
return new User("流控!!");
}
}
测试结果图