微服务实战 04 springCloud 集成 Sentinel 实战
参考《Spring Cloud Alibaba 微服务原理与实战》
springCloud 集成 Sentinel
-
引入依赖
<!-- SpringCloud Alibaba Sentinel --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency>
-
创建REST接口,通过@SentinelResource配置限流保护资源
@RestController @RequestMapping("api/testSentinel") public class TestSentinelController { @SentinelResource(value = "test",blockHandler = "handlerExcption1") @GetMapping() public Map<String,String> testSentinel(String name) throws InterruptedException { TimeUnit.SECONDS.sleep(2); HashMap<String, String> objectObjectHashMap = new HashMap<>(); objectObjectHashMap.put("msg",name); return objectObjectHashMap; } public static Map<String,String> handlerExcption1(String name,BlockException exception){ HashMap<String, String> objectObjectHashMap = new HashMap<>(); objectObjectHashMap.put("msg","禁止访问"); FlowRule flowRule = new FlowRule(); return objectObjectHashMap; } }
-
启动 sentinel 服务
-
在 application.yml 中加入如下配置
spring: cloud: sentinel: # 取消控制台懒加载 eager: true transport: # 控制台地址 dashboard: 127.0.0.1:8858
-
启动项目
-
通过 sentinel Dashboard 配置流控规则
-
使用 apiFox 或者其他工具测试
自定义 url 限流
在默认情况下 ,URL 触发限流会直接返回
大多数情况下们都采用JSON格式的数据,所以如果希望修改触发限流之后的返回结果形式,则可以通过自定义异常来处理,实现BlockExceptionHandler并且重写 handle方法
@Service
public class CustomerUrlBlockerHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
httpServletResponse.setHeader("Content-Type","application/json;charset=UTF-8");
String message = "{\"code\": 999,\"msg\":\"访问人数过多\"}";
httpServletResponse.getWriter().write(message);
}
}
还有一种 我们可以通过 以下配置,跳转到一个降级页面
spring.cloud.semtinel.servlet.block-page={url}
url 资源清洗
Sentinel 中的 CommonFilter 会把每个不同的url都作为不同的资源来处理
@GetMapping("user/{id}")
public Map<String,String> testSentinel1(@PathVariable("id") Long id) throws InterruptedException {
HashMap<String, String> objectObjectHashMap = new HashMap<>();
objectObjectHashMap.put("msg","hello");
return objectObjectHashMap;
}
上面的这两个写法会导致两个问题
- 限流统计不准确,实际需求时统计方法总的QPS,结果统计的时每个URL的QPS
- 导致Sentinel中资源数过多,默认资源数量的阈值是6000,多出的将不会生效
针对于上边第一个问题 我们可以通过UrlCleaner 来实现资源清洗
@Service
public class CustomerUrlCleaner implements UrlCleaner {
@Override
public String clean(String url) {
if(StringUtils.isEmpty(url)) {
return url;
}
if(url.startsWith("/clean/")){
return "/clean/*";
}else {
return url;
}
}
}
Sentinel集成Nacos数据源
通过 springBoot 接入Sentinel DashBoard所配置的的流控规则,都是保存在内存中的,一旦应用重启,这些规则都会被清除,为了解决这个问题,Sentinel提供了动态数据源支持
-
添加Nacos数据源依赖包
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency>
-
在 Naocs的配置中心配置数据源
spring: cloud: sentinel: # 取消控制台懒加载 eager: true transport: # 控制台地址 dashboard: 127.0.0.1:8858 datasource: - nacos: server-addr: 127.0.0.1:8848 data-id: ${spring.application.name}-sentinel namespace: zcctConfig group-id: sentinel-data data-type: json rule-type: flow
-
增加流控配置文件
-
启动项目测试
可以看到Sentinel控制台中增加了一个流控规则,当我们在Nacos中更改该规则时,可以同步到Sentinel DashBoard中
Sentinel集成Nacos动态规则原理
Nacos 虽然被作为 ”DataSource“ , 但实际上在这里仍然是配置中心的角色,开发者可以在Nacos控制台上动态修改流控规则并实现规则同步,但在 Sentinel Dashboard 中修改或新增规则后不会持久化到配置中心。