《springcloud alibaba》 三 sentinel流量控制

目录

  • sentinel准备
  • 流控规则 qps
    • pom.xml
    • apllication.yml
    • 启动类
    • controller
    • 查看结果
      • 流控提示不太友好
  • 流控规则 线程数
  • 全局异常处理
    • pom.xml
    • application.yml
    • 启动类
    • 实体类
    • controller类
    • 异常类
    • 测试
  • 关联流控模式
    • 关联
      • jmeter
    • 链路
      • service
      • controller
      • 代码调整
  • 流控效果
    • Warm UP
  • 熔断降级规则
    • 慢调用比例
    • 异常比例
    • 异常数
  • 整合openFeign
    • stock项目
    • order项目
      • pom.xml
      • application.yml
    • openFeign降级报错友好处理
      • application.yml
      • 增加异常处理类
      • openFeign消费者接口改造
  • 热点参数流控
    • 代码
  • 系统保护规则
    • cpu
    • qps
  • 规则持久化
    • 原始模式
    • 拉模式
    • 推模式
    • nacos设置
      • pom.xml
      • application.yml

在这里插入图片描述

sentinel官方中文文档

sentinel准备

sentinel控制台1.8.0

  • 注意需要跟springboot cloud版本与之对应,不然会有很多问题
    在这里插入图片描述

在这里插入图片描述
输入命令

java -jar sentinel-dashboard-1.8.0.jar
  • 注意默认端口是8080,很容易冲突
    在这里插入图片描述
  • 账号和密码都是sentinel
    在这里插入图片描述

流控规则 qps

创建一个maven模块,父类的包,可以查看第一篇文章

pom.xml

<?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>springcloudalibaba</artifactId>
        <groupId>com.cxy.springcloud</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.cxy.ssentinelnew</groupId>
    <artifactId>sentinel-demo</artifactId>

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

    <dependencies>
        <!--web-->
        <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>
    </dependencies>
</project>

  • 导入sentinel启动包

apllication.yml

server:
  port: 8010

spring:
  application:
    name: sentinel-demo
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080

  • dashboard 是sentinel地址
  • 记得启动sentinel控制台界面

启动类

package com.cxy.sentinel;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author wu
 * @version 1.0
 * @date 2024/2/26 15:52
 */
@SpringBootApplication
public class StartApplication {
    public static void main(String[] args) {
        SpringApplication.run(StartApplication.class, args);
    }
}

controller

package com.cxy.sentinel.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author wu
 * @version 1.0
 * @date 2024/2/2 11:39
 */
@RestController
@RequestMapping("/order")
public class OrderController {

    @RequestMapping("/add")
    public String add(){
        System.out.println("下单成功");
        return "Hello Feign!";
    }
}

查看结果

在这里插入图片描述

  • 红色是项目里面的服务名
  • 注意:需要访问接口后,再来查看,不然会显示空白,先访问下面接口
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

  • 表示1秒钟之内超过2次就会流控
    在这里插入图片描述

流控提示不太友好

我们来修改一下代码

     @RequestMapping("/add")
    @SentinelResource(value = "add",blockHandler = "addBlockHandler")
    public String add(){
        System.out.println("下单成功");
        return "Hello Feign!";
    }

    public String addBlockHandler(BlockException exception){
        return "流控";
    }
  • addBlockHandler这个方法,有几点需要注意
    1. 一定是public
  • 2、返回值一定跟需要做流控的那个方法一样
  • 3、BlockException 的包记得,一定是sentinel下面的
    启动后,去访问http://localhost:8010/order/add接口,发现之前做的1秒2次流控不生效
    why?
    这是因为之前的规则是保存在内存中,重启服务器后, 就不存在,需要重新加一次
    在这里插入图片描述
    再来访问一下http://localhost:8010/order/add
    在这里插入图片描述
    -返回状态码也变成200,实际使用过程中,返回值,我们肯定会封装成一个返回类包装一下的

流控规则 线程数

package com.cxy.sentinel.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

/**
 * @author wu
 * @version 1.0
 * @date 2024/2/2 11:39
 */
@RestController
@RequestMapping("/order")
public class OrderController {

    /**
     * 流控----qps
     * @return
     */
    @RequestMapping("/add")
    @SentinelResource(value = "add",blockHandler = "addBlockHandler")
    public String add(){
        System.out.println("下单成功");
        return "Hello Feign!";
    }

    public String addBlockHandler(BlockException exception){
        return "流控";
    }

    /**
     *  流控--线程控制方法
     * @return
     * @throws InterruptedException
     */
    @RequestMapping("/addThread")
    @SentinelResource(value = "addThread",blockHandler = "addBlockHandler")
    public String addThread() throws InterruptedException {
        System.out.println("下单成功");
        TimeUnit.SECONDS.sleep(5);
        return "Hello Feign!"+Thread.currentThread().getName();
    }
}
  • addThread 这个方法是新增加的,其他的代码,跟qps的代码一样
  • 增加一个延迟,是为了测试方便测试线程数
    在这里插入图片描述
    在这里插入图片描述
    启动两个浏览器,才能测出线程数流控的效果
    在这里插入图片描述
  • 搞不清楚为什么,同一个浏览器,我看了一下线程名称也不一样,为什么不走流控

全局异常处理

在这里插入图片描述
在之前写的代码中,会存在一个问题,每一个需要流控、降级处理的方法,都需要加上@sentinelResource注解,在家一个异常处理的方式,用起来什么不方便,看起来也十分的别扭。
那有全局处理sentinel异常的方案,有的

pom.xml

<?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>springcloudalibaba</artifactId>
        <groupId>com.cxy.springcloud</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.cxy.ssentinelnew</groupId>
    <artifactId>sentinel-demo</artifactId>

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

    <dependencies>
        <!--web-->
        <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>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>
    </dependencies>
</project>

application.yml

server:
  port: 8010

spring:
  application:
    name: sentinel-demo
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080

启动类

package com.cxy.sentinel;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author wu
 * @version 1.0
 * @date 2024/2/26 15:52
 */
@SpringBootApplication
public class StartApplication {
    public static void main(String[] args) {
        SpringApplication.run(StartApplication.class, args);
    }
}

实体类

package com.cxy.sentinel.entity;

public enum ResponseCode {
    SUCCESS(200, "success"),
    FAILURE(201, "failure"),
    EXCEPTION(500, "exception"),
    INVALID_TOKEN(501, "invalidToken");

    private int code;
    private String message;

    ResponseCode(int code, String message) {
        this.code = code;
        this.message = message;
    }

    public int getCode() {
        return code;
    }

    public String getMessage(){
        return message;
    }
}


package com.cxy.sentinel.entity;

import lombok.Data;

import java.io.Serializable;

@Data
public class ResponseResult<T> implements Serializable {
    private static final long serialVersionUID = 1L;

    private int code;

    private String message;

    private T payload;

    public ResponseResult() {
        this.code = ResponseCode.SUCCESS.getCode();
        this.message = ResponseCode.SUCCESS.getMessage();
    }

    public ResponseResult(int code, String message) {
        this.code = code;
        this.message = message;
    }

    public ResponseResult(int code, String message, T payload) {
        this.code = code;
        this.message = message;
        this.payload = payload;
    }

    public static <T> ResponseResult<T> SUCCESS() {
        return new ResponseResult<>(ResponseCode.SUCCESS.getCode(), ResponseCode.SUCCESS.getMessage(), null);
    }

    public static <T> ResponseResult<T> SUCCESS(T payload) {
        return new ResponseResult<>(ResponseCode.SUCCESS.getCode(), ResponseCode.SUCCESS.getMessage(), payload);
    }

    public static <T> ResponseResult<T> FAILURE(String message) {
        return new ResponseResult<>(ResponseCode.FAILURE.getCode(), message);
    }

    public static <T> ResponseResult<T> EXCEPTION(String message) {
        return new ResponseResult<>(ResponseCode.EXCEPTION.getCode(), message, null);
    }

    public static <T> ResponseResult<T> EXCEPTION(ResponseCode resCode) {
        ResponseResult<T> resResult = new ResponseResult<>();
        resResult.setCode(resCode.getCode());
        resResult.setMessage(resCode.getMessage());
        return resResult;
    }

    public static <T> ResponseResult<T> INVALID_TOKEN(String message) {
        return new ResponseResult<>(ResponseCode.INVALID_TOKEN.getCode(), message);
    }
}


  • 返回辅助类

controller类

package com.cxy.sentinel.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.cxy.sentinel.entity.ResponseResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

/**
 * @author wu
 * @version 1.0
 * @date 2024/2/2 11:39
 */
@RestController
@RequestMapping("/order")
public class OrderController {


    /**
     *  流控--异常处理
     * @return
     * @throws InterruptedException
     */
    @RequestMapping("/addException")
    public ResponseResult addException() throws InterruptedException {
        System.out.println("流控异常处理!");
        return ResponseResult.SUCCESS();
    }
}

异常类

package com.cxy.sentinel.config;

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.cxy.sentinel.entity.ResponseResult;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;

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

@Component  //  注册为Bean  让Spring管理
public class SentinelExceptionHandler implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        String msg = "未知异常";
        int status = 429;

// 通过判断异常的类型 来判断到底是限流还是熔断降级还是授权限制
        if (e instanceof FlowException) {
            msg = "请求被限流了";
        } else if (e instanceof ParamFlowException) {
            msg = "请求被热点参数限流";
        } else if (e instanceof DegradeException) {
            msg = "请求被降级了";
        } else if (e instanceof AuthorityException) {
            msg = "没有权限访问";
            status = 401;
        }

        response.setContentType("application/json;charset=utf-8");
        response.setCharacterEncoding("utf-8");
        response.setStatus(status);
        new ObjectMapper().writeValue(response.getWriter(), ResponseResult.EXCEPTION(msg));
    }
}

  • 试过用全局注解的方式来处理sentinel的异常,不知道为什么捕获不到,有知道的朋友可以解答一下,网上我看也有类似的方法,但是,测试过不行

测试

先访问http://localhost:8010/order/addException接口,再增加一条流控为1的规则,表示1秒钟之内只能访问一次
在这里插入图片描述

  • 出现这个,表示设置成功

关联流控模式

在这里插入图片描述
流控模式,分为三种,直接、关联、链路

关联

类似场景,12306,如果下单人数过多,点击查询票的时候,就显示服务正在繁忙

当两个资源存在争取时,就会存在关联,例如,数据库的某个表的读写,写多,读少等等

    /**
     * 关联流控模式
     * @return
     */
    @RequestMapping("/addOrder")
    public String addOrder(){
        System.out.println("下单成功");
        return "生成订单!";
    }

    /**
     * 关联流控模式
     * @return
     */
    @RequestMapping("/get")
    public String get(){
        System.out.println("查询订单");
        return "查询订单!";
    }
  • 在全局异常处理的controller类中,增加如上代码
    在这里插入图片描述
    启动项目,增加流控,点击关联,访问http://localhost:8010/order/get 查询接口时,关联下单接口,意思是,下单接口访问过多时,查询会流控
    在这里插入图片描述
    为了方便测试,需要借助一个工具jmeter用来模拟发送请求

jmeter

jmeter测试工具
在这里插入图片描述

  • 表示100秒内,300个线程,1秒至少3次
    访问http://localhost:8010/order/get接口
    在这里插入图片描述

链路

跟全局异常处理一样的代码,增加如下代码

service

package com.cxy.sentinel.service;

/**
 * @author wu
 * @version 1.0
 * @date 2024/2/28 14:26
 */
public interface OrderService {
    /**
     * 查询用户
     * @return
     */
    public String getUser();
}


package com.cxy.sentinel.service;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.stereotype.Service;

/**
 * @author wu
 * @version 1.0
 * @date 2024/2/28 14:27
 */
@Service
public class OrderServiceImpl implements OrderService{
    @Override
    @SentinelResource(value = "getUser")
    public String getUser() {
        return "查询用户";
    }
}

  • 增加SentinelResource注解,说明是sentinel资源,在界面就可以进行设置

controller

在这里插入图片描述
-以前的controller增加如下代码

  @Autowired
    private OrderService orderService;

    //关联流控 访问/add 触发/get
    @RequestMapping("/test1")
    public String test1(){
        return orderService.getUser();
    }

    //关联流控 访问/add 触发/get
    @RequestMapping("/test2")
    public String test2(){
        return orderService.getUser();
    }

访问http://localhost:8010/order/test2,设置流控
在这里插入图片描述
继续访问http://localhost:8010/order/test2,三次,出现如下画面,说明,流控成功
在这里插入图片描述
== 为什么报错?==
这是因为service类里面增加@SentinelResource后,会导致,对应的接口,不走全局异常,只能自定义异常来处理

代码调整

在这里插入图片描述

  • 配置里面需要调整一下这个

package com.cxy.sentinel.service;

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

/**
 * @author wu
 * @version 1.0
 * @date 2024/2/28 14:27
 */
@Service
public class OrderServiceImpl implements OrderService{
    @Override
    @SentinelResource(value = "getUser",blockHandler="getUserHandler")
    public String getUser() {
        return "查询用户";
    }

    public String getUserHandler(BlockException ex) {
        return "流控用户";
    }
}


访问http://localhost:8010/order/test2,如下图,说明配置成功
在这里插入图片描述
总结起来:
两个坑点:

  • 配置里面application.yml配置里面需要设置成false, 全局流控异常处理不生效,需要自定义异常处理

流控效果

在这里插入图片描述

  • 流控效果分为三种

Warm UP

有一个预热的过程,长期处在一个低流量过程,突然一下子流量狂飙,很容易导致系统出问题,所以,通过冷启动,让通过的流量,缓慢的增加,在一定时间内,加到对应的阈值

在这里插入图片描述
设置快速失败为5

在这里插入图片描述

  • 设置1秒10次,循环4次
    在这里插入图片描述
  • 定时休息5秒
    在这里插入图片描述
  • 设置http请求
    在这里插入图片描述
    -通过上图可以发现,蓝色的线和绿色的线有重合的地方,我们的目标就是让蓝色的线,变平缓
    在这里插入图片描述
  • 设置成排队等待5秒,效果如下图
    在这里插入图片描述
  • 标红的地方,有空闲,说明,我们之前在线程哪里设置的,1秒10次,对服务器的压力不大

熔断降级规则

说到熔断,降级,我想大部分的人,脑海中,顿时就飘过hystrix,今天主要是看看sentinel的熔断

慢调用比例

在这里插入图片描述

  • 访问/order/addThread资源时,如果在1000毫秒内,请求数量超过5,并且这些数量中超过1000毫秒的请求数量的比例超过0.1则熔断1秒

代码和前面一样,在之前的基础上,增加
在这里插入图片描述

  /**
     *  熔断降级规则,----慢调用比例
     * @return
     * @throws InterruptedException
     */
    @RequestMapping("/addLevel")
    public String addLevel() throws InterruptedException {
        System.out.println("下单成功");
        TimeUnit.SECONDS.sleep(2);
        return "Hello Feign!"+Thread.currentThread().getName();
    }

三部曲:
1、访问接口http://localhost:8010/order/addLevel
2、添加熔断规则
在这里插入图片描述
3、jemter压测
在这里插入图片描述
在这里插入图片描述
再去访问,接口被熔断了
在这里插入图片描述

  • 熔断后,只有有一次不是慢查询,就会恢复正常

异常比例

熔断策略异常比例是以请求异常数量的比例作为阈值,当单位统计时长(statIntervalMs)内请求数大于设置的最小请求数,并且异常请求数的比例大于比例阈值,则接下来的请求会自动熔断,熔断时间为设置的熔断时长。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若在HALF-OPEN状态下有一个请求正常响应 则结束熔断,否则继续熔断。
在这里插入图片描述
先访问http://localhost:8010/order/err
在这里插入图片描述
在这里插入图片描述

  • 从第六次开始,就熔断降级

异常数

在这里插入图片描述
在这里插入图片描述

  • 连续访问3次后,服务就进行了熔断,会熔断10s

整合openFeign

openFeign代码
在这个基础上做测试
在这里插入图片描述

  • 主要是涉及两个项目

stock项目

在这里插入图片描述

    /**
     * 增加异常
     * @return
     */
    @RequestMapping("/reduct1")
    public String reduct1(){
       int a = 1/0;
        System.out.println("扣减库存!");
        return "扣减库存"+port;
    }

order项目

在这里插入图片描述

    /**
     * 产生异常
     * @return
     */
    @RequestMapping("/reduct1")
    public String reduct1(){
        String msg = stockFeignService.reduct1();
        return "Hello Feign!"+msg;
    }

在这里插入图片描述

pom.xml

<?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>springcloudalibaba</artifactId>
        <groupId>com.cxy.springcloud</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>order</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>

        <!--Nacos做配置中心-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <!--添加openfeign依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>

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

</project>

  • 添加sentinel依赖

application.yml

在这里插入图片描述

  • 红色部分,是新增代码
server:
  port: 8015

spring:
  application:
    name: order-service
  cloud:
    nacos:
      server-addr: 127.0.0.1:8848
      discovery:
        name: nacos
        password: nacos
        namespace: public

    loadbalancer:
      ribbon:
        enabled: false
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080
      web-context-unify: false   #默认将调用链路收起来




####设置springboot级别
logging:
  level:
    com.cxy.order.feign.StockFeignService: debug
feign:
  client:
    config:
      stock-servic: ###对应微服务
        ###链接超时时间  默认2s
        connectTimeout: 5000
        ### 请求处理超时时间 默认5s
        readTimeout: 10000
  ##添加feign对sentinel的兼容
  sentinel:
    enabled: true

访问http://localhost:8015/order/reduct1,直接报错,有点不友好
在这里插入图片描述

openFeign降级报错友好处理

1、增加openFeign对sentinel的兼容
在这里插入图片描述

application.yml

feign:
  client:
    config:
      stock-servic: ###对应微服务
        ###链接超时时间  默认2s
        connectTimeout: 5000
        ### 请求处理超时时间 默认5s
        readTimeout: 10000
  ##添加feign对sentinel的兼容
  sentinel:
    enabled: true

增加异常处理类

package com.cxy.order.feign;

import org.springframework.stereotype.Component;

/**
 * @author wu
 * @version 1.0
 * @date 2024/2/21 17:54
 */
@Component
public class StockFeignServiceFallback implements StockFeignService{

    @Override
    public String reduct() {
        return "降级";
    }

    @Override
    public String reduct1() {
        return "降级";
    }
}

  • 返回异常处理提示

openFeign消费者接口改造

在这里插入图片描述

  • 跟以前的hystric一样的写法
    启动order项目,再来访问
    在这里插入图片描述
    到这里,openFeign降级就完成咯。

热点参数流控

热点即经常访问的数据,很多时候,我们需要针对一些频率很高的数据,对其使用限制。

代码

  /**
     * 热点规则,必须使用@SentinelResource
     *
     * @return
     */
    @RequestMapping("/get/{id}")
    @SentinelResource(value = "getById", blockHandler = "HotBlockHandler")
    public String getById(@PathVariable("id") Integer id) {
        System.out.println("正常访问:" + id);
        return "正常访问:" + id;
    }

    public String HotBlockHandler(@PathVariable("id") Integer id, BlockException e) {
        return "热点异常处理" + id;
    }
  • 还是在之前项目中,进行更改(Order项目)
    在这里插入图片描述
  • 单机阈值遵循一个原则,热点参数和普通参数,谁多,谁就是设置成单机阈值
    例如: 某个商品平台,今天晚上进行白酒秒杀,其他的商品没有活动,就可以把普通商品设置成单机阈值,白酒作为参数特殊设置。
  • 上面的效果,就是普通的商品,能1秒访问10次,商品id为1的,1秒钟只能访问2次。

直接访问http://localhost:8015/order/get/1 三次
在这里插入图片描述

系统保护规则

系统保护规则是从应用级别的入口流量进行控制,从单台机器的总体 Load、RT、线程数、入口 QPS 和CPU使用率监控应用数据,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。

cpu

在这里插入图片描述

  • sentinel刚开始整的那个项目代码里面进行测试
package com.cxy.sentinel.config;

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.cxy.sentinel.entity.ResponseResult;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;

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

@Component  //  注册为Bean  让Spring管理
public class SentinelExceptionHandler implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        String msg = "未知异常";
        int status = 429;

// 通过判断异常的类型 来判断到底是限流还是熔断降级还是授权限制
        if (e instanceof FlowException) {
            msg = "请求被限流了";
        } else if (e instanceof ParamFlowException) {
            msg = "请求被热点参数限流";
        } else if (e instanceof DegradeException) {
            msg = "请求被降级了";
        }else if (e instanceof SystemBlockException){
            msg = "系统规则保护";
        }    else if (e instanceof AuthorityException) {
            msg = "没有权限访问";
            status = 401;
        }

        response.setContentType("application/json;charset=utf-8");
        response.setCharacterEncoding("utf-8");
        response.setStatus(status);
        new ObjectMapper().writeValue(response.getWriter(), ResponseResult.EXCEPTION(msg));
    }
}

  • 之前的历史代码,少了一个SystemBlockException异常else判断的代码,这里补一下

在这里插入图片描述

  • 为了方便测试,cpu使用率的值是0-1,所以这里的0.01表示,只要cpu超过1,就会走系统保护

在这里插入图片描述

qps

在这里插入图片描述
这里的1,表示所有接口的平均qps,而不是某个接口的阈值

规则持久化

在这里插入图片描述

原始模式

存在内存中,开发环境测试使用,服务一重启,配置就消失

拉模式

pull模式的数据源(如本地文件、RDBMS等)一般是可写入的。使用时需要在客户端注册数据源:将对应的读数据源注册至对应的 RuleManager,将写数据源注册至transport的WritableDataSourceRegistry中。

推模式

生产环境下一般更常用的是push模式的数据源。对于push模式的数据源,如远程配置中心(ZooKeeper, Nacos, Apollo等等),推送的操作不应由Sentinel客户端进行,而应该经控制台统一进行管理,直接进行推送,数据源仅负责获取配置中心推送的配置并更新到本地。因此推送规则正确做法应该是配置中心控制台/Sentinel控制台 → 配置中心 → Sentinel数据源 → Sentinel,而不是经Sentinel数据源推送至配置中心。这样的流程就非常清晰了:

nacos设置

在这里插入图片描述

  • 先新增nacos对应的配置

pom.xml

<?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>springcloudalibaba</artifactId>
        <groupId>com.cxy.springcloud</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>order</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>

        <!--Nacos做配置中心-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <!--添加openfeign依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>

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

        <!--sentinel配置中心控制台推送-->
        <!--以nacos作为sentinel数据源的依赖-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
    </dependencies>

</project>

在这里插入图片描述

  • 在以前的基础上,新增了该接口

application.yml

server:
  port: 8015

spring:
  application:
    name: order-service
  cloud:
#    nacos:
#      server-addr: 127.0.0.1:8848
#      discovery:
#        name: nacos
#        password: nacos
#        namespace: public

    loadbalancer:
      ribbon:
        enabled: false
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080
      web-context-unify: false   #默认将调用链路收起来
      datasource:
        flow-ds:
          nacos:
            server-addr: 127.0.0.1:8848
            username: nacos
            password: nacos
            namespace: public
            dataId: ${spring.application.name}-flow
            groupId: DEFAULT_GROUP
            data-type: json
            rule-type: flow




####设置springboot级别
logging:
  level:
    com.cxy.order.feign.StockFeignService: debug
feign:
  client:
    config:
      stock-servic: ###对应微服务
        ###链接超时时间  默认2s
        connectTimeout: 5000
        ### 请求处理超时时间 默认5s
        readTimeout: 10000
  ##添加feign对sentinel的兼容
  sentinel:
    enabled: true

  • flow-ds 是随便写的,其他的有讲究
    支持很多的数据库,这里我们使用的nacos,所以用nacos的配置
    ctrl+shift+\ 输入DataSourcePropertiesConfiguration,找到nacois得代码,打开
    在这里插入图片描述
    在这里插入图片描述
  • 可以进行参考配置

有个问题:不知道为什么,需要先调用一次服务的接口后,才能看到,我们之前在nacos里面的配置,同步到sentinel中,怀疑是不是缓存
在这里插入图片描述
到这里我们就实现sentinel配置持久化了
存在几个问题:
1.在nacos配置很复杂
2、在sentinel中变更后,怎么同步到nacos里面来,有知道朋友,可以留言评论

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/419154.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

idea项目中文乱码

背景&#xff1a; 从gitee下download了项目发现配置值文件application.properies中出现了乱码&#xff0c;如下 其他文件都正常&#xff0c;例如 解决&#xff1a; 不要 忘记 ok 解决后配置文件 application.properties

2.1 表结构数据

1、表结构数据 字段&#xff1a;整列数 记录&#xff1a;整行数 维度&#xff1a;业务角度 度量&#xff1a;业务行为结果 维度字段&#xff1a;文本型&#xff08;状态&#xff09; 度量字段&#xff1a;数值型&#xff08;交易结果&#xff09; 2、事实表&维度表 维度表…

ubuntu22.04安裝mysql8.0

官网下载mysql&#xff1a;MySQL :: Download MySQL Community Server 将mysql-server_8.0.20-2ubuntu20.04_amd64.deb-bundle.tar上传到/usr/local/src #解压压缩文件 tar -xvf mysql-server_8.0.20-2ubuntu20.04_amd64.deb-bundle.tar解压依赖包依次输入命令 sudo dpkg -i m…

基于springboot+vue的纺织品企业财务管理系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

顶刊 Radiology2023 Top10文章排行榜发布:ChatGPT霸占5席!医学前沿必读

顶刊 Radiology2023 Top10文章排行榜发布&#xff1a;ChatGPT霸占5席&#xff01;医学前沿必读 期刊基本信息 期刊名称&#xff1a;RADIOLOGY 期刊ISSN: 0033-8419 影响因子/SCI分区&#xff1a;19.7/1区 出版周期&#xff1a;Monthly Radiology 是医学放射学领域的顶级期刊&am…

【算法】最小生成树—Prim算法与Kruskal算法

Prim算法和Kruskal算法都是解决最小生成树问题的经典算法。最小生成树是原图的最小连通子图&#xff0c;它包含原图的全部结点&#xff0c;且保持图连通的所有边代价和最小。一个连通图可能有多个最小生成树。 一、Prim算法 含义 Prim算法&#xff0c;也被称为普里姆算法&…

Unity(第十七部)Unity自带的角色控制器

组件Character Controller 中文角色控制器 using System.Collections; using System.Collections.Generic; using UnityEngine;public class player : MonoBehaviour {private CharacterController player;void Start(){player GetComponent<CharacterController>();}v…

Win11系统实现adb命令向安卓子系统安装APP

Win11系统实现通过adb命令向安卓子系统安装已下载好的apk包。 要实现以上目标&#xff0c;我们需要用到一个Android SDK 的组件Android SDK Platform-Tools &#xff01;这个组件呢其实是被包含在 Android Studio中的&#xff0c;如果你对安卓开发有所了解对此应该不会陌生&…

jmeter如何请求访问https接口

添加线程组http请求 新建线程组&#xff0c;添加http请求 填入协议&#xff0c;ip&#xff0c;端口&#xff0c;请求类型&#xff0c;路径&#xff0c;以及请求参数&#xff0c;查看结果树等。 然后最关键的一步来了。 导入证书 步骤&#xff1a;获取证书&#xff0c;重新生…

Linux磁盘性能方法以及磁盘io性能分析

Linux磁盘性能方法以及磁盘io性能分析 1. fio压测1.1. 安装fio1.2. bs 4k iodepth 1&#xff1a;随机读/写测试&#xff0c;能反映硬盘的时延性能1.3. bs 128k iodepth 32&#xff1a;顺序读/写测试&#xff0c;能反映硬盘的吞吐性能 2. dd压测2.1. 测试纯写入性能2.2. 测试…

【深度学习】Pytorch 教程(十五):PyTorch数据结构:7、模块(Module)详解(自定义神经网络模型并训练、评估)

文章目录 一、前言二、实验环境三、PyTorch数据结构1、Tensor&#xff08;张量&#xff09;1. 维度&#xff08;Dimensions&#xff09;2. 数据类型&#xff08;Data Types&#xff09;3. GPU加速&#xff08;GPU Acceleration&#xff09; 2、张量的数学运算1. 向量运算2. 矩阵…

《2023跨境电商投诉大数据报告》发布|亚马逊 天猫国际 考拉海购 敦煌网 阿里巴巴

2023年&#xff0c;跨境电商API接口天猫国际、京东国际和抖音全球购以其强大的品牌影响力和市场占有率&#xff0c;稳坐行业前三的位置。同时&#xff0c;各大跨境电商平台消费纠纷问题层出不穷。依据国内知名网络消费纠纷调解平台“电诉宝”&#xff08;315.100EC.CN&#xff…

C++设计模式_创建型模式_工厂方法模式

目录 C设计模式_创建型模式_工厂方法模式 一、简单工厂模式 1.1 简单工厂模式引入 1.2 简单工厂模式 1.3 简单工厂模式利弊分析 1.4 简单工厂模式的UML图 二、工厂方法模式 2.1 工厂模式和简单工厂模式比较 2.2 工厂模式代码实现 2.3 工厂模式UML 三、抽象工厂模式 3.1 战斗场景…

C语言可以干些什么?C语言主要涉及哪些IT领域?

C语言可以干些什么&#xff1f;C语言主要涉及哪些IT领域&#xff1f; 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「C语言的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家…

LangChain---大型语言模型(LLM)的标准接口和编程框架

1.背景说明 公司在新的一年规划中突然提出要搞生成式AI(GenAI)的相关东西&#xff0c;在公司分享的参考资料中了解到了一些相关的信息&#xff0c;之所以想到使用LangChain&#xff0c;是因为在应用中遇到了瓶颈问题&#xff0c;除了已经了解和研究过的OpenAI的ChatGpt&#xf…

分层解耦-三层架构(未完)

controller层——》service——》dao——》service——》controller 控制反转 依赖注入

阿里巴巴找黄金宝箱(I)【华为OD机试-JAVAPythonC++JS】

题目描述 一贫如洗的樵夫阿里巴巴在去砍柴的路上&#xff0c;无意中发现了强盗集团的藏宝地&#xff0c;藏宝地有编号从0~N的箱子&#xff0c;每个箱子上面贴有一个数字&#xff0c;箱子中可能有一个黄金宝箱。 黄金宝箱满足排在它之前的所有箱子数字和等于排在它之后的所有箱子…

Android 性能优化--APK加固(1)混淆

文章目录 为什么要开启混淆如何开启代码混淆如何开启资源压缩代码混淆配置代码混淆后&#xff0c;Crash 问题定位结尾 本文首发地址&#xff1a;https://h89.cn/archives/211.html 最新更新地址&#xff1a;https://gitee.com/chenjim/chenjimblog 为什么要开启混淆 先上一个 …

“智农”-高标准农田

高标准农田是指通过土地整治、土壤改良、水利设施、农电配套、机械化作业等措施&#xff0c;提升农田质量和生产能力&#xff0c;达到田块平整、集中连片、设施完善、节水高效、宜机作业、土壤肥沃、生态友好、抗灾能力强、与现代农业生产和经营方式相适应的旱涝保收、稳产高产…

BUUCTF---wireshark1

1.题目描述 2.下载附件是一个.pcap的文件 3.需要用到wireshark工具&#xff0c;用该工具打开文件 4.用户在登录密码时一般不会用get方式提交&#xff0c;因为这样不安全&#xff0c;相比较而言post安全一点。 5.使用http.request.methodPOST命令进行过滤&#xff0c;得到一条流…