目录
为什么要流控
解决方案
超时机制
服务限流
服务熔断
服务降级
Sentinel工作原理
Sentinel保护方式
API实现
引入依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.8.0</version>
</dependency>
@RestController
@RequestMapping("/sentinel/")
public class HelloController {
@Resource
OrderFeignService orderFeignService;
private static final String RESOURCE_NAME="helloSentinel";
@RequestMapping("hello")
public String findOrders(@RequestParam(value = "id") String id){
Entry entry=null;
try {
entry= SphU.entry(RESOURCE_NAME);//资源名,唯一标识字符串
//要保护的业务
System.out.println("正常");
return orderFeignService.findOrders(id).getName();
} catch (BlockException e) {
return "流控了";
} catch (Exception e){
Tracer.traceEntry(e,entry);
}finally{
if(entry!=null){
entry.exit();
}
}
return null;
}
/**定义流控规则**/
@PostConstruct
private static void initFlowRules(){
List<FlowRule> list=new ArrayList<>();
FlowRule rule=new FlowRule();
//设置受保护的资源
rule.setResource(RESOURCE_NAME);
//设置流控规则 QPS
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
//设置受保护资源的阈值
rule.setCount(1);
list.add(rule);
FlowRuleManager.loadRules(list);//加载配置好的规则
}
}
狂点请求接口:http://localhost:8048/sentinel/hello?id=1
也可以用注解 SentinelResource
@RequestMapping("testSenOrders")
@SentinelResource(value = "findSenOrders",
blockHandlerClass = CommonBlockHandler.class,
blockHandler ="handleException2"
)
public String findSenOrders(@RequestParam(value = "id") String id){
return orderFeignService.findOrders(id).getName();
}
package com.drb.cloud.sentinel;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import java.util.Map;
public class CommonBlockHandler {
public static String handleException(Map<String,Object> params, BlockException exception){
return "***********被限流了="+exception;
}
public static String handleException2(String id, BlockException exception){
return "***********被限流了2="+exception;
}
}
添加依赖:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>1.8.0</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.8.0</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
修改yml配置:
sentinel:
transport:
dashboard: 127.0.0.1:8080
启动dashboard:
启动微服务,请求接口http://localhost:8048/sentinel/testSenOrders?id=1
进入dashboard页面:http://localhost:8080/ 用户密码默认:sentinel
流控规则
添加方法流控:
狂点http://localhost:8048/sentinel/testSenOrders?id=1触发限流,此处报错为自定义CommonBlockHandler类中方法
添加接口流控,会先于上面方法流控触发:
狂点http://localhost:8048/sentinel/testSenOrders?id=1触发限流:
测试QPS的关联
一边频繁访问http://localhost:8048/sentinel/testSenOrders2?id=1
再访问http://localhost:8048/sentinel/testSenOrder3?id=1,被限制的资源是/sentinel/testSenOrder3
流控效果
熔断规则
测试熔断降级:
@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, BlockException e) throws Exception {
CommonResult errorInfo = null;
if(e instanceof FlowException){
errorInfo=new CommonResult("接口限流了");
}else if(e instanceof DegradeException){
errorInfo=new CommonResult("服务降级了");
}else if(e instanceof ParamFlowException){
errorInfo=new CommonResult("热点参数限流了");
}else if(e instanceof SystemBlockException){
errorInfo=new CommonResult("系统保护规则不通过");
}else if(e instanceof AuthorityException){
errorInfo=new CommonResult("授权规则不通过");
}
httpServletResponse.setStatus(500);
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
new ObjectMapper().writeValue(httpServletResponse.getWriter(),errorInfo);
}
}
@RequestMapping("test")
public CommonResult test(@RequestParam(value = "id") String id){
try{
Thread.sleep(200);
}catch (Exception e){
e.printStackTrace();
}
return new CommonResult("==============================test");
}
热点规则
@RequestMapping("/info/{id}")
@SentinelResource(value = "findOrderInfo",
blockHandlerClass = CommonBlockHandler.class,
blockHandler ="handleException",
fallbackClass = CommonFallback.class,
fallback = "fallback"
)
public CommonResult findOrderInfo(@PathVariable String id){
return new CommonResult(orderFeignService.findOrders(id).getName());
}
先添加热点规则
再编辑热点规则,配置热点参数值1
测试当http://localhost:8048/sentinel/info/1值为1时,连点2次触发热点参数阈值限流,其它比如http://localhost:8048/sentinel/info/3需要连点4次触发热点规则阈值限流
系统规则
1.8.0各个规则生效顺序:授权规则>系统规则>热点>流控>链路
授权规则
openfeign整合sentinel
@FeignClient(name="order-demo",path="/order/",fallbackFactory = FallBackFeignServiceFactory.class)
public interface OrderFeignService {
@GetMapping("findOrder")
CommonResult findOrders(@RequestParam(value = "id",required = false) String id);
}
@Component
public class FallBackFeignServiceFactory implements FallbackFactory<OrderFeignService> {
@Override
public OrderFeignService create(Throwable throwable) {
return new OrderFeignService() {
@Override
public CommonResult findOrders(String id) {
if(throwable instanceof FlowException){
return new CommonResult("FallBackFeignServiceFactory接口限流了");
}
return new CommonResult("FallBackFeignServiceFactory接口降级了");
}
};
}
}
请求http://localhost:8048/sentinel/info/1 ,可以看到http://order-demo/order/findOrder也在控制台可以配置流控
配置/order/findOrder流控
由于/sentinel/info/1接口会请求/order/findOrder,所以点击/sentinel/info/1可以触发/order/findOrder流控规则:
规则持久化
规则推送模式
原始模式
pull模式
push模式
测试降级和熔断配置持久化
引入依赖:<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency>
修改yml配置
添加nacos配置文件:
启动微服务,测试接口
查看sentinel控制台:
修改nacos配置:
查看到sentinel控制台,可以看到同步过来了:
到这里,如果我们想在sentinel控制台改规则同步到nacos配置中心,我们需要改sentinel源码了