sentinel 使用 nacos 作为数据源示例

This commit is contained in:
YunaiV
2020-01-31 00:44:08 +08:00
parent 80595e87d3
commit 3f55794dd2
6 changed files with 133 additions and 31 deletions

View File

@@ -13,19 +13,13 @@
<artifactId>lab-46-sentinel-demo-nacos</artifactId>
<dependencies>
<!-- 实现对 SpringMVC 的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 实现对 Nacos 作为配置中心的自动化配置 -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>0.2.4</version>
</dependency>
<!-- Sentinel 核心库 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
@@ -44,11 +38,18 @@
<artifactId>sentinel-spring-webmvc-adapter</artifactId>
<version>1.7.1</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.alibaba.csp</groupId>-->
<!-- <artifactId>sentinel-datasource-extension</artifactId>-->
<!-- <version>1.7.1</version>-->
<!-- </dependency>-->
<!-- Sentinel 对【热点参数限流】的支持 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-parameter-flow-control</artifactId>
<version>1.7.1</version>
</dependency>
<!-- Sentinel 对 Spring AOP 的拓展 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>1.7.1</version>
</dependency>
<!-- Sentinel 对 Nacos 作为数据源的支持 -->
<dependency>
<groupId>com.alibaba.csp</groupId>

View File

@@ -1,6 +1,6 @@
package cn.iocoder.springboot.lab46.sentineldemo.config;
import com.alibaba.boot.nacos.config.properties.NacosConfigProperties;
import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
@@ -19,13 +19,25 @@ import java.util.Properties;
public class SentinelConfiguration {
@Bean
public NacosDataSource nacosDataSource(NacosConfigProperties nacosConfigProperties, ObjectMapper objectMapper) {
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
@Bean
public NacosDataSource nacosDataSource(ObjectMapper objectMapper) {
// Nacos 配置。这里先写死,推荐后面写到 application.yaml 配置文件中。
String serverAddress = "127.0.0.1:8848"; // Nacos 服务器地址
String namespace = ""; // Nacos 命名空间
String dataId = "demo-application-flow-rule"; // Nacos 配置集编号
// String dataId = "example-sentinel"; // Nacos 配置集编号
String group = "DEFAULT_GROUP"; // Nacos 配置分组
// 创建 NacosDataSource 对象
Properties properties = new Properties();
properties.setProperty(PropertyKeyConst.SERVER_ADDR, nacosConfigProperties.getServerAddr());
properties.setProperty(PropertyKeyConst.NAMESPACE, nacosConfigProperties.getNamespace());
NacosDataSource<List<FlowRule>> nacosDataSource = new NacosDataSource<>(properties,
nacosConfigProperties.getGroup(), nacosConfigProperties.getDataId(),
new Converter<String, List<FlowRule>>() {
properties.setProperty(PropertyKeyConst.SERVER_ADDR, serverAddress);
properties.setProperty(PropertyKeyConst.NAMESPACE, namespace);
NacosDataSource<List<FlowRule>> nacosDataSource = new NacosDataSource<>(properties, group, dataId,
new Converter<String, List<FlowRule>>() { // 转换器,将读取的 Nacos 配置,转换成 FlowRule 数组
@Override
public List<FlowRule> convert(String value) {
try {
@@ -35,6 +47,8 @@ public class SentinelConfiguration {
}
}
});
// 注册到 FlowRuleManager 中
FlowRuleManager.register2Property(nacosDataSource.getProperty());
return nacosDataSource;
}

View File

@@ -14,7 +14,7 @@ public class SpringMvcConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// Add Sentinel interceptor
addSentinelWebTotalInterceptor(registry);
// addSentinelWebTotalInterceptor(registry);
addSentinelWebInterceptor(registry);
}
@@ -23,6 +23,20 @@ public class SpringMvcConfiguration implements WebMvcConfigurer {
SentinelWebMvcConfig config = new SentinelWebMvcConfig();
config.setHttpMethodSpecify(true); // 是否包含请求方法。即基于 URL 创建的资源,是否包含 Method。
// config.setBlockExceptionHandler(new DefaultBlockExceptionHandler()); // 设置 BlockException 处理器。
// config.setOriginParser(new RequestOriginParser() { // 设置请求来源解析器。用于黑白名单控制功能。
//
// @Override
// public String parseOrigin(HttpServletRequest request) {
// // 从 Header 中,获得请求来源
// String origin = request.getHeader("s-user");
// // 如果为空,给一个默认的
// if (StringUtils.isEmpty(origin)) {
// origin = "default";
// }
// return origin;
// }
//
// });
// 添加 SentinelWebInterceptor 拦截器
registry.addInterceptor(new SentinelWebInterceptor(config)).addPathPatterns("/**");

View File

@@ -1,7 +1,12 @@
package cn.iocoder.springboot.lab46.sentineldemo.controller;
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@@ -18,4 +23,60 @@ public class DemoController {
return "test";
}
@GetMapping("/sleep")
public String sleep() throws InterruptedException {
Thread.sleep(100L);
return "sleep";
}
// 测试热点参数限流
@GetMapping("/product_info")
@SentinelResource("demo_product_info_hot")
public String productInfo(Integer id) {
return "商品编号:" + id;
}
// 手动使用 Sentinel 客户端 API
@GetMapping("/entry_demo")
public String entryDemo() {
Entry entry = null;
try {
// 访问资源
entry = SphU.entry("entry_demo");
// ... 执行业务逻辑
return "执行成功";
} catch (BlockException ex) {
return "被拒绝";
} finally {
// 释放资源
if (entry != null) {
entry.exit();
}
}
}
// 测试 @SentinelResource 注解
@GetMapping("/annotations_demo")
@SentinelResource(value = "annotations_demo_resource",
blockHandler = "blockHandler",
fallback = "fallback")
public String annotationsDemo(@RequestParam(required = false) Integer id) throws InterruptedException {
if (id == null) {
throw new IllegalArgumentException("id 参数不允许为空");
}
return "success...";
}
// BlockHandler 处理函数,参数最后多一个 BlockException其余与原函数一致.
public String blockHandler(Integer id, BlockException ex) {
return "block" + ex.getClass().getSimpleName();
}
// Fallback 处理函数,函数签名与原函数一致或加一个 Throwable 类型的参数.
public String fallback(Integer id, Throwable throwable) {
return "fallback" + throwable.getMessage();
}
}

View File

@@ -1,11 +0,0 @@
nacos:
# Nacos 配置中心的配置项,对应 NacosConfigProperties 配置类
config:
server-addr: 127.0.0.1:8848 # Nacos 服务器地址
bootstrap:
enable: true # 是否开启 Nacos 配置预加载功能。默认为 false。
log-enable: true # 是否开启 Nacos 支持日志级别的加载时机。默认为 false。
data-id: example-sentinel # 使用的 Nacos 配置集的 dataId。
type: JSON # 使用的 Nacos 配置集的配置格式。默认为 PROPERTIES。
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP。
namespace: # 使用的 Nacos 的命名空间,默认为 null。

View File

@@ -6,6 +6,7 @@ import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@@ -56,4 +57,26 @@ public class DemoController {
}
}
// 测试 @SentinelResource 注解
@GetMapping("/annotations_demo")
@SentinelResource(value = "annotations_demo_resource",
blockHandler = "blockHandler",
fallback = "fallback")
public String annotationsDemo(@RequestParam(required = false) Integer id) throws InterruptedException {
if (id == null) {
throw new IllegalArgumentException("id 参数不允许为空");
}
return "success...";
}
// BlockHandler 处理函数,参数最后多一个 BlockException其余与原函数一致.
public String blockHandler(Integer id, BlockException ex) {
return "block" + ex.getClass().getSimpleName();
}
// Fallback 处理函数,函数签名与原函数一致或加一个 Throwable 类型的参数.
public String fallback(Integer id, Throwable throwable) {
return "fallback" + throwable.getMessage();
}
}