feat: Sentinel 示例

This commit is contained in:
dunwu 2024-02-05 07:59:21 +08:00
parent a44e5f4c5d
commit 84ece9cf77
10 changed files with 274 additions and 19 deletions

View File

@ -11,5 +11,6 @@
<modules>
<module>trace</module>
<module>ratelimit</module>
</modules>
</project>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.dunwu.spring</groupId>
<artifactId>spring-distributed-ratelimit</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<name>Spring::分布式::流量控制</name>
<modules>
<module>sentinel</module>
</modules>
</project>

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
</parent>
<groupId>io.github.dunwu.spring</groupId>
<artifactId>spring-distributed-ratelimit-sentinel</artifactId>
<version>1.0.0</version>
<name>Spring::分布式::流量控制::Sentinel</name>
<dependencies>
<!-- Spring Web 的 Spring Boot 启动包,完成 Web 相关的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Test 的 Spring Boot 启动包,提供了一些便利的测试工具集 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.8.7</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.8.7</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,102 @@
package example.spring.ratelimit.sentinel;
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphO;
import com.alibaba.csp.sentinel.SphU;
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 lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
/**
* 限流示例 Http 接口
*
* @author <a href="mailto:forbreak@163.com">Zhang Peng</a>
* @date 2024-01-30
*/
@Slf4j
@RestController
public class RateLimitController {
/**
* 抛出异常的方式定义资源并限流
*/
@GetMapping("/limit1")
public String limit1() {
// 1.5.0 版本开始可以利用 try-with-resources 特性
// 资源名可使用任意有业务语义的字符串比如方法名接口名或其它可唯一标识的字符串
try (Entry entry = SphU.entry("limit1")) {
// 被保护的业务逻辑
log.info("limit1 -> 请求通过");
return "ok";
} catch (BlockException e) {
// 资源访问阻止被限流或被降级
// 在此处进行相应的处理操作
log.error("limit1 -> 请求限流", e);
return "failed";
}
}
/**
* 返回布尔值方式定义资源并限流
*/
@GetMapping("/limit2")
public String limit2() {
// 资源名可使用任意有业务语义的字符串
if (SphO.entry("limit2")) {
// 务必保证finally会被执行
try {
// 被保护的业务逻辑
log.info("limit2 -> 请求通过");
return "ok";
} finally {
SphO.exit();
}
} else {
// 资源访问阻止被限流或被降级
// 进行相应的处理操作
log.error("limit2 -> 请求限流");
return "failed";
}
}
/**
* 注解方式定义资源并限流
*/
@GetMapping("/limit3")
@SentinelResource(value = "limit3")
public String limit3() {
try {
log.info("limit3 -> 请求通过");
return "ok";
} catch (Exception e) {
log.error("limit3 -> 请求限流", e);
return "failed";
}
}
/**
* 初始化流控规则
*/
@PostConstruct
public void initFlowRules() {
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
// 设置限流资源
rule.setResource("limit1");
// 设置 QPS
rule.setCount(2);
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
}

View File

@ -0,0 +1,49 @@
package example.spring.ratelimit.sentinel;
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
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 java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:forbreak@163.com">Zhang Peng</a>
* @date 2024-01-30
*/
public class SentinelDemo {
public static void main(String[] args) {
// 定义规则
initFlowRules();
// 定义资源
while (true) {
// 1.5.0 版本开始可以利用 try-with-resources 特性
// 资源名可使用任意有业务语义的字符串比如方法名接口名或其它可唯一标识的字符串
try (Entry entry = SphU.entry("HelloWorld")) {
// 被保护的业务逻辑
System.out.println("hello world");
} catch (BlockException ex) {
// 资源访问阻止被限流或被降级
// 在此处进行相应的处理操作
System.err.println("blocked!");
}
}
}
private static void initFlowRules() {
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
rule.setResource("HelloWorld");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
// Set limit QPS to 20.
rule.setCount(20);
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
}

View File

@ -0,0 +1,24 @@
package example.spring.ratelimit.sentinel;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 启动类
*
* @author <a href="mailto:forbreak@163.com">Zhang Peng</a>
* @date 2024-01-30
*/
@SpringBootApplication
public class SpringBootSentinelApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(SpringBootSentinelApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
}
}

View File

@ -0,0 +1,12 @@
${AnsiColor.BRIGHT_YELLOW}${AnsiStyle.BOLD}
________ ___ ___ ________ ___ __ ___ ___
|\ ___ \|\ \|\ \|\ ___ \|\ \ |\ \|\ \|\ \
\ \ \_|\ \ \ \\\ \ \ \\ \ \ \ \ \ \ \ \ \\\ \
\ \ \ \\ \ \ \\\ \ \ \\ \ \ \ \ __\ \ \ \ \\\ \
\ \ \_\\ \ \ \\\ \ \ \\ \ \ \ \|\__\_\ \ \ \\\ \
\ \_______\ \_______\ \__\\ \__\ \____________\ \_______\
\|_______|\|_______|\|__| \|__|\|____________|\|_______|
${AnsiColor.CYAN}${AnsiStyle.BOLD}
:: Java :: (v${java.version})
:: Spring Boot :: (v${spring-boot.version})
${AnsiStyle.NORMAL}

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%boldYellow(%thread)] [%highlight(%-5level)] %boldGreen(%c{36}.%M) - %boldBlue(%m%n)
</pattern>
</encoder>
</appender>
<logger name="example.spring" level="INFO" />
<root level="WARN">
<appender-ref ref="CONSOLE" />
</root>
</configuration>

View File

@ -1,6 +1,5 @@
package example.spring.web.helloworld;
import example.spring.web.helloworld.entity.Weather;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@ -9,27 +8,9 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
private final WeatherService weatherService;
public HelloController(WeatherService weatherService) {
this.weatherService = weatherService;
}
@RequestMapping("hello")
public String index() {
return "Hello World";
}
@RequestMapping("weather")
public Weather weather() {
log.info("查询南京市天气:");
Weather weather = weatherService.getWeather("101190101");
if (weather == null) {
log.info("未查到数据!");
return null;
}
weatherService.printBasicWeatherInfo(weather);
return weather;
}
}

View File

@ -16,5 +16,6 @@
<module>codes/web</module>
<module>codes/integration</module>
<module>codes/security</module>
<module>codes/distributed</module>
</modules>
</project>