当前位置: 首页 > news >正文

15、Spring Cloud Alibaba Sentinel实现熔断与限流

注:本篇文章主要参考周阳老师讲解的cloud进行整理的!

1、Sentinel

1.1、官网

https://sentinelguard.io/zh-cn/
等价对标 Spring Cloud Circuit Breaker

1.2、是什么

https://github.com/alibaba/Sentinel/wiki

1.3、去哪下

https://github.com/alibaba/Sentinel/releases

1.4、能干嘛

从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性

1.5、怎么玩(面试题)

  • 讲讲什么是缓存穿透?击穿?雪崩?如何解决?
    https://www.bilibili.com/video/BV13R4y1v7sP/?p=123

1.5.1、服务雪崩

多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其它的微服务,这就是所谓的“扇出”。如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩效应”。对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒钟内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障。这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。

所以,通常当你发现一个模块下的某个实例失败后,这时候这个模块依然还会接收流量,然后这个有问题的模块还调用了其他的模块,这样就会发生级联故障,或者叫雪崩。复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败。

在这里插入图片描述

1.5.2、服务降级

服务降级,说白了就是一种服务托底方案,如果服务无法完成正常的调用流程,就使用默认的托底方案来返回数据。

例如,在商品详情页一般都会展示商品的介绍信息,一旦商品详情页系统出现故障无法调用时,会直接获取缓存中的商品介绍信息返回给前端页面。

1.5.3、服务熔断

在分布式与微服务系统中,如果下游服务因为访问压力过大导致响应很慢或者一直调用失败时,上游服务为了保证系统的整体可用性,会暂时断开与下游服务的调用连接。这种方式就是熔断。类比保险丝达到最大服务访问后,直接拒绝访问,拉闸限电,然后调用服务降级的方法并返回友好提示。
服务熔断一般情况下会有三种状态:闭合、开启和半熔断;

闭合状态(保险丝闭合通电OK):服务一切正常,没有故障时,上游服务调用下游服务时,不会有任何限制。
开启状态(保险丝断开通电Error):上游服务不再调用下游服务的接口,会直接返回上游服务中预定的方法。
半熔断状态:处于开启状态时,上游服务会根据一定的规则,尝试恢复对下游服务的调用。此时,上游服务会以有限的流量来调用下游服务,同时,会监控调用的成功率。如果成功率达到预期,则进入关闭状态。如果未达到预期,会重新进入开启状态。

1.5.4、服务限流

服务限流就是限制进入系统的流量,以防止进入系统的流量过大而压垮系统。其主要的作用就是保护服务节点或者集群后面的数据节点,防止瞬时流量过大使服务和数据崩溃(如前端缓存大量实效),造成不可用;还可用于平滑请求,类似秒杀高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行。

限流算法有两种,一种就是简单的请求总量计数,一种就是时间窗口限流(一般为1s),如令牌桶算法和漏牌桶算法就是时间窗口的限流算法。

  • 服务隔离

有点类似于系统的垂直拆分,就按照一定的规则将系统划分成多个服务模块,并且每个服务模块之间是互相独立的,不会存在强依赖的关系。如果某个拆分后的服务发生故障后,能够将故障产生的影响限制在某个具体的服务内,不会向其他服务扩散,自然也就不会对整体服务产生致命的影响。

互联网行业常用的服务隔离方式有:线程池隔离和信号量隔离。

1.5.5、服务超时

整个系统采用分布式和微服务架构后,系统被拆分成一个个小服务,就会存在服务与服务之间互相调用的现象,从而形成一个个调用链。

形成调用链关系的两个服务中,主动调用其他服务接口的服务处于调用链的上游,提供接口供其他服务调用的服务处于调用链的下游。服务超时就是在上游服务调用下游服务时,设置一个最大响应时间,如果超过这个最大响应时间下游服务还未返回结果,则断开上游服务与下游服务之间的请求连接,释放资源。

2、安装Sentinel

2.1、sentinel组件由2部分构成

在这里插入图片描述

https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D

  • 后台8719默认
  • 前台8080开启

2.2、安装步骤

2.2.1、下载

https://github.com/alibaba/Sentinel/releases

在这里插入图片描述

下载到本地sentinel-dashboard-1.8.6.jar

2.2.2、运行命令

  • 前提

    • Java环境OK
    • 8080端口不能被占用
  • 命令

    • java -jar sentinel-dashboard-1.8.6.jar

2.2.3、访问sentinel管理界面

  • 登录账号密码均是sentinel
  • http://localhost:8080 在这里插入图片描述

3、微服务8401整合Sentinel入门案例

3.1、启动Nacos8848成功

startup.cmd -m standalone
http://localhost:8848/nacos

3.2、启动Sentinel8080成功

java -jar sentinel-dashboard-1.8.6.jar

3.3、新建微服务8401

3.3.1、新建cloudalibaba-sentinel-service8401

  • 将被哨兵纳入管控的8401微服务提供者
    在这里插入图片描述

3.3.2、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"><modelVersion>4.0.0</modelVersion><parent><groupId>com.mui.cloud</groupId><artifactId>cloud2024</artifactId><version>1.0-SNAPSHOT</version></parent><groupId>com.mui.cloud</groupId><artifactId>cloudalibaba-sentinel-service8401</artifactId><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!--SpringCloud alibaba sentinel --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency><!--nacos-discovery--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!-- 引入自己定义的api通用包 --><dependency><groupId>com.mui.cloud</groupId><artifactId>cloud-api-commons</artifactId><version>1.0-SNAPSHOT</version></dependency><!--SpringBoot通用依赖模块--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--hutool--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId></dependency><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.28</version><scope>provided</scope></dependency><!--test--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

3.3.3、YML

server:port: 8401spring:application:name: cloudalibaba-sentinel-servicecloud:nacos:discovery:server-addr: localhost:8848         # Nacos服务注册中心地址sentinel:transport:dashboard: localhost:8080 # 配置Sentinel dashboard控制台服务地址port: 8719 # 默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口

3.3.4、主启动

package com.mui.cloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@EnableDiscoveryClient
@SpringBootApplication
public class Main8401 {public static void main(String[] args) {SpringApplication.run(Main8401.class, args);}
}

3.3.5、业务类FlowLimitController

package com.mui.cloud.controller;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class FlowLimitController {@GetMapping("/testA")public String testA() {return "------testA";}@GetMapping("/testB")public String testB() {return "------testB";}}
  • 启动微服务8401并访问

3.4、启动8401微服务后查看sentinel控制台

  • 空空如也,啥都没有
    在这里插入图片描述

3.4.1、sentinel采用的懒加载说明

  • 注意

想使用Sentinel对某个接口进行限流和降级等操作,一定要先访问下接口,使Sentinel监测出响应的接口

  • 执行一次访问即可

    • http://localhost:8401/testA
    • http://localhost:8401/testB
  • 效果
    在这里插入图片描述

4、流控规则

4.1、基本介绍

在这里插入图片描述

  • 概述
    Sentinel能够对流量进行控制,主要是监控应用的QPS流量或者并发线程数等指标,如果达到指定的阈值时,就会被流量进行控制,以避免服务被瞬时的高并发流量击垮,保证服务的高可靠性。参数见最下方:在这里插入图片描述
1资源名资源的唯一名称,默认就是请求的接口路径,可以自行修改,但是要保证唯一。
2针对来源具体针对某个微服务进行限流,默认值为default,表示不区分来源,全部限流。
3阈值类型QPS表示通过QPS进行限流,并发线程数表示通过并发线程数限流。
4单机阈值与阈值类型组合使用。如果阈值类型选择的是QPS,表示当调用接口的QPS达到阈值时,进行限流操作。如果阈值类型选择的是并发线程数,则表示当调用接口的并发线程数达到阈值时,进行限流操作。
5是否集群选中则表示集群环境,不选中则表示非集群环境。

4.2、 流控模式

在这里插入图片描述

4.2.1、 直接

  • 默认的流控模式,当接口到限流条件时,直接开启限流功能
  • 配置及说明
    • 表示1秒钟内查询1次就是OK,若超过次数1,就直接-快速失败,报默认错误在这里插入图片描述
  • 测试
    • 快速点击访问http://localhost:8401/testA
    • 结果在这里插入图片描述
    • 思考
      • 直接调用默认报错信息,技术方面OK,但是,是否应该由我们自己的后续处理?
      • 类似有个fallback的兜底方法

4.2.2、关联

4.2.2.1、是什么
  • 当管理的资源达到阈值时,就限流自己
  • 当与A关联的资源B达到阈值后,就限流A自己
  • B惹事,A挂了
    • 张三感冒,李四吃药
4.2.2.2、配置A
  • 当关联资源/testB的qps阀值超过1时,就限流/testA的Rest访问地址,当关联资源到阈值后限制配置好的资源名,B惹事,A挂了在这里插入图片描述
4.2.2.3、Jmeter模拟并发密集访问testB
  • https://jmeter.apache.org/download_jmeter.cgi(超级慢)

    • Apache JMeter 5.6.3 (Requires Java 8+)
  • https://mirrors.cloud.tencent.com/apache/jmeter/binaries/ (下载速度快)

  • 访问testB成功

    • http://localhost:8401/testB
  • Run在这里插入图片描述在这里插入图片描述

  • 大批量线程高并发访问B,导致A失效了

4.2.2.4、运行后发现testA挂了
  • 点击访问http://localhost:8401/testA
  • 结果在这里插入图片描述

4.2.3、链路

  • 来自不通链路的请求对同一个目标访问时,实施针对性的不通限流措施
    • 比如C请求来访问就限流,D请求来访问就是OK
4.2.3.1、修改微服务cloudalibaba-sentinel-service8401
  • YML
server:port: 8401spring:application:name: cloudalibaba-sentinel-servicecloud:nacos:discovery:server-addr: localhost:8848         # Nacos服务注册中心地址sentinel:transport:dashboard: localhost:8080 # 配置Sentinel dashboard控制台服务地址port: 8719 # 默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口web-context-unify: false # controller层的方法对service层调用不认为是同一个根链路
  • 业务类
    • 新建FlowLimitService
package com.mui.cloud.service;import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.stereotype.Service;@Service
public class FlowLimitService {@SentinelResource(value = "common")public void common() {System.out.println("------FlowLimitService come in");}
}
  • 修改FlowLimitController
package com.mui.cloud.controller;import com.mui.cloud.service.FlowLimitService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class FlowLimitController {@GetMapping("/testA")public String testA() {System.out.println("aaa");return "------testA";}@GetMapping("/testB")public String testB() {System.out.println("bbb");return "------testB";}/*** 流控-链路演示demo* C和D两个请求都访问flowLimitService.common()方法,阈值到达后对C限流,对D不管*/@Resourceprivate FlowLimitService flowLimitService;@GetMapping("/testC")public String testC() {flowLimitService.common();return "------testC";}@GetMapping("/testD")public String testD() {flowLimitService.common();return "------testD";}}
4.2.3.2、sentinel配置

说明:C和D两个请求都访问flowLimitService.common()方法,对C限流,对D不管

在这里插入图片描述

4.2.3.3、测试
  • http://localhost:8401/testC
    • 超过一秒钟一次后,就发生限流在这里插入图片描述
    • D链路OK

4.3、流控效果

4.3.1、直接

  • 快速失败(默认的流控处理)
    • 直接失败,抛出异常
      • Blocked by Sentinel(flow limiting)

4.3.2、预热Warm UP

4.3.2.1、 限流-冷启动

限流-冷启动
在这里插入图片描述

4.3.2.2、说明

公式: 阈值除以冷却银子coldFactor(默认值为3),经过预热时长后才会达到阈值

4.3.2.3、官网

在这里插入图片描述

  • 源码
    • package com.alibaba.csp.sentinel.slots.block.flow.controller;在这里插入图片描述
4.3.2.4、WarmUP配置

默认 coldFactor 为 3,即请求QPS从(threshold / 3) 开始,经多少预热时长才逐渐升至设定的 QPS 阈值。

案例,单机阈值为10,预热时长设置5秒。
系统初始化的阈值为10 / 3 约等于3,即单机阈值刚开始为3(我们人工设定单机阈值是10,sentinel计算后QPS判定为3开始);
然后过了5秒后阀值才慢慢升高恢复到设置的单机阈值10,也就是说5秒钟内QPS为3,过了保护期5秒后QPS为10

在这里插入图片描述

  • 多次点击http://localhost:8401/testB
    • 刚开始不行,后续慢慢OK
4.3.2.5、应用场景

如:秒杀系统在开启的瞬间,会有很多流量上来,很有可能把系统打死,预热方式就是把为了保护系统,可慢慢的把流量放进来,慢慢的把阈值增长到设置的阈值。

4.3.3、排队等待

4.3.3.1、是什么

在这里插入图片描述

4.3.3.2、修改FlowLimitController
@GetMapping("/testE")
public String testE() {System.out.println(System.currentTimeMillis() + "      testE,排队等待");return "------testE";
}
  • http://localhost:8401/testE
4.3.3.3、sentinel配置

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

按照单机阈值,一秒钟通过一个请求,10秒后的请求作为超时处理,放弃
在这里插入图片描述

4.4、流控效果V2(并发线程数)

4.4.1、sentinel配置

在这里插入图片描述

4.4.2、Jmeter模拟多个线程并发 + 循环请求

在这里插入图片描述

  • http://localhost:8401/testB
    • Jmeter给它打满了,大部分我们自己访问都不好使,偶尔Jmeter线程切换系统判定没访问,我们自己的点击才有机会 在这里插入图片描述

5、熔断规则

5.1、官网

https://github.com/alibaba/Sentinel/wiki/%E7%86%94%E6%96%AD%E9%99%8D%E7%BA%A7

  • 基本介绍
    • Sentinel主要提供了三个熔断策略
      在这里插入图片描述

5.2、熔断规则实战

5.2.1、慢调用比例

5.2.1.1、是什么

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

5.2.1.2、名词解释

进入熔断状态判断依据:在统计时长内,实际请求数目>设定的最小请求数 且 实际慢调用比例>比例阈值 ,进入熔断状态。

在这里插入图片描述

1.调用:一个请求发送到服务器,服务器给与响应,一个响应就是一个调用。
2.最大RT:即最大的响应时间,指系统对请求作出响应的业务处理时间。
3.慢调用:处理业务逻辑的实际时间 > 设置的最大RT时间,这个调用叫做慢调用。
4.慢调用比例:在所以调用中,慢调用占有实际的比例=慢调用次数➗总调用次数
5.比例阈值:自己设定的 , 比例阈值=慢调用次数➗调用次数
6.统计时长:时间的判断依据
7.最小请求数:设置的调用最小请求数,上图比如1秒钟打进来10个线程(大于我们配置的5个了)调用被触发

5.2.1.3、触发条件 + 熔断状态

进入熔断状态判断依据:在统计时长内,实际请求数目>设定的最小请求数 且 实际慢调用比例>比例阈值 ,进入熔断状态。

在这里插入图片描述

1.熔断状态(保险丝跳闸断电,不可访问):在接下来的熔断时长内请求会自动被熔断
2.探测恢复状态(探路先锋):熔断时长结束后进入探测恢复状态
3.结束熔断(保险丝闭合恢复,可以访问):在探测恢复状态,如果接下来的一个请求响应时间小于设置的慢调用 RT,则结束熔断,否则继续熔断。

5.2.1.4、测试
  • 代码
/*** 新增熔断规则-慢调用比例** @return*/
@GetMapping("/testF")
public String testF() {//暂停几秒钟线程try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("----测试:新增熔断规则-慢调用比例 ");return "------testF 新增熔断规则-慢调用比例";
}
  • 配置
    进入熔断状态判断依据:在统计时长内,实际请求数目>设定的最小请求数 且 实际慢调用比例>比例阈值 ,进入熔断状态。
    在这里插入图片描述

  • jmeter压测
    在这里插入图片描述

  • 结论
    在这里插入图片描述
    在这里插入图片描述

按照上述配置,熔断触发:
多次循环,一秒钟打进来10个线程(大于5个了)调用/testF,我们希望200毫秒处理完一次调用,和谐系统;_
假如在统计时长内,实际请求数目>最小请求数且慢调用比例>比例阈值 ,断路器打开(保险丝跳闸)微服务不可用(Blocked by Sentinel (flow limiting)),进入熔断状态5秒;后续我停止jmeter,没有这么大的访问量了,单独用浏览器访问rest地址,断路器关闭(保险丝恢复,合上闸口),微服务恢复OK

5.2.2、异常比例

5.2.2.1、是什么

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

5.2.2.2、测试
  • 代码
/*** 新增熔断规则-异常比例** @return*/
@GetMapping("/testG")
public String testG() {System.out.println("----测试:新增熔断规则-异常比例 ");int age = 10 / 0;return "------testG,新增熔断规则-异常比例 ";
}
  • 配置

不配置Sentinel,对于int age=10/0,调一次错一次报错error,页面报【Whitelabel Error Page】或全局异常
配置Sentinel,对于int age=10/0,如符合如下异常比例启动熔断,页面报【Blocked by Sentinel (flow limiting)】

在这里插入图片描述

  • jemeter
    在这里插入图片描述
  • 结论

按照上述配置,单独访问一次,必然来一次报错一次(int age = 10/0)达到100%,调一次错一次报错error;
在这里插入图片描述

开启jmeter后,直接高并发发送请求,多次调用达到我们的配置条件了。
在这里插入图片描述

断路器开启(保险丝跳闸),微服务不可用了,不再报错error而是服务熔断+服务降级,出提示
Blocked by Sentinel (flow limiting)。
在这里插入图片描述

5.2.3、异常数

5.2.3.1、是什么

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

5.2.3.2、测试
  • 代码
/*** 新增熔断规则-异常数** @return*/
@GetMapping("/testH")
public String testH() {System.out.println("----测试:新增熔断规则-异常数 ");int age = 10 / 0;return "------testH,新增熔断规则-异常数 ";
}
  • 配置
    在这里插入图片描述

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

  • 结论

http://localhost:8401/testH,第一次访问绝对报错,因为除数不能为零,我们看到error窗口;
在这里插入图片描述

开启jmeter后,直接高并发干爆他发送请求,多次调用达到我们的配置条件了。
在这里插入图片描述

但是jmeter开工,上述配置表示,在1秒钟内最少请求2次,当异常数大于1时,会触发熔断操作断路器开启(保险丝跳闸),微服务不可用了,熔断的时长为5秒,不再报错error而是服务降级了出提示Blocked by Sentinel (flow limiting) 在这里插入图片描述

6、@SentinelResource注解

6.1、是什么

SentinelResource是一个流量防卫防护组件注解,用户指定防护资源,对配置的资源进行流量控制、熔断降级等功能。

  • @SentinelResource注解说明
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface SentinelResource {//资源名称String value() default "";//entry类型,标记流量的方向,取值IN/OUT,默认是OUTEntryType entryType() default EntryType.OUT;//资源分类int resourceType() default 0;//处理BlockException的函数名称,函数要求://1. 必须是 public//2.返回类型 参数与原方法一致//3. 默认需和原方法在同一个类中。若希望使用其他类的函数,可配置blockHandlerClass ,并指定blockHandlerClass里面的方法。String blockHandler() default "";//存放blockHandler的类,对应的处理函数必须static修饰。Class<?>[] blockHandlerClass() default {};//用于在抛出异常的时候提供fallback处理逻辑。 fallback函数可以针对所//有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。函数要求://1. 返回类型与原方法一致//2. 参数类型需要和原方法相匹配//3. 默认需和原方法在同一个类中。若希望使用其他类的函数,可配置fallbackClass ,并指定fallbackClass里面的方法。String fallback() default "";//存放fallback的类。对应的处理函数必须static修饰。String defaultFallback() default "";//用于通用的 fallback 逻辑。默认fallback函数可以针对所有类型的异常进//行处理。若同时配置了 fallback 和 defaultFallback,以fallback为准。函数要求://1. 返回类型与原方法一致//2. 方法参数列表为空,或者有一个 Throwable 类型的参数。//3. 默认需要和原方法在同一个类中。若希望使用其他类的函数,可配置fallbackClass ,并指定 fallbackClass 里面的方法。Class<?>[] fallbackClass() default {};//需要trace的异常Class<? extends Throwable>[] exceptionsToTrace() default {Throwable.class};//指定排除忽略掉哪些异常。排除的异常不会计入异常统计,也不会进入fallback逻辑,而是原样抛出。Class<? extends Throwable>[] exceptionsToIgnore() default {};
}

6.2、启动Nacos

startup.cmd -m standalone

6.3、启动Sentinel

java -jar sentinel-dashboard-1.8.6.jar

6.4、按照rest地址限流 + 默认限流返回

  • 通过访问的rest地址来限流,会返回Sentinel自带默认的限流处理信息
  • 业务类RateLimitController
package com.mui.cloud.controller;import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@Slf4j
public class RateLimitController {@GetMapping("/rateLimit/byUrl")public String byUrl() {return "按rest地址限流测试OK";}}
  • 访问一次

    • http://localhost:8401/rateLimit/byUrl
  • Sentinel控制台配置
    在这里插入图片描述

在这里插入图片描述

  • 测试
    • 疯狂点击http://localhost:8401/rateLimit/byUrl
    • 结果
      • 会返回Sentinel自带的限流处理结果,默认 在这里插入图片描述

6.5、按SentinelResource资源名称限流 + 自定义限流返回

  • 不想用默认的限流提示(Blocked by Sentinel (flow limiting)),想返回自定义限流的提示

  • 微服务cloudalibaba-sentinel-service8401

    • 业务类RateLimitController
package com.mui.cloud.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.RestController;@RestController
@Slf4j
public class RateLimitController {@GetMapping("/rateLimit/byUrl")public String byUrl() {return "按rest地址限流测试OK";}@GetMapping("/rateLimit/byResource")@SentinelResource(value = "byResourceSentinelResource", blockHandler = "handleException")public String byResource() {return "按资源名称SentinelResource限流测试OK";}public String handleException(BlockException exception) {return "服务不可用@SentinelResource启动" + "\t" + "o(╥﹏╥)o";}}
  • 测试地址

    • http://localhost:8401/rateLimit/byResource
  • 配置流控规则

    • 配置步骤在这里插入图片描述

    • 图像配置和代码关系在这里插入图片描述

  • 测试

    • 1秒钟点击1下,OK
    • 超过上述,疯狂点击,返回了自定义的限流处理信息,限流发生
      • sentinel默认在这里插入图片描述

      • 自定义限流提示在这里插入图片描述

6.6、按SentinelResource资源名称限流 + 自定义限流返回 + 服务降级处理

  • 按SentinelResource配置,点击超过限流配置返回自定义限流提示 + 程序异常返回fallback服务降级
  • 微服务cloudalibaba-sentinel-service8401
    • 业务类RateLimitController
@GetMapping("/rateLimit/doAction/{p1}")
@SentinelResource(value = "doActionSentinelResource",blockHandler = "doActionBlockHandler", fallback = "doActionFallback")
public String doAction(@PathVariable("p1") Integer p1) {if (p1 == 0){throw new RuntimeException("p1等于零直接异常");}return "doAction";
}public String doActionBlockHandler(@PathVariable("p1") Integer p1,BlockException e){log.error("sentinel配置自定义限流了:{}", e);return "sentinel配置自定义限流了";
}public String doActionFallback(@PathVariable("p1") Integer p1,Throwable e){log.error("程序逻辑异常了:{}", e);return "程序逻辑异常了"+"\t"+e.getMessage();
}
  • http://localhost:8401/rateLimit/doAction/2

  • 配置流控规则

    • 图像配置和代码关系在这里插入图片描述在这里插入图片描述

    • 表示1秒钟内查询次数大于1,就跑到我们自定义的处流,限流

  • 测试

    • http://localhost:8401/rateLimit/doAction/2

    • 1秒钟点击1下,OK

    • 超过上述,疯狂点击,返回了自定义的限流处理信息,限流发生,配合了sentinel设定的规则在这里插入图片描述

    • http://localhost:8401/rateLimit/doAction/0在这里插入图片描述

    • p1参数为零,异常发生,返回了自定义的服务降级处理

    • 小结

      • blockHandler,主要针对sentinel配置后出现的违规情况处理
      • fallback,程序异常JVM抛出的异常服务降级
      • 两者可以同时共存

7、热点规则

7.1、基本介绍

是什么?何为热点
热点即经常访问的数据,很多时候我们希望统计或者限制某个热点数据中访问频次最高的TopN数据,并对其访问进行限流或者其它操作在这里插入图片描述

7.2、官网

https://github.com/alibaba/Sentinel/wiki/%E7%83%AD%E7%82%B9%E5%8F%82%E6%95%B0%E9%99%90%E6%B5%81

7.3、代码

@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey", blockHandler = "dealHandler_testHotKey")
public String testHotKey(@RequestParam(value = "p1", required = false) String p1, @RequestParam(value = "p2", required = false) String p2) {return "---------------testHotKey";
}public String dealHandler_testHotKey(String p1, String p2, BlockException exception) {return "---------------dealHandler_testHotKey";
}

7.4、配置

在这里插入图片描述

限流模式只支持QPS模式,固定写死了。(这才叫热点)
@SentinelResource注解的方法参数索引,0代表第一个参数,1代表第二个参数,以此类推
单机阀值以及统计窗口时长表示在此窗口时间超过阀值就限流。
上面的抓图就是第一个参数有值的话,1秒的QPS为1,超过就限流,限流后调用dealHandler_testHotKey支持方法。

  • 方法testHotKey里面第一个参数P1只要QPS超过每秒1次,马上降级处理
  • http://localhost:8401/testHotKey

7.5、测试

  • error

    • http://localhost:8401/testHotKey?p1=abc在这里插入图片描述

    • 含有参数P1,当每秒访问的频率超过1次时,会触发Sentinel的限流操作

  • error

    • http://localhost:8401/testHotKey?p1=abc&p2=11在这里插入图片描述

    • 含有参数P1,当每秒访问的频率超过1次时,会触发Sentinel的限流操作

  • right

    • http://localhost:8401/testHotKey?p2=abc
      在这里插入图片描述
    • 没有热点参数P1,不断访问则不会触发限流操作

7.6、参数例外项

  • 上述案例演示了第一个参数p1,当QPS超过1秒1次点击后马上被限流

  • 特例情况

    • 普通正常限流
      • 含有P1参数,超过1秒钟一个后,达到阈值1后马上被限流
    • 例外特殊限流
      • 我们期望p1参数当它时某个特殊值时,到达某个约定值后【普通正常限流】规则突然例外、失效了,它的限流值和平时不一样
      • 例如当p1的值等于5时,它的阈值可以达到200或其他值
  • 配置在这里插入图片描述
    在这里插入图片描述

    • 添加按钮不能忘记了
  • 测试

    • http://localhost:8401/testHotKey?p1=5
      • 超过1秒钟一个后,达到阈值200后才会被限流
      • 当p1等于5的时候,阈值变为200
    • http://localhost:8401/testHotKey?p1=3
      • 超过1秒钟一个后,达到阈值后马上被限流
      • 当p1不等于5的时候,阈值就是平常的【普通正常限流】规则
  • 前提条件

    • 热点参数的注意点,参数必须是基本类型或者String

8、授权规则

8.1、授权规则概述

在某些场景下,需要根据调用接口的来源判断是否允许执行本次请求。此时就可以使用Sentinel提供的授权规则来实现,Sentinel的授权规则能够根据请求的来源判断是否允许本次请求通过。

在Sentinel的授权规则中,提供了 白名单与黑名单 两种授权类型。白放行、黑禁止

8.2、官网

https://github.com/alibaba/Sentinel/wiki/%E9%BB%91%E7%99%BD%E5%90%8D%E5%8D%95%E6%8E%A7%E5%88%B6

8.3、演示授权规则,黑名单禁止

  • 代码
    • EmpowerController
package com.mui.cloud.controller;import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@Slf4j
public class EmpowerController {@GetMapping(value = "/empower")public String requestSentinel4(){log.info("测试Sentinel授权规则empower");return "Sentinel授权规则";}}
  • MyRequestOriginParser
package com.mui.cloud.handler;import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;@Component
public class MyRequestOriginParser implements RequestOriginParser {@Overridepublic String parseOrigin(HttpServletRequest httpServletRequest) {return httpServletRequest.getParameter("serverName");}}
  • 启动8401后先访问成功
  • http://localhost:8401/empower

8.4、配置

在这里插入图片描述

8.5、测试

  • error

    • http://localhost:8401/empower?serverName=test
      在这里插入图片描述
  • error

    • http://localhost:8401/empower?serverName=test2
      在这里插入图片描述
  • 说明

    • 不断在浏览器中刷新http://localhost:8401/empower?serverName=test
    • 不断在浏览器中刷新http://localhost:8401/empower?serverName=test2
    • 上述2个rest地址,serverName=test或serverName=test2是处于黑名单的状态,无法访问,会发现无法访问,被Sentinel限流了
  • right

    • http://localhost:8401/empower?serverName=abc

9、规则持久化

9.1、是什么

一旦我们重启微服务应用,sentinel规则将消失,生产环境需要将配置规则进行持久化

9.2、怎么玩

将限流配置规则持久化进Nacos保存,只要刷新8401某个rest地址,sentinel控制台的流控规则就能看到,只要Nacos里面的配置不删除,针对8401上sentinel上的流控规则持续有效

9.3、步骤

  • 修改cloudalibaba-sentinel-service8401

9.3.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"><modelVersion>4.0.0</modelVersion><parent><groupId>com.mui.cloud</groupId><artifactId>cloud2024</artifactId><version>1.0-SNAPSHOT</version></parent><groupId>com.mui.cloud</groupId><artifactId>cloudalibaba-sentinel-service8401</artifactId><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!--SpringCloud ailibaba sentinel-datasource-nacos --><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId></dependency><!--SpringCloud alibaba sentinel --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency><!--nacos-discovery--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!-- 引入自己定义的api通用包 --><dependency><groupId>com.dashun.cloud</groupId><artifactId>cloud-api-commons</artifactId><version>1.0-SNAPSHOT</version></dependency><!--SpringBoot通用依赖模块--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--hutool--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId></dependency><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.28</version><scope>provided</scope></dependency><!--test--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

9.3.2、YML

server:port: 8401spring:application:name: cloudalibaba-sentinel-servicecloud:nacos:discovery:server-addr: localhost:8848         # Nacos服务注册中心地址sentinel:transport:dashboard: localhost:8080 # 配置Sentinel dashboard控制台服务地址port: 8719 # 默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口web-context-unify: false # controller层的方法对service层调用不认为是同一个根链路datasource:ds1:nacos:server-addr: localhost:8848dataId: ${spring.application.name}groupId: DEFAULT_GROUPdata-type: jsonrule-type: flow # com.alibaba.cloud.sentinel.datasource.RuleType
9.3.2.1、添加Nacos数据源配置
spring:cloud:sentinel:datasource:ds1: nacos:server-addr: localhost:8848dataId: ${spring.application.name}groupId: DEFAULT_GROUPdata-type: jsonrule-type: flow
# 备注:rule-type是什么?看看源码
9.3.2.2、源代码

在这里插入图片描述

9.3.2.3、进一步说明

在这里插入图片描述

9.3.3、添加Nacos业务规则配置

在这里插入图片描述

9.3.3.1、内容解析
[{"resource": "/rateLimit/byUrl","limitApp": "default","grade": 1,"count": 1,"strategy": 0,"controlBehavior": 0,"clusterMode": false}
]

resource:资源名称;
limitApp:来源应用;
grade:阈值类型,0表示线程数,1表示QPS;
count:单机阈值;
strategy:流控模式,0表示直接,1表示关联,2表示链路;
controlBehavior:流控效果,0表示快速失败,1表示Warm Up,2表示排队等待;
clusterMode:是否集群。

9.3.4、快速访问测试接口
  • http://localhost:8401/rateLimit/byUrl
  • 上面地址访问后等待3秒
  • 启动8401后刷新sentinel发现业务规则有了
  • 默认在这里插入图片描述

9.3.5、停止8401再看sentinel

在这里插入图片描述

9.3.6、重新启动8401再看sentinel

  • 乍一看还是没有,稍等一会
  • 多次调用
    • http://localhost:8401/rateLimit/byUrl
      -重新配置出现了,持久化验证成功

相关文章:

15、Spring Cloud Alibaba Sentinel实现熔断与限流

注&#xff1a;本篇文章主要参考周阳老师讲解的cloud进行整理的&#xff01; 1、Sentinel 1.1、官网 https://sentinelguard.io/zh-cn/ 等价对标 Spring Cloud Circuit Breaker 1.2、是什么 https://github.com/alibaba/Sentinel/wiki 1.3、去哪下 https://github.com/alibab…...

Linux logout命令教程:如何安全地退出Linux会话(附实例详解和注意事项)

Linux logout命令介绍 logout命令用于退出当前的登录Shell。这个命令可以被普通用户用来结束他们自己的会话。 Linux logout命令适用的Linux版本 logout命令在所有主流的Linux发行版中都是可用的&#xff0c;包括但不限于Debian、Ubuntu、Alpine、Arch Linux、Kali Linux、R…...

数据结构——顺序表(C语言版)

顺序表是数据结构中最基本的一种线性表&#xff0c;它以一段连续的存储空间来存储数据元素&#xff0c;元素之间的顺序由它们在内存中的位置来决定。在C语言中&#xff0c;我们通常使用数组来实现顺序表。 目录 顺序表的结构定义 顺序表的基本操作 应用实例 顺序表的结构定义…...

Knative 助力 XTransfer 加速应用云原生 Serverless 化

作者&#xff1a;元毅 公司介绍 XTransfer 是一站式外贸企业跨境金融和风控服务公司&#xff0c;致力于帮助中小微企业大幅降低全球展业的门槛和成本&#xff0c;提升全球竞争力。公司连续7年专注 B2B 外贸金融服务&#xff0c;已成为中国 B2B 外贸金融第一平台&#xff0c;目…...

服务器离线配置vscode连接,conda虚拟环境

记录一下服务器离线配置问题&#xff0c;以备不时之需。 服务器离线配置 vscode连接参考&#xff1a;vscode-server离线安装-CSDN博客 服务器离线配置conda虚拟环境&#xff1a;Conda 环境离线迁移&#xff08;服务器断网情况下搭建虚拟环境envs&#xff09; - 知乎 上次两个…...

各种需要使用的方法-->vue/微信小程序/layui

各种需要使用的方法-->vue/微信小程序/layui 1、vue里样式不起作用的方法&#xff0c;可以通过deep穿透的方式2、 js获取本周、上周、本月、上月日期3、ArrayBuffer Blob 格式转换ArrayBuffer与Blob的区别ArrayBuffer转BlobBlob转ArrayBuffer需要借助fileReader对象 4、使用…...

360奇酷刷机 360刷机助手 QGDP360手机QGDP刷机

360奇酷刷机 360刷机助手 QGDP破解版360手机QGDP刷机 360手机刷机资源下载链接&#xff1a;360rom.github.io 参考&#xff1a;360手机-360刷机360刷机包twrp、root 360奇酷刷机&#xff1a;360高通驱动安装 360手机刷机驱动&#xff1b;手机内置&#xff0c;可通过USB文件传输…...

2299. 强密码检验器 II

文章目录 题意思路代码 题意 题目链接 判断是否合法密码 思路 if 代码 class Solution { public:bool strongPasswordCheckerII(string password) {if (password.size() < 8)return false;int visit 0;for (size_t i 0; i < password.size(); i){char &ch pa…...

跟着cherno手搓游戏引擎【29】Batch简单合批

思路&#xff1a; CPU和GPU都开辟同样大小的一大块内存&#xff08;为了存储顶点信息&#xff09; 索引在程序运行时生成对应规则后绑定到索引缓冲中 动态生成顶点信息&#xff08;现在改成Drawquad只是确定图形顶点的位置&#xff09; 然后在Endscene&#xff0c;将CPU的动…...

粘包/半包及解决方案

一、粘包/半包介绍 1&#xff1a;粘包 粘包&#xff08;Packet Concatenation&#xff09;通常发生在基于流式传输协议&#xff08;如 TCP&#xff09;的通信中&#xff0c;因为 TCP 是面向流的传输协议&#xff0c;它不保证数据包的边界&#xff0c;而是将数据视为连续的字节…...

2024华为软件精英挑战赛记录

前言 本次主要是记录自己第一次参加华为软件挑战赛的经历。第一次参加比赛还是缺少经验&#xff0c;训练赛中拿到赛区的20多名&#xff0c;最后在正式赛中被反超了&#xff0c;只拿了40多名&#xff0c;实在是感到可惜。 题目&#xff1a;本次题目是一个智慧港口的问题。10个机…...

数据可视化艺术:Matplotlib与Seaborn实战

目录 1.Matplotlib基础绘图与定制化 1.1. 基础绘图 1.2. 定制化 2.Seaborn高级图表类型与样式设定 2.1. 高级图表类型 2.2. 样式设定 3.实战&#xff1a;绘制多维度数据可视化报告 4.总结 1. 前言 在数据科学领域&#xff0c;数据可视化扮演着至关重要的角色。通过图形化…...

python初级第一次作业

一、 dayint(input("enter today day")) fdayint(input("enter num of day since today")) c((fday%7)day)%7 if c0:print("sunday") elif c1:print("monday") elif c2:print("tuesday") elif c3:print("wendnsday&quo…...

Spring Boot整合Camunda打造高效工作流程

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是尘缘&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f449;点击这里&#xff0c;就可以查看我的主页啦&#xff01;&#x1f447;&#x…...

2.8、下拉刷新与上拉加载

页面的下拉刷新与上拉加载功能在移动应用中十分常见,例如,新闻页面的内容刷新和加载。这两种操作的原理都是通过响应用户的触摸事件,在顶部或者底部显示一个刷新或加载视图,完成后再将此视图隐藏。 实现思路 以下拉刷新为例,其实现主要分成三步: 监听手指按下事件,记录…...

java Web餐馆订单管理系统用eclipse定制开发mysql数据库BS模式java编程jdbc

一、源码特点 JSP 餐馆订单管理系统是一套完善的web设计系统&#xff0c;对理解JSP java 编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,eclipse开发&#xff0c;数据库为Mysql5.0&#xff0c;使…...

小程序从入门到入坑:事件系统

前言 哈喽大家好&#xff0c;我是 SuperYing&#xff0c;本文是小程序从入门到入坑系列的第 3 篇&#xff0c;将比较详尽的讲解 小程序事件系统 的相关知识点&#xff0c;欢迎小伙伴阅读。 读完本文您将收获&#xff1a; 了解小程序事件及基础使用。了解小程序事件分类及多种的…...

Windows蓝牙驱动开发之模拟HID设备(二)(把Windows电脑模拟成蓝牙鼠标和蓝牙键盘等设备)

by fanxiushu 2024-03-24 转载或引用请注明原作者 接上文,当我们建立了蓝牙链接请求之后,就该传输数据了, 其实传输数据比起上章阐述的创建SDP和建立连接要简单许多。 使用类型 BRB_L2CA_ACL_TRANSFER 的BRB请求,就可以实现接收和发送操作, 至于具体是接收还是发送,根据设…...

快速区分清楚图形渲染中的AABB,KD树和BVH这些概念

快速区分清楚图形渲染中的AABB&#xff0c;KD树和BVH这些概念 主要想形象去区分好这些术语&#xff0c;目的是扫盲&#xff0c;先开好坑&#xff0c;内容持续填充。 0.先摆出这些词的全称 AABB&#xff1a; 原名&#xff1a;axis aligned bounding box&#xff1b;中文直译名…...

Rust 的 HashMap 特定键值元素值的累加方法

在Rust中&#xff0c;如果你想要对HashMap中特定键对应的值进行累加操作&#xff0c;你需要首先检查该键是否已存在。如果存在&#xff0c;则取出其值&#xff0c;进行累加&#xff0c;然后将结果存回HashMap。如果不存在&#xff0c;则可能需要插入一个新的键值对&#xff0c;…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

腾讯云V3签名

想要接入腾讯云的Api&#xff0c;必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口&#xff0c;但总是卡在签名这一步&#xff0c;最后放弃选择SDK&#xff0c;这次终于自己代码实现。 可能腾讯云翻新了接口文档&#xff0c;现在阅读起来&#xff0c;清晰了很多&…...

探索Selenium:自动化测试的神奇钥匙

目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...

使用SSE解决获取状态不一致问题

使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件&#xff0c;这个上传文件是整体功能的一部分&#xff0c;文件在上传的过程中…...

零基础在实践中学习网络安全-皮卡丘靶场(第十一期-目录遍历模块)

经过前面几期的内容我们学习了很多网络安全的知识&#xff0c;而这期内容就涉及到了前面的第六期-RCE模块&#xff0c;第七期-File inclusion模块&#xff0c;第八期-Unsafe Filedownload模块。 什么是"遍历"呢&#xff1a;对学过一些开发语言的朋友来说应该知道&…...