Sentinel - 介绍

sentinel的使用可以分为两个部分

核心库不依赖任何框架/库,能够允许在jdk7以上的版本运行时环境,同时对Dubbo、SpringCloud等框架也有比较好的支持。

控制台主要负责管理推送规则、监控、集群限流分配管理、机器发现等。

一、sentinel core

引入依赖

<sentinel.version>1.8.3</sentinel.version>

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-core</artifactId>
    <version>${sentinel.version}</version>
</dependency>
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-annotation-aspectj</artifactId>
    <version>${sentinel.version}</version>
</dependency>
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-transport-simple-http</artifactId>
    <version>${sentinel.version}</version>
</dependency>
  • sentinel-core核心包
  • sentinel-annotation-aspectj适合spring切面和注解
  • sentinel-transport-simple-http便于接入console控制台

引入注解

@Configuration
public class SentinelAspectConfiguration {
    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }
}

使用方法:定义资源、定义规则

//定义资源使用注解方式
@SentinelResource("HelloWorld")
public void helloWorld() {
    // 资源中的逻辑
    System.out.println("hello world");
}
//定义规则
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);
}
  • SentinelResource为Sentinel的注解

  • value为资源标识

以上就完成了sentinel的基本使用。

使用实例:

   private static final String KEY = "queryGoodsInfo2";

    /**
     * 模拟商品查询接口
     *
     * @param spuId
     * @return
     */
    @SentinelResource(value = KEY, blockHandler = "blockHandlerMethod", fallback = "queryGoodsInfoFallback")
    public String queryGoodsInfo(String spuId) {

        // 模拟调用服务出现异常
        if ("0".equals(spuId)) {
            throw new RuntimeException();
        }

        return "query goodsinfo success, " + spuId;
    }

    //用来处理Sentinel 限流/熔断等错误 处理方法中方法名、参数都需与受保护的函数保持一致
    public String blockHandlerMethod(String spuId, BlockException e) {
        log.warn("queryGoodsInfo222 blockHandler", e.toString());
        return "queryGoodsInfo error, blockHandlerMethod res: " + spuId;

    }

    //用来处理接口中业务代码所有异常 处理方法中方法名、参数都需与受保护的函数保持一致
    public String queryGoodsInfoFallback(String spuId, Throwable e) {
        log.warn("queryGoodsInfo222 fallback", e.toString());
        return "queryGoodsInfo error, return fallback res: " + spuId;
    }

    @PostConstruct
    public void initFlowQpsRule() {
        List<FlowRule> rules = new ArrayList<FlowRule>();
        FlowRule rule1 = new FlowRule();
        rule1.setResource(KEY);
        // QPS控制在2以内
        rule1.setCount(2);
        // QPS限流
        rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule1.setLimitApp("default");
        rules.add(rule1);
        FlowRuleManager.loadRules(rules);
    }
View Code

 如果使用了注解方式,异常处理方法必须手工定义,不会走全局异常。

二、Dashboard

控制台下载地址:

可以从https://github.com/alibaba/Sentinel/releases下载sentinel-dashboard-$version.jar包。

 启动:

java -Dserver.port=8718 -Dcsp.sentinel.dashboard.server=localhost:8718 -Dproject.name=sentinel-dashboard -Dcsp.sentinel.api.port=8719 -jar D:\sentinel\sentinel-dashboard-1.8.0.jar

Sentinel Dashboard使用的是懒加载,因此需要调用接口后才会在控制台显示,如果只引入而不调用接口,是不会在控制台显示的。 

控制台配置的规则,重启后规则会消失。

三、Openfeign sentinel 容错

Feign在调用远程服务的时候,由于远程服务的原因,可能会产生异常。就需要进行相应的容错降级设计,注意不是 流控。
当Feign远程调用服务出现问题后,进入到了容错工厂类中的同名方法,执行容错逻辑。而且,Feign调用产生的异常信息也可以获取到。

引入alibaba依赖

<!--sentinel客户端依赖-->
<dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        <version>2.2.3.RELEASE</version>
</dependency>

1、开启openfeign对sentinel的支持,单独的标签:

feign:
  client:
    config:
      default:
        #连接超时时间
        connectTimeout: 5000
        #数据读取超时是时间
        readTimeout: 5000
  sentinel:
    enabled: true

注意:如果要启用控制台 则在 springcloud标签下加上如下配置,这样就可以使用控制台进行配置了。

sentinel:
      # 取消控制台懒加载
      eager: true
      transport:
        # 控制台地址
        dashboard: 127.0.0.1:8858

2、为被容错的interface指定容错类(容错工厂类)

//@FeignClient(name="stock-service",path="/stock",fallback = StockFeignServiceFallback.class)
@FeignClient(name="stock-service",path="/stock",fallbackFactory = StockFeignFallbackFactory.class)
public interface StockFeignService {
    /**
     * 声明需要调用的rest接口对应的方法
     * @return
     */
    @RequestMapping("/reduct2")
    String reduct();

    @RequestMapping("/res")
    String res();
}

3、创建容错类

容错类的创建有两种方案:
1、直接继承被容错的接口,并为每个方法实现容错方案
2、实现FallbackFactory接口
推荐使用第2种方案,实现FallbackFactory接口。这样可以在容错工厂类中拿到具体的错误,便于后期排查问题。

实例:

@Component
public class StockFeignFallbackFactory implements FallbackFactory<StockFeignService> {
    @Override
    public StockFeignService create(Throwable e) {
        System.out.println("打印流控错误信息" + e.getMessage());
        return new StockFeignService()
        {
            @Override
            public String reduct() {
                return "factory 降级了";
            }
            @Override
            public String res() {
                return "facotory 降级了";
            }
        };

    }
}

4、controller处理

package cn.jack.controller;
 
import cn.jack.domain.Order;
import cn.jack.domain.Product;
import cn.jack.service.OrderService;
import cn.jack.service.ProductService;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
 
@RestController
@Slf4j
public class OrderController {
 
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private OrderService orderService;
    @Autowired
    private DiscoveryClient discoveryClient;
    @Autowired
    private ProductService productService;
 
    /**
     * 下单 -- 基于Feign实现服务调用
     * @param pid   商品id
     * @return
     */
    @RequestMapping("/order/prod/{pid}")
    public Order order(@PathVariable("pid") Long pid) {
        log.info("收到下单请求,准备查询商品信息。pid={}", pid);
 
        // 通过Feign调用商品微服务,查询商品信息
        Product product = this.productService.findByPid(pid);
        log.info("商品信息查询成功。内容为:{}", JSON.toJSONString(product));
        
        // 进行容错判断
        if (product.getPid() == -100) {
            Order order = new Order();
            order.setOid(-100L);
            order.setPname("下单失败");
            return order;
        }
 
        // 生成商品信息保存
        Order order = new Order();
        order.setNumber(1);
        order.setPid(pid);
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());
        order.setUid(1);
        order.setUsername("测试用户");
 
        this.orderService.createOrder(order);
        log.info("订单信息保存成功。内容为:{}", JSON.toJSONString(order));
 
        return order;
    }
}
View Code

注意:以上只是容错降级,如果有流控则可以统一定制流控异常处理类:

/**
 * 流控异常统一处理
 */
@Component
public class SentinelFallbackHandler implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
            Map<String, Object> backMap = new HashMap<>();
            if (e instanceof FlowException) {
                backMap.put("code", -1);
                backMap.put("msg", "限流-异常啦");
                backMap.put("data", null);
            } else if (e instanceof DegradeException) {
                backMap.put("code", -2);
                backMap.put("msg", "降级-异常啦");
                backMap.put("data", null);
            } else if (e instanceof ParamFlowException) {
                backMap.put("code", -3);
                backMap.put("msg", "热点-异常啦");
                backMap.put("data", null);
            } else if (e instanceof SystemBlockException) {
                backMap.put("code", -4);
                backMap.put("msg", "系统规则-异常啦");
                backMap.put("data", null);
            } else if (e instanceof AuthorityException) {
                backMap.put("code", -5);
                backMap.put("msg", "认证-异常啦");
                backMap.put("data", null);
            }

            // 设置返回json数据
            httpServletResponse.setStatus(200);//响应消息的状态码
            httpServletResponse.setHeader("content-Type", "application/json;charset=UTF-8");
            httpServletResponse.getWriter().write(JSON.toJSONString(backMap, SerializerFeature.WriteMapNullValue));
    }
}
View Code

满足流控条件时,走流控异常,满足降级异常时走降级异常

 四、springcloud gateway sentinel nacos 持久化

引入:

<!-- SpringCloud Ailibaba Sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
 
        <!-- SpringCloud Ailibaba Sentinel Gateway -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
        </dependency>
        
        <!-- sentinel datasource nacos -->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>

配合参数:

    sentinel:
      # 取消控制台懒加载
      eager: true
      transport:
        # 控制台地址
        dashboard: 127.0.0.1:8858
      # nacos配置持久化
      datasource:
        ds1:
          nacos:
            server-addr: 127.0.0.1:8848
            dataId: sentinel-ruoyi-gateway
            groupId: DEFAULT_GROUP
            data-type: json
            rule-type: flow

 nacos配置:

[
    {
        "resource": "ruoyi-auth",
        "count": 500,
        "grade": 1,
        "limitApp": "default",
        "strategy": 0,
        "controlBehavior": 0
    },
    {
        "resource": "ruoyi-system",
        "count": 1000,
        "grade": 1,
        "limitApp": "default",
        "strategy": 0,
        "controlBehavior": 0
    }
]

dashboard查看流控规则:

 

 sentinel做了持久化,一般不在需要控制台配置规则了,规则提前预置在nacos。

参考:https://blog.csdn.net/liaomingwu/article/details/122181098

posted on 2022-02-17 17:05  TrustNature  阅读(235)  评论(0编辑  收藏  举报