// 定义限流规则
@PostConstruct
public void initFlowRules() {
// 创建存放限流规则的集合
List<FlowRule> rules = new ArrayList<>();
// 创建限流规则
FlowRule rule = new FlowRule();
// 定义资源,标识Sentinel会对哪个资源生效
rule.setResource("HelloResource1");
// 定义限流规则类型 QPS限流类型
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
// 定义QPS每秒能通过的请求个数
rule.setCount(2.0);
// 将限流规则存放到集合中
rules.add(rule);
// 加载限流规则
FlowRuleManager.loadRules(rules);
}
/**
* 抛出异常的方式定义资源
* Sentinel中的SphU包含了try-catch风格的API。用这种方式,当资源翻身了限流之后会抛出BlockException。这个时候可以捕获异常,进行限流之后的逻辑处理。
*/
@GetMapping("/hello1")
public String hello1() {
// 限流入口
// 使用限流规则监控保护资源
try (Entry entry = SphU.entry("HelloResource1")) {
LocalDateTime now = LocalDateTime.now();
// 被保护的资源
return "Hello, Now is " + dateTimeFormatter.format(now);
} catch (BlockException exception) {
exception.printStackTrace();
log.error("Exception is : {}", exception);
// 被限流或是被降级的操作处理
return "系统繁忙,请稍候重试";
}
}
/**
* 返回Boolean值方式定义资源
* Sentinel中的SphO提供if-else风格的API。用这种方式,当资源发生了限流之后会返回false,这个时候可以根据返回值,进行限流之后的逻辑处理
* SphO.entry()需要与SphO.exit()方法成对出现,否则会导致调用链记录异常,抛出ErrorEntryFreeException
*/
@GetMapping("/hello2")
public String hello2() {
// 进行限流控制,限流入口
if (SphO.entry("HelloResource2")) {
try {
// 被保护的资源
log.info("访问成功");
return "Hello, Now is " + dateTimeFormatter.format(LocalDateTime.now());
} finally {
// 限流出口
SphO.exit();
}
} else {
// 被限制或者降级的处理
log.info("系统繁忙,请稍候重试");
return "系统繁忙,请稍候重试";
}
}
先定义异步Service,并开启异步
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;
@Service
@Slf4j
public class HelloService {
private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Async
public void hello3() {
log.info("异步开始: {}", dateTimeFormatter.format(LocalDateTime.now()));
try {
TimeUnit.SECONDS.sleep(2L);
} catch (InterruptedException exception) {
log.error("exception is {}", exception);
}
log.info("异步结束: {}", dateTimeFormatter.format(LocalDateTime.now()));
}
}
/**
* 异步调用支持
* Sentinel支持异步调用链路的统计。在异步调用中,需要通过SphU.asyncEntry()方法定义资源,并通常需要在异步的回调函数中调用exit方法
*/
@GetMapping("/hello3")
public String hello3() {
// 进行限流控制
AsyncEntry asyncEntry = null;
try {
// 限流入口
asyncEntry = SphU.asyncEntry("HelloResource3");
// 异步方法调用
helloService.hello3();
return "Hello, Now is " + dateTimeFormatter.format(LocalDateTime.now());
} catch (BlockException exception) {
// 被限流或者降级的处理
return "系统繁忙,请稍候重试";
} finally {
if (Objects.nonNull(asyncEntry)) {
// 限流出口
asyncEntry.exit();
}
}
}
需要引入
<dependency>
<groupId>com.alibaba.cspgroupId>
<artifactId>sentinel-annotation-aspectjartifactId>
<version>1.7.2version>
dependency>
配置SentinelResourceAspect
import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SentinelAspectJConfiguration {
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
}
/**
* 注解方式定义资源
* Sentinel支持通过@SentinelResource注解定义资源并配置blockHandler函数来进行限流之后的处理
*/
@GetMapping("/hello4")
// 定义限流资源和限流降级回调函数
@SentinelResource(value = "HelloResource4", blockHandler = "exceptionHandler")
public String hello4() {
return "Hello, Now is " + dateTimeFormatter.format(LocalDateTime.now());
}
// blockHandler函数,原方法调用被限流/降级/系统保护时候被调用,不能为private
public String exceptionHandler(BlockException exception) {
log.error("exception is {}", exception);
return "系统繁忙,请稍候重试";
}
完整pom.xml文件:
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.4.2version>
<relativePath/>
parent>
<groupId>com.lwy.itgroupId>
<artifactId>sentinel-demoartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>sentinel-demoname>
<description>Demo project for Spring Boot Sentineldescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cspgroupId>
<artifactId>sentinel-coreartifactId>
<version>1.8.5version>
dependency>
<dependency>
<groupId>com.alibaba.cspgroupId>
<artifactId>sentinel-transport-simple-httpartifactId>
<version>1.8.5version>
dependency>
<dependency>
<groupId>com.alibaba.cspgroupId>
<artifactId>sentinel-annotation-aspectjartifactId>
<version>1.8.5version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
exclude>
excludes>
configuration>
plugin>
plugins>
build>
project>
更多学习参考官方文档:https://sentinelguard.io/zh-cn/docs/quick-start.html