Spring Cloud Alibaba整合Sentinel

1、引入POM文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>vnacos</artifactId>
        <groupId>com.nacos</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>order-sentinel</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>


    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--sentinel启动器-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

   报错: Unable to create a Configuration, because no Bean Validation provider could be found. Add a provide 加下面POM文件
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.2.4.Final</version> </dependency> </dependencies> </project>

 

配置文件:

spring:
  application:
    name: order-sentinel
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8850     # 控制台 ip和端口

Controller层:

package com.sentinel.order.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

/**
 * @author vans on 2022/2/24 11:39
 */
@Slf4j
@RestController
@RequestMapping("/vn/sentinel")
public class VnSentinelController {


    @GetMapping(value = "/flow")
    @SentinelResource(value = "flow",blockHandler = "flowBlockHandler")
    public String  flow(){

        return "正常访问";
    }

    public String  flowBlockHandler(BlockException e){

        return "流控";
    }

    @GetMapping(value = "/flowThread")
    @SentinelResource(value = "flowThread",blockHandler = "flowBlockHandler")
    public String  flowThread() throws InterruptedException {

        TimeUnit.SECONDS.sleep(5);

        return "正常访问";
    }

}
BlockException异常统一处理(1、统一处理,将Controller层中@SentinelResource去掉;2、实现BlockExceptionHandler类)
package com.sentinel.order.interceptor.sentinel.exception;

import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sentinel.order.entity.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@Component
public class SentinelException implements BlockExceptionHandler {

    Logger log= LoggerFactory.getLogger(this.getClass());

    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse response, BlockException e) throws Exception {
        // getRule() 资源  规则的详细信息
        log.info("BlockExceptionHandler BlockException================"+e.getRule());

        Result r = null;

        if (e instanceof FlowException) {
            r = Result.error(100,"接口限流了");

        } else if (e instanceof DegradeException) {
            r = Result.error(101,"服务降级了");

        } else if (e instanceof ParamFlowException) {
            r = Result.error(102,"热点参数限流了");

        } else if (e instanceof SystemBlockException) {
            r = Result.error(103,"触发系统保护规则了");

        } else if (e instanceof AuthorityException) {
            r = Result.error(104,"授权规则不通过");
        }

        //返回json数据
        response.setStatus(500);
        response.setCharacterEncoding("utf-8");
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        new ObjectMapper().writeValue(response.getWriter(), r);
    }
}

 客户端启动后必须访问,在控制台才能看到数据

流控模式:(通常在服务提供短进行配置)


直接流控:

QPS流控:

 

线程流控:

 

关联流控:

 

链路流控:

 代码实现:

 ------配置文件:

spring:
  application:
    name: order-sentinel
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8850     # 控制台 ip和端口
      web-context-unify: false    # 默认将调用链路收敛, 导致链路流控效果无效, 所以  web-context-unify: false 才可以

 ------Controller层:

package com.sentinel.order.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.sentinel.order.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

/**
 * @author vans on 2022/2/24 11:39
 */
@Slf4j
@RestController
@RequestMapping("/vn/sentinel")
public class VnSentinelController {


    @Autowired
    private OrderService orderService;


    // 链路流控   test1 获取订单
    @RequestMapping("/test1")
    public String test1(){
        return orderService.selectOrder();
    }

    // 链路流控   test2 获取订单
    @RequestMapping("/test2")
    public String test2() throws InterruptedException {
        return orderService.selectOrder();
    }

}

 ------Service层:

package com.sentinel.order.service.impl;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.sentinel.order.service.OrderService;
import org.springframework.stereotype.Service;

/**
 * @author vans on 2022/2/25 16:59
 */

@Service
public class OrderServiceImpl implements OrderService {

   /**
   *
    * 链路流控,此场景拦截不到BlockException,对应@SentinelResource指定的资源必须在@SentinelResource注解中指定blockHandler处理BlockException
   */
    @Override
    @SentinelResource(value="selectOrder",blockHandler = "blockHandlerSelectOrder")
    public String selectOrder() {
        return "查询订单selectOrder";
    }

    public String blockHandlerSelectOrder(BlockException e) {
        return "查询订单selectOrder流控";
    }
}

 

 流控效果

warmUp:预热(激增流量)

即预热/冷启动方式

当系统长期处于低水位的情况下,当流量 突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐 增加到阈值上限,给冷系统一个预热的时间,

避免冷系统被压垮。 冷加载因子: codeFactor 默认是3,即请求 QPS 从 threshold / 3 开始,经预热时长逐渐升至设定的 QPS 阈值。

 

 

 

 

 

 

 

 

排队等待:(脉冲流量)

 

 

 

 

 

 

 

 

降级规则(通常在服务消费端进行配置)
---慢调用比例
慢调用比例 (SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间), 请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)
内请求数目大于设置的最小请求数目,
并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态 (HALF­OPEN 状态),若接下来的一个请求响应时
间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会 再次被熔断

 

 

 

 

 

---异常调用比例
异常比例 (ERROR_RATIO):当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例 大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进
入探测恢复状态(HALF­OPEN 状 态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0], 代表 0% ­ 100%

 

 

 

 ---异常调用数

异常数 (ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探 测恢复状态(HALF­OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束
熔断,否则会再次被熔断。 注意:异常降级仅针对业务异常,对 Sentinel 限流降级本身的异常(BlockException)不生效

 

---热点参数限流

 

热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流
热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。

图片解释:

 

 

 

 

 

代码:

 
/**
     * 热点规则,必须使用@SentinelResource
     *
     * @param id
     * @throws InterruptedException
     */
    @PostMapping("/get/{id}")
    @SentinelResource(value = "getById",blockHandler = "HotBlockHandler")
    public String getById(@PathVariable("id") Integer id) throws InterruptedException {
        return "getById--success";
    }

    public String HotBlockHandler(@PathVariable("id") Integer id,BlockException e) throws InterruptedException {

        return "getById--hotError";
    }

 

系统规则
 
1、Load 自适应(仅对 Linux/Unix­like 机器生效):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的
并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统 容量由系统的 maxQps * minRt 估算得出。设定参考值一般是 CPU cores * 2.5
https://www.cnblogs.com/gentlemanhai/p/8484839.html 2、CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0­1.0),比较灵敏。 3、平均 RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。 4、并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。 5、入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。

 

 

 

 

 
 
 
 
 
 
 
 
 

 

posted @ 2022-02-24 13:40  VNone  阅读(221)  评论(0)    收藏  举报