微服务流控Sentinel3

  • Post author:
  • Post category:其他

目录

Sentinel工作原理

流控规则

熔断规则

热点规则

系统规则

openfeign整合sentinel

规则持久化


为什么要流控

解决方案

超时机制

服务限流

 服务熔断

  

 服务降级

 

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源码了


版权声明:本文为dingruibao原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。