《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同步配置持续化到nacos
    • sentinel同步到nacos演示
    • 源码
      • 修改pom.xml
      • nacos包移动
      • application.properties
      • 配置
      • 修改代码
        • 流控
          • 添加流控规则时同步推送到nacos
            • 测试
      • 其他规则

在这里插入图片描述

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: 8010spring:application:name: sentinel-democloud: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: 8010spring:application:name: sentinel-democloud: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 {@Overridepublic 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增加如下代码

  @Autowiredprivate 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: 8015spring:application:name: order-servicecloud:nacos:server-addr: 127.0.0.1:8848discovery:name: nacospassword: nacosnamespace: publicloadbalancer:ribbon:enabled: falsesentinel:transport:dashboard: 127.0.0.1:8080web-context-unify: false   #默认将调用链路收起来####设置springboot级别
logging:level:com.cxy.order.feign.StockFeignService: debug
feign:client:config:stock-servic: ###对应微服务###链接超时时间  默认2sconnectTimeout: 5000### 请求处理超时时间 默认5sreadTimeout: 10000##添加feign对sentinel的兼容sentinel:enabled: true

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

openFeign降级报错友好处理

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

application.yml

feign:client:config:stock-servic: ###对应微服务###链接超时时间  默认2sconnectTimeout: 5000### 请求处理超时时间 默认5sreadTimeout: 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{@Overridepublic String reduct() {return "降级";}@Overridepublic 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 {@Overridepublic 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: 8015spring:application:name: order-servicecloud:
#    nacos:
#      server-addr: 127.0.0.1:8848
#      discovery:
#        name: nacos
#        password: nacos
#        namespace: publicloadbalancer:ribbon:enabled: falsesentinel:transport:dashboard: 127.0.0.1:8080web-context-unify: false   #默认将调用链路收起来datasource:flow-ds:nacos:server-addr: 127.0.0.1:8848username: nacospassword: nacosnamespace: publicdataId: ${spring.application.name}-flowgroupId: DEFAULT_GROUPdata-type: jsonrule-type: flow####设置springboot级别
logging:level:com.cxy.order.feign.StockFeignService: debug
feign:client:config:stock-servic: ###对应微服务###链接超时时间  默认2sconnectTimeout: 5000### 请求处理超时时间 默认5sreadTimeout: 10000##添加feign对sentinel的兼容sentinel:enabled: true
  • flow-ds 是随便写的,其他的有讲究
    支持很多的数据库,这里我们使用的nacos,所以用nacos的配置
    ctrl+shift+\ 输入DataSourcePropertiesConfiguration,找到nacois得代码,打开
    在这里插入图片描述
    在这里插入图片描述
  • 可以进行参考配置

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

sentinel同步配置持续化到nacos

之前是只能通过在nacos里面设置json格式的方式来设置

sentinel同步到nacos演示

在sentinel里面,新增一条流控规则
在这里插入图片描述

  • 之前测试的时候,忘记截图,通过编辑来截图
    在这里插入图片描述
    在这里插入图片描述

源码

sentinel 控制台
下载zip包,引入idea
在这里插入图片描述

  • 主要是改造dashboard项目

修改pom.xml

在这里插入图片描述

  • 不然,会有一个service的类报错,注意jdk是8,如果版本不一样,得特殊处理

nacos包移动

在这里插入图片描述

  • 使用的nacos就移动nacos,到src下,跟当前目录一下的包下

application.properties

在这里插入图片描述

  • 增加一个配置
    在这里插入图片描述
    -找到nacosConfig,调整一下对应的代码, 如果有设置账号和密码,这里就需要调整一下,不知道的可以百度一下

配置

在这里插入图片描述
-NacosConfigUtil类的这两个配置也是有讲究的,不修改,默认分组是service_group

  • 第二个参数,意思就是生成文件的名称后缀
    在这里插入图片描述

修改代码

流控

流控需要注意:得区分是V1还是V2的接口,修改对应的代码
在这里插入图片描述

  • 新增流控就知道是走V1还是V2的结果咯
添加流控规则时同步推送到nacos

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

    @Autowired@Qualifier("flowRuleNacosProvider")private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;@Autowired@Qualifier("flowRuleNacosPublisher")private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;try {rulePublisher.publish(app,rules);}catch (Exception e){logger.info("同步失败");}
  • 按截图,添加对应的代码
测试

添加流控规则
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 设置的阈值是111,count也是111,说明sentinel的修改会同步到nacos
  • 注意: 上面我只设置了流控的

其他规则

参考这个博客设置

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【快刊合集】中科院2区SCI,Elsevier出版社,仅2个月录用!

【SciencePub学术】 1 计算机智能类SCI&#xff08;高质量/分区上升&#xff09; 【期刊简介】IF&#xff1a;6.5-7.0&#xff0c;JCR1区&#xff0c;中科院2区 【出版社】Elsevier出版社 【版面类型】正刊&#xff0c;仅5篇版面 【检索情况】SCIE在检&#xff0c;预计3个…

AI日报:埃隆·马斯克起诉OpenAI

埃隆马斯克&#xff08;ElonMusk&#xff09;正在起诉OpenAI涉嫌违约&#xff0c;声称这位ChatGPT的创建者违反了其成为非营利组织的创始承诺&#xff0c;这位科技亿万富翁表示&#xff0c;他资助并培育了这一承诺。 在一份长达46页的爆炸性投诉中&#xff0c;马斯克将OpenAI首…

在三个el-form-item中的el-radio的值中取一个发送给后端怎么获取

问: 请问,这段代码怎么获取:无策略,策略1,策略2的值? 回答: 问: 三个里面只可以选中一个吗? 回答:

docker容器内修改容器时间

因为开发需要&#xff0c;需要临时修改容器内时间测试&#xff0c;且不影响宿主机的原始时间。调研了下相关方法&#xff0c;现做记录如下. LIBFAKETIME ​ libfaketime 可以安装在linux和macOS系统。它使用操作系统的预加载library机制&#xff0c;因此对于静态链接或setuid程…

linemap | 这样好看的山峦地图真的可以快速绘制啦~~

上一次介绍了Python绘制svg的优秀可视化库Pygal&#xff0c;今天我们介绍一下一个优秀的R地图可视化绘制包-linemap包&#xff0c;顾名思义&#xff0c;该包是是为了绘制由线组成的地图&#xff0c;其官网如下&#xff1a;https://github.com/rCarto/linemap。该包主要拥有两个…

在CentOS7系统中安装Tomcat

下载 下载地址&#xff1a;Apache Tomcat - Welcome! 使用工具上传 使用FinalShell自带的上传工具将Tomcat的二进制发布包上传到Linux 在FinalShell文件栏点击上传按钮 将下载好的 apache-tomcat-9.0.86.tar.gz 上传至根目录 查看上传结果 # 跳转到root cd ~ # 查看目录内容…

【Java设计模式】六、代理模式:静态代理、JDK + CGLIB动态代理

文章目录 1、代理对象2、代理模式结构3、静态代理4、JDK动态代理5、JDK动态代理的原理6、CGLIB动态代理7、三种代理的对比8、代理模式的总结 结构型设计是将类或者对象按某种布局&#xff08;继承机制、组合聚合&#xff09;来组成更大结构。包括七种&#xff1a; * 代理模式 …

【Python】外网远程登录访问jupyter notebook+pycharm使用ipython

第一步&#xff1a;创建python虚拟环境 conda create -n py3610 python3.6.10第二步&#xff1a;安装ipython pip install ipython pip install ipython notebook第三步&#xff1a;创建 IPython Notebook 服务器配置文件 # 进入python交互shell&#xff0c;设置密码 >&…

信钰证券|沪指震荡涨0.26%,传媒等板块拉升,消费电子概念活跃

5日早盘&#xff0c;沪指盘中窄幅震荡上扬&#xff0c;创业板指、科创50指数走高&#xff0c;北证50指数跌超2%&#xff1b;北向资金小幅流入。 截至午间收盘&#xff0c;沪指涨0.26%报3047.2点&#xff0c;深成指微涨0.05%&#xff0c;创业板指涨0.42%&#xff0c;科创50指数…

GEE 数据集 ——利用leafmap python软件包实现NASA数据的接入(colab示例)

我们如何获取我们想要的数据,这里我们通过 leafmap python软件包实现NASA数据种全球超过9000+的数据集产品的接入和使用。这里我们使用在线的colab来实现处理,因为这里我们可以很好的应用已经在线配置好的colab环境来实现,省去了安装过程的繁琐。 要下载和访问数据,您需要…

AI预测福彩3D第一弹【2024年3月4日预测】

众所周知&#xff0c;深度学习算法&#xff08;AI算法&#xff09;由于其内部含有庞大数量的神经元&#xff0c;理论上能够拟合任意维度的数据&#xff0c;目前在大数据分析领域应用非常广泛&#xff0c;并且能够很好的挖掘数据规律&#xff0c;对相关数据进行预测分析。 前面一…

Unity 角色控制(初版)

角色控制器组件&#xff0c;当然是将组件放在角色上了。 using System.Collections; using System.Collections.Generic; using UnityEngine;public class c1 : MonoBehaviour {// 获取角色控制器private CharacterController player;void Start(){// 加载角色控制器player …