SpringCloud框架学习(第六部分:Sentinel实现熔断与限流)

目录

十四、SpringCloud Alibaba Sentinel实现熔断与限流

1.简介

 2.作用

3.下载安装

4.微服务 8401 整合 Sentinel 入门案例

5.流控规则

(1)基本介绍

(2)流控模式

Ⅰ. 直接

Ⅱ. 关联

Ⅲ. 链路 

(3) 流控效果

Ⅰ. 直接

Ⅱ. 预热WarmUp

Ⅲ. 排队等待 

Ⅳ. 并发线程数

 6.熔断规则

(1)慢调用比例 

(2)异常比例

(3)异常数 

7.@SentinelResource注解

(1)介绍

(2)实战

Ⅰ. 按照rest地址限流 + 默认限流返回 

Ⅱ. 按SentinelResource​资源名称限流 + 自定义限流返回

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

8.热点规则

(1)介绍

(2) 实战

Ⅰ. 常规情况

Ⅱ. 特殊情况(参数例外项)

9.授权规则

10.规则持久化 

11.OpenFeign和Sentinel集成实现fallback服务降级

(1)需求说明

(2)编码步骤

Ⅰ. 修改服务提供方cloudalibaba-provider-payment9001

 Ⅱ. 修改cloud-api-commons

Ⅲ. 修改cloudalibaba-consumer-nacos-order83

(3)测试验证

12.GateWay和Sentinel集成实现服务限流

(1)需求说明

(2)编码步骤


十四、SpringCloud Alibaba Sentinel实现熔断与限流

1.简介

官网:home | Sentinel

等价于 Spring Cloud Circuit Breaker

 2.作用

丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。

完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。

广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Apache Dubbo、gRPC、Quarkus 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。同时 Sentinel 提供 Java/Go/C++ 等多语言的原生实现。

完善的 SPI 扩展机制:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。

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

3.下载安装

下载地址: Releases · alibaba/Sentinel

 Sentinel 组件由两部分组成,后台默认端口:8719,前台默认端口:8080 

 所以,启动时千万要注意,8080 端口不能被占用!

安装目录打开 cmd 窗口,运行命令:java -jar sentinel-dashboard-1.8.8.jar

访问 sentinel 管理界面:http://localhost:8080(登录账号密码均为 sentinel)

4.微服务 8401 整合 Sentinel 入门案例

步骤:

Ⅰ. 启动 Nacos8848 成功

命令:startup.cmd -m standalone

网址:http://localhost:8848/nacos/#/login

Ⅱ. 启动Sentinel8080成功

Ⅲ. 新建微服务8401(将被哨兵纳入管控的   8401微服务提供者)

① 新建 module(cloudalibaba-sentinel-service8401

② 导入依赖

    <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.mihoyo.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>

③ 修改 application.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扫描,直至找到未被占用的端口

④ 修改主启动类

@EnableDiscoveryClient
@SpringBootApplication
public class Main8401
{public static void main(String[] args){SpringApplication.run(Main8401.class,args);}
}

⑤ 编写业务类(FlowLimitController)

@RestController
public class FlowLimitController
{@GetMapping("/testA")public String testA(){return "------testA";}@GetMapping("/testB")public String testB(){return "------testB";}
}

⑥ 启动微服务 8401 并访问

 Ⅳ. 启动 8401 微服务后查看 sentienl 控制台

一开始,控制台是空的:

Sentinel采用的懒加载说明:

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

访问地址:

http://localhost:8401/testA

http://localhost:8401/testB

访问后,sentinel 控制台效果:

5.流控规则

(1)基本介绍

Sentinel 能够对流量进行控制,主要是监控应用的 QPS 流量或者并发线程数等指标,如果达到指定的阈值时,就会被流量进行控制,以避免服务被瞬时的高并发流量击垮,保证服务的高可靠性。

参数如下:

1
资源名
资源的唯一名称,默认就是请求的接口路径,可以自行修改,但是要保证唯一。
2
针对来源
具体针对某个微服务进行限流,默认值为default,表示不区分来源,全部限流。
3
阈值类型
QPS表示通过QPS进行限流,并发线程数表示通过并发线程数限流。
4
单机阈值
与阈值类型组合使用。如果阈值类型选择的是QPS,表示当调用接口的QPS达到阈值时,进行限流操作。如果阈值类型选择的是并发线程数,则表示当调用接口的并发线程数达到阈值时,进行限流操作。
5
是否集群
选中则表示集群环境,不选中则表示非集群环境。

(2)流控模式

Ⅰ. 直接

说明:默认的流控模式是,当接口达到限流条件时,直接开启限流功能。

配置说明:表示 1 秒钟内查询 2 次就是OK,若超过次数 2,就直接 - 快速失败,报默认错误

测试:快速点击访问 http://localhost:8401/testA

当 1 秒钟点击超过 2次,就会触发限流! 

但是,直接显示报错信息并不是我们想要的,我们需要通过一个 fallback 方法进行服务降级。

Ⅱ. 关联

说明:当关联的资源达到阈值时,就限流自己 --> 当与 A 关联的资源 B 达到阀值后,就限流A 自己(B惹事,A挂了)

配置说明:当关联资源 /testB 的 qps 阀值超过 1 时,就限流 /testA 的 Rest 访问地址

                (当关联资源到阈值后限制配置好的资源名,B惹事,A挂了)

 使用 Jmeter 模拟并发密集访问 testB:

执行 1 次,4s 内发 80 个请求 

正常情况下,testA正常访问:

打开 JMeter,让大批量线程高并发访问 testB

此时再访问被关联的 testA,就会触发限流

Ⅲ. 链路 

说明:来自不同链路的请求对同一个目标访问时,实施针对性的不同限流措施

        (比如 C 请求来访问就限流,D 请求来访问就是 OK)

准备:

① 新建 FlowLimitService

@Service
public class FlowLimitService
{@SentinelResource(value = "common")public void common(){System.out.println("------FlowLimitService come in");}
}

 注意:@SentinelResource注解后续将会详细介绍

② 修改 FlowLimitController

@RestController
public class FlowLimitController
{@GetMapping("/testA")public String testA(){return "------testA";}@GetMapping("/testB")public String testB(){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";}
}

③ 修改 application.yml

server:
  port8401

spring:
  application:
    name: cloudalibaba-sentinel-service #8401微服务提供者后续将会被纳入阿里巴巴sentinel监管
  
cloud:
    nacos:
      discovery:
        server-addr: localhost:8848         #Nacos服务注册中心地址
    
sentinel:
      transport:
        dashboard: localhost:8080 #配置Sentinel dashboard控制台服务地址
                
port: 8719 #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
            
web-context-unifyfalse # controller层的方法对service层调用不认为是同一个根链路

细节:

web-context-unify表示上下文的隔离性。当它设置为 false 之后,表示每个请求的上下文都是独立的。因此,虽然 testC 和 testD 调用(共享)同一个 service 方法,但在 Sentinel 的监控和流量控制下,每一个请求都是独立的!所以如果某一请求的负载过大,Sentinel 只会对该请求的上下文进行限流,而不会影响到其他请求。

web-context-unify: true 结果如下:

web-context-unify: false 结果如下:

配置说明:当 common 方法由 testC 链路调用,qps 阀值超过 1 时,就触发限流

此时,每秒访问一次 testC 和 testD 都是正常的。

但是,如果 testC 每秒超过一次,就会触发限流,但 testD 不会!

抛出的异常被全局异常捕捉机制捕捉到! 

(3) 流控效果

Ⅰ. 直接

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

Ⅱ. 预热WarmUp

限流 / 冷启动:

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

源码:

 配置说明:

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

案例:

单机阈值为 10,预热时长设置 5 秒。

系统初始化的阈值为 10 / 3 约等于 3,即单机阈值刚开始为 3(我们人工设定单机阈值是 10,sentinel计算后QPS 判定为 3 开始);
然后过了 5 秒后阀值才慢慢升高恢复到设置的单机阈值 10。

此时,testB 的访问结果如下: 

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

Ⅲ. 排队等待 

修改 FlowLimitController:

@RestController
public class FlowLimitController
{...//流控效果--排队等待@GetMapping("/testE")public String testE(){System.out.println(System.currentTimeMillis()+"      testE,排队等待");return "------testE";}
}

配置说明:按照单机阈值,一秒钟通过一个请求,10 秒后的请求作为超时处理,放弃

 打开 JMeter 进行测试,1s 内向 testE 发送 20 个请求

 细节:这里接收了 11 个请求,因为会有一定时间上的误差,让第 11 个请求挤了进来。

Ⅳ. 并发线程数

配置说明:testB 的并发数量仅为 1,其余的请求只能等待线程结束,再抢占线程

 打开 JMeter 进行测试,100 个线程同时访问 testB,无限下去

此时,这 100 个线程不断循环往复的去访问 testB,也就是唯一的那 1 个并发线程,几乎一直处于被抢占状态。

这时,如果我们浏览器访问 testB,基本上是打不开的,因为抢不到线程。

当然,也有极小概率刚好抢到这唯一的线程,但极大可能是抢不到的! 

 6.熔断规则

Sentinel 熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,

让请求快速失败,避免影响到其它的资源而导致级联错误。当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出 DegradeException)。

(1)慢调用比例 

举例: 

效果:

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

名词解释
1调用一个请求发送到服务器,服务器给与响应,一个响应就是一个调用。
2最大RT即最大的响应时间,指系统对请求作出响应的业务处理时间。
3慢调用处理业务逻辑的实际时间 > 设置的最大RT时间,这个调用叫做慢调用。
4慢调用比例在所以调用中,慢调用占有实际的比例=慢调用次数➗总调用次数
5比例阈值自己设定的 , 比例阈值 = 慢调用次数➗调用次数
6统计时长时间的判断依据
7最小请求数设置的调用最小请求数,上图比如 1 秒钟打进来 10 个线程(大于我们配置的 5 个了)调用被触发
熔断状态
1熔断状态(保险丝跳闸断电,不可访问)在接下来的熔断时长内请求会自动被熔断
2探测恢复状态(探路先锋)熔断时长结束后进入探测恢复状态
3结束熔断(保险丝闭合恢复,可以访问)在探测恢复状态,如果接下来的一个请求响应时间小于设置的慢调用 RT,则结束熔断,否则继续熔断。

修改 FlowLimitController:

@RestController
public class FlowLimitController
{...//新增熔断规则-慢调用比例@GetMapping("/testF")public String testF(){//暂停几秒钟线程try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }System.out.println("----测试:新增熔断规则-慢调用比例 ");return "------testF 新增熔断规则-慢调用比例";}
}

说明:

10 个线程,在 1s 内发送完。又因为服务器响应时长设置:暂停 1s,而 RT = 200ms,所以响应一个请求的时长都大于 1s。

综上,符合熔断条件,所以当线程开启1秒后,进入熔断状态!

 配置:

  打开 JMeter 进行测试,1s 内 10个线程访问 testF,使之触发熔断状态

此时,浏览器访问 testF,必然访问失败

解释:

多次循环,一秒钟打进来10个线程(大于 5 个了)调用 /testF,我们希望 200 毫秒处理完一次调用,和谐系统;

因为在统计时长内,实际请求数目>最小请求数   且  慢调用比例>比例阈值 ,断路器打开(保险丝跳闸)微服务不可用(Blocked by Sentinel (flow limiting)),进入熔断状态 5 秒;

后续我们停止 jmeter,没有这么大的访问量了,单独用浏览器访问 rest 地址,断路器关闭(保险丝恢复,合上闸口),微服务恢复OK

(2)异常比例

举例:

 效果:

 修改 FlowLimitController:

@RestController
public class FlowLimitController
{...//新增熔断规则-异常比例@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)】

注意:为了能够更好的展示效果,务必关闭全局异常处理

否则普通异常和熔断异常显示的页面都一样,如下:

配置:

 打开 JMeter 进行测试,1s 内 20 个线程访问 testG,使之触发熔断状态

此时,浏览器访问 testG,触发熔断异常

(3)异常数 

举例: 

效果:

  修改 FlowLimitController:

@RestController
public class FlowLimitController
{...//新增熔断规则-异常数@GetMapping("/testH")public String testH(){System.out.println("----测试:新增熔断规则-异常数 ");int age = 10/0;return "------testH,新增熔断规则-异常数 ";}
}

正常访问:

配置说明:1s 内最小请求数为 5,只要有 1 次异常,就会触发熔断状态

打开 JMeter 进行测试,1s 内 20 个线程访问 testH,使之触发熔断状态

 此时,浏览器访问 testH,触发熔断异常

7.@SentinelResource注解

(1)介绍

@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 {};
}

(2)实战

在使用 @SentinelResource 注解之前,请确保 nacos 和 sentinel 均已启动成功。

Ⅰ. 按照rest地址限流 + 默认限流返回 

说明:通过访问的 rest 地址来限流,会返回 Sentinel 自带默认的限流处理信息

步骤:

① 新增业务类RateLimitController

@RestController
@Slf4j
public class RateLimitController
{@GetMapping("/rateLimit/byUrl")public String byUrl(){return "按rest地址限流测试OK";}
}

② 访问地址:http://localhost:8401/rateLimit/byUrl,让其在 sentinel 中检测到

③ Sentinel控制台配置 

 此时,浏览器疯狂刷新,访问:http://localhost:8401/rateLimit/byUrl

结果:会返回 Sentinel 自带的限流处理结果,默认 

解释:

虽然我们的 rest 方法没有加 @SentinelResource 注解,但由于其 Rest 地址是唯一的,所以也可以触发 Sentinel 的限流

Ⅱ. 按SentinelResource​资源名称限流 + 自定义限流返回

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

步骤:

① 修改业务类RateLimitController

@RestController
@Slf4j
public class RateLimitController
{...@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,让其在 sentinel 中检测到

 ③ Sentinel 控制台配置 

 关系说明:

此时,浏览器疯狂刷新,访问:http://localhost:8401/rateLimit/byResource

结果:返回了自定义的限流处理信息,限流发生

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

说明:按SentinelResource配置,点击超过限流配置返回自定义限流提示+程序异常返回fallback服务降级

 步骤:

① 修改业务类 RateLimitController

@RestController
@Slf4j
public class 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();}
}

注意:blockHander 方法 和 fallback 方法的形参要包含源 rest方法的所有参数

 ② 访问地址:http://localhost:8401/rateLimit/doAction/2,让其在 sentinel 中检测到

 ③ Sentinel 控制台配置 

  关系说明:

Question:blockHander 方法 和 fallback 方法都是兜底方法?会不会冲突呢?

浏览器疯狂刷新,访问:http://localhost:8401/rateLimit/doAction/2

返回了自定义的限流处理信息(blockHander 方法)限流发生 

这是否意味着 fallback 方法无效?两者冲突了?

别急,我们访问地址: http://localhost:8401/rateLimit/doAction/0

我们发现,异常发生,返回了自定义的服务降级处理(fallback 方法)!

总结:

blockHander 方法 和 fallback 方法两者可以共存!

  • blockHander 方法:主要针对 sentinel 配置后出现的违规情况处理
  • fallback方法:程序异常了,JVM 抛出的异常服务降级

8.热点规则

(1)介绍

热点:即经常访问的数据,很多时候我们希望统计或者限制某个热点数据中访问频次最高的TopN数据,并对其访问进行限流或者其它操作。

(2) 实战

Ⅰ. 常规情况

 步骤:

① 修改业务类 RateLimitController

@RestController
@Slf4j
public class RateLimitController
{...@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";}
}

 ② 访问地址:http://localhost:8401/testHotKey,让其在 sentinel 中检测到

③ Sentinel 控制台配置 

关系说明: 

 限流模式只支持QPS模式,固定写死了。(这才叫热点)

@SentinelResource 注解的方法参数索引,0 代表第一个参数,1 代表第二个参数,以此类推。

单机阀值以及统计窗口时长表示在此窗口时间超过阀值就限流。

上面的图表示:第一个参数 p1 有值的话,只要 QPS 超过 1 秒内 1次,就马上限流,限流后调用 dealHandler_testHotKey 方法。

④ 测试:

error:http://localhost:8401/testHotKey?p1=abc

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

 error:http://localhost:8401/testHotKey?p1=abc&p2=33

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

right:http://localhost:8401/testHotKey?p2=33

没有热点参数P1,不断访问则不会触发限流操作

Ⅱ. 特殊情况(参数例外项)

普通正常限流:

含有 P1 参数,超过1秒钟一个后,达到阈值 1 后马上被限流

例外特殊限流:

我们期望 p1 参数,当它是某个特殊值时(到达某个约定值后),【普通正常限流】规则突然例外(失效了),它的限流值和平时不一样

(假如当 p1 的值等于 5 时,它的阈值可以达到 200 或其它值)

配置:

注意:

① 添加按钮不能忘记点!!! 

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


测试:

 error:http://localhost:8401/testHotKey?p1=3

超过1秒钟一个后,达到阈值后马上被限流

right:http://localhost:8401/testHotKey?p1=5

超过1秒钟一个后,达到阈值 200 后才会被限流

效果:

  • 当p1等于5的时候,阈值变为200
  • 当p1不等于5的时候,阈值就是平常的【普通正常限流】规则

9.授权规则

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

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

步骤:

① 新建业务类 EmpowerController 

@RestController
@Slf4j
public class EmpowerController //Empower授权规则,用来处理请求的来源
{@GetMapping(value = "/empower")public String requestSentinel4(){log.info("测试Sentinel授权规则empower");return "Sentinel授权规则";}
}

② 新建 MyRequestOriginParser 类,用于定义放行规则

@Component
public class MyRequestOriginParser implements RequestOriginParser
{@Overridepublic String parseOrigin(HttpServletRequest httpServletRequest) {return httpServletRequest.getParameter("serverName");}
}

细节:

MyRequestOriginParser 类实现了 RequestOriginParser 接口

 我们通过重写 parseOrigin 方法,告诉资源地址,我们发送的请求需要携带什么参数(serverName),再通过后续的 sentinel 配置,设置哪些值为白名单,哪些值为黑名单。

③ 访问地址:http://localhost:8401/empower,让其在 sentinel 中检测到

④ Sentinel 控制台配置 

我们设置了黑名单为:test1 和 test2

也就是,当请求传入的参数有 serverName,且它的值为 test1 或 test2 时,禁止访问!

如果不带 serverName 参数,或者它的值为其他值时,放行。

⑤ 测试

error:http://localhost:8401/empower?serverName=test1

error:http://localhost:8401/empower?serverName=test2

 right:http://localhost:8401/empower?serverName=test3

 right:http://localhost:8401/empower 

10.规则持久化 

问题:

虽然我们在 Sentinel 控制台配置了很多规则,但肯定有人已经发现:

一旦我们重启微服务应用,sentinel 规则将消失!

所以,生产环境需要将配置规则进行持久化。

解决办法:

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

步骤(修改 8401):

① 导入依赖

        <!--SpringCloud ailibaba sentinel-datasource-nacos --><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId></dependency>

② 修改 application.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

Question:rule-type是什么?看看源码

 我们现在只配置了一个流控规则,我们也可以同时配置多个规则

③ 添加 Nacos 业务规则配置 

注意:配置格式是 json,不是 yaml

参数说明:

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

④ 测试

重启 8401,访问地址:http://localhost:8401/rateLimit/byUrl

刷新 sentinel,发现新增了流控规则

这时我们停止 8401,再刷新 sentinel

我们发现刚才新增的流控规则又消失了,难道持久化失败了?

重启 8401,再度刷新 sentinel 查看

 我们发现 sentinel 中还是空空如也,难道真的失败了吗?

别急,我们访问一下地址:http://localhost:8401/rateLimit/byUrl,多刷新几次

我们发现,该 rest 地址被限流了,这说明,流控规则还在,他生效了! 

再次刷新 sentinel 查看

没错,刚才新增的流控规则又回来了,持久化验证成功!

这是因为,sentinel 采用懒加载的方式,即需要的时候才会出现,不用的时候不会打扰。

11.OpenFeign和Sentinel集成实现fallback服务降级

(1)需求说明

83   通过OpenFeign调用  9001微服务,正常访问OK

83   通过OpenFeign调用  9001微服务,异常访问error

访问者要有 fallback 服务降级的情况,不要持续访问 9001 加大微服务负担,但是通过 feign 接口调用的又方法各自不同。

如果每个不同方法都加一个fallback配对方法,会导致代码膨胀不好管理,工程埋雷

③ 9001 微服务自身还带着 sentinel 内部配置的流控规则,如果满足也会被触发。

所以,为了统一进行管理

public @interface FeignClient

通过 fallback 属性进行统一配置,feign 接口里面定义的全部方法都走统一的服务降级,一个搞定即可

即本例有 2 个Case:

  • OpenFeign 接口的统一 fallback 服务降级处理
  • Sentinel 访问触发了自定义的限流配置,在注解 @SentinelResource 里面配置的 blockHandler 方法。

(2)编码步骤

前提:nacos服务器 和 Sentinel 启动成功

Ⅰ. 修改服务提供方cloudalibaba-provider-payment9001

① 导入依赖

        <!--openfeign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!--alibaba-sentinel--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency>

② 修改 application.yml

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

 ③ 修改业务类 PayAlibabaController

@RestController
public class PayAlibabaController
{...//openfeign+sentinel进行服务降级和流量监控的整合处理case@GetMapping("/pay/nacos/get/{orderNo}")@SentinelResource(value = "getPayByOrderNo",blockHandler = "handlerBlockHandler")public ResultData getPayByOrderNo(@PathVariable("orderNo") String orderNo){//模拟从数据库查询出数据并赋值给DTOPayDTO payDTO = new PayDTO();payDTO.setId(1024);payDTO.setOrderNo(orderNo);payDTO.setAmount(BigDecimal.valueOf(9.9));payDTO.setPayNo("pay:"+ IdUtil.fastUUID());payDTO.setUserId(1);return ResultData.success("查询返回值:"+payDTO);}public ResultData handlerBlockHandler(@PathVariable("orderNo") String orderNo, BlockException exception){return ResultData.fail(ReturnCodeEnum.RC500.getCode(),"getPayByOrderNo服务不可用," +"触发sentinel流控配置规则"+"\t"+"o(╥﹏╥)o");}/*fallback服务降级方法纳入到Feign接口统一处理,全局一个public ResultData myFallBack(@PathVariable("orderNo") String orderNo,Throwable throwable){return ResultData.fail(ReturnCodeEnum.RC500.getCode(),"异常情况:"+throwable.getMessage());}*/
}

④ 启动 9001 测试,访问地址:http://localhost:9001/pay/nacos/get/ord1024

 Ⅱ. 修改cloud-api-commons

① 导入依赖(openfeign 的依赖之前已经引入过,所以只需要引入 sentinel 的依赖)

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

② 新增 PayFeignSentinelApi 接口

@FeignClient(value = "nacos-payment-provider",fallback = PayFeignSentinelApiFallBack.class)
public interface PayFeignSentinelApi
{@GetMapping("/pay/nacos/get/{orderNo}")public ResultData getPayByOrderNo(@PathVariable("orderNo") String orderNo);
}

③ 新建全局统一服务降级类(fallback =​ PayFeignSentinelApiFallBack.class)

@Component
public class PayFeignSentinelApiFallBack implements PayFeignSentinelApi
{@Overridepublic ResultData getPayByOrderNo(String orderNo){return ResultData.fail(ReturnCodeEnum.RC500.getCode(),"对方服务宕机或不可用,FallBack服务降级o(╥﹏╥)o");}
}

④ 通用 api 模块修改完成后,maven 需要刷新一下

Ⅲ. 修改cloudalibaba-consumer-nacos-order83

① 导入依赖 

        <!-- 引入自己定义的api通用包 --><dependency><groupId>com.mihoyo.cloud</groupId><artifactId>cloud-api-commons</artifactId><version>1.0-SNAPSHOT</version></dependency><!--openfeign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!--alibaba-sentinel--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency>

② 修改 application.yml

server:port: 83spring:application:name: nacos-order-consumercloud:nacos:discovery:server-addr: localhost:8848#消费者将要去访问的微服务名称(nacos微服务提供者叫什么你写什么)
service-url:nacos-user-service: http://nacos-payment-provider# 激活Sentinel对Feign的支持
feign:sentinel:enabled: true

③  修改主启动类,激活 feign 的功能

@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients    //启动feign的功能
public class Main83
{public static void main(String[] args){SpringApplication.run(Main83.class,args);}
}

④ 修改业务类 OrderNacosController

@RestController
public class OrderNacosController
{...@Resourceprivate PayFeignSentinelApi payFeignSentinelApi;@GetMapping(value = "/consumer/pay/nacos/get/{orderNo}")public ResultData getPayByOrderNo(@PathVariable("orderNo") String orderNo){return payFeignSentinelApi.getPayByOrderNo(orderNo);}
}

(3)测试验证

① 启动 9001 和 83,访问地址:http://localhost:83/consumer/pay/nacos/get/1024

83 通过 feign 成功调用 9001,测试成功!

细节:

视频中采用的 springboot 和 springcloud 版本过高,而 springcloud alibaba 的版本由于没来的及更新,所以不兼容。

我这里 springcloud alibaba 的版本为 2023.0.0.0-RC1,已经完成兼容,所以不会出现问题。

②  Sentinel 控制台配置 

③  测试限流:

访问地址:http://localhost:83/consumer/pay/nacos/get/1024,不停刷新

触发了 sentinel 的流控配置规则,blockHandler 方法生效!

④ 测试服务降级:

模拟场景:9001宕机了,83 继续通过 feign 调用 9001

关闭 9001 服务,继续访问地址: http://localhost:83/consumer/pay/nacos/get/1024

 触发服务降级,调用 fallback 方法!

12.GateWay和Sentinel集成实现服务限流

(1)需求说明

(2)编码步骤

前提:nacos服务器 和 Sentinel 启动成功

① 新建 module(cloudalibaba-sentinel-gateway9528)

②  导入依赖

    <dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-transport-simple-http</artifactId><version>1.8.6</version></dependency><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-spring-cloud-gateway-adapter</artifactId><version>1.8.6</version></dependency><dependency><groupId>javax.annotation</groupId><artifactId>javax.annotation-api</artifactId><version>1.3.2</version><scope>compile</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>

③ 修改 application.yml

server:port: 9528spring:application:name: cloudalibaba-sentinel-gateway     # sentinel+gataway整合Casecloud:nacos:discovery:server-addr: localhost:8848gateway:routes:- id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名uri: http://localhost:9001                #匹配后提供服务的路由地址predicates:- Path=/pay/**                      # 断言,路径相匹配的进行路由

注意:

如果这里你想使用动态路由(uri: lb://nacos-payment-provider) ,9528 网关必须导入 nacos 和 loadbalancer 的相关依赖:

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

nacos 依赖:它负责让网关 9528 可以通过 Nacos 注册中心 动态获取服务列表。 

loadbalancer 依赖:网关通过 lb:// 协议访问服务时,负载均衡器需要决定将请求发送到哪一个具体的服务实例。

Question:可能会有人注意到,之前 9527 使用动态路由的时候,只是导入了 consul 的相关依赖,并没有导入 loadbalancer 的依赖啊?

 

Spring Cloud Gateway 依赖 spring-cloud-loadbalancer 提供负载均衡能力,但这一能力的生效依赖于网关能够获取服务实例列表。而服务实例列表的来源依赖于服务注册发现组件,比如:

  • Eureka、Consul、Zookeeper(Spring Cloud 原生支持)。
  • Nacos(Spring Cloud Alibaba 生态)。

对于 Spring Cloud Gateway

  • 如果使用的是 Spring Cloud 原生的服务注册发现组件(如 Consul),网关的 spring-cloud-starter-gateway 中已经隐式集成了负载均衡相关功能,无需显式添加额外依赖。
  • 如果使用的是 Spring Cloud Alibaba 的服务注册发现组件(如 Nacos),需要显式引入 spring-cloud-starter-loadbalancer,因为它不默认包含。

总结:

  • 9527 网关(基于 Consul):

    • Spring Cloud Gateway 和 Spring Cloud Consul 是原生兼容的,lb:// 的负载均衡能力通过默认配置生效。
  • 9528 网关(基于 Nacos):

    • Spring Cloud Gateway 和 Nacos 不直接兼容,需要显式引入 spring-cloud-starter-loadbalancer,否则 lb:// 无法正常解析。

④ 修改主启动类

@SpringBootApplication
@EnableDiscoveryClient
public class Main9528
{public static void main(String[] args){SpringApplication.run(Main9528.class,args);}
}

⑤ 配置

参考官网配置说明案例改写:网关限流 · alibaba/Sentinel Wiki · GitHubicon-default.png?t=O83Ahttps://github.com/alibaba/Sentinel/wiki/%E7%BD%91%E5%85%B3%E9%99%90%E6%B5%81#spring-cloud-gateway

 新建配置类 GatewayConfiguration:

//使用时只需注入对应的 SentinelGatewayFilter 实例以及 SentinelGatewayBlockExceptionHandler 实例即可
@Configuration
public class GatewayConfiguration {private final List<ViewResolver> viewResolvers;private final ServerCodecConfigurer serverCodecConfigurer;public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer){this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);this.serverCodecConfigurer = serverCodecConfigurer;}@Bean@Order(Ordered.HIGHEST_PRECEDENCE)public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {// Register the block exception handler for Spring Cloud Gateway.return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);}@Bean@Order(-1)public GlobalFilter sentinelGatewayFilter() {return new SentinelGatewayFilter();}@PostConstruct //javax.annotation.PostConstructpublic void doInit() {initBlockHandler();}//处理 + 自定义返回的例外信息内容private void initBlockHandler() {Set<GatewayFlowRule> rules = new HashSet<>();rules.add(new GatewayFlowRule("pay_routh1").setCount(2).setIntervalSec(1)  //QPS为1s内2次);GatewayRuleManager.loadRules(rules);BlockRequestHandler handler = new BlockRequestHandler() {@Overridepublic Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable t) {Map<String,String> map = new HashMap<>();map.put("errorCode", HttpStatus.TOO_MANY_REQUESTS.getReasonPhrase());map.put("errorMessage", "请求太过频繁,系统忙不过来,触发限流(sentinel+gataway整合Case)");return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(map));}};GatewayCallbackManager.setBlockHandler(handler);}}

⑥ 启动 9001 和 9528,进行测试

原生url:http://localhost:9001/pay/nacos/333

http://localhost:9001/pay/nacos/333

加网关:http://localhost:9528/pay/nacos/333

sentinel+gateway:加快点击频率,出现限流容错 

http://localhost:9528/pay/nacos/333

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

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

相关文章

【Java基础面试题009】Java的I/O流是什么?

相关知识补充&#xff1a;黑马-字符集、IO流&#xff08;一&#xff09;.pdf Autism_Btkrsr/Blog_md_to_pdf - 码云 - 开源中国 (gitee.com) 黑马-IO流&#xff08;二&#xff09;.pdf Autism_Btkrsr/Blog_md_to_pdf - 码云 - 开源中国 (gitee.com) 回答重点 Java的I/O&…

第六届国际科技创新学术交流会暨管理科学信息化与经济创新发展(MSIEID 2024)

重要信息 大会官网&#xff1a;msieid2024.iaecst.org &#xff08;点击了解大会&#xff0c;参会等内容&#xff09; 大会时间&#xff1a;2024年12月6-8日 大会地点&#xff1a;中国-广州 大会简介 随着全球化和信息化的不断深入&#xff0c;管理科学、信息化和经济发展…

python学opencv|读取视频(一)灰度视频制作和保存

【1】引言 上一次课学习了用opencv读取图像&#xff0c;掌握了三个函数&#xff1a;cv.imread()、cv.imshow()、cv.imwrite() 相关链接如下&#xff1a; python学opencv|读取图像-CSDN博客 这次课我们继续&#xff0c;来学习用opencv读取视频。 【2】学习资源 首先是官网…

题外话 (火影密令)

哥们&#xff01; 玩火影不&#xff01; 村里人全部评论&#xff01; 不评论的忍战李全保底&#xff01; 哥们&#xff01; 密令领了不&#xff01; “1219村里人集合”领了吗&#xff01; 100金币&#xff01; 哥们&#xff01; 我粉丝没人能上影&#xff01; 老舅说的…

人形机器人训练、机器臂远程操控、VR游戏交互、影视动画制作,一副手套全部解决!

广州虚拟动力基于自研技术推出了多节点mHand Pro动捕数据手套&#xff0c;其最大的特点就是功能集成与高精度捕捉&#xff0c;可以用于人形机器人训练、机器臂远程操控、VR游戏交互、影视动画制作等多种场景。 一、人形机器人训练 mHand Pro动捕数据手套双手共装配16个9轴惯性…

vue3+view-ui-plus+vite+less 实现自定义iview样式

首先是结论&#xff1a; "less": "^2.7.3", "less-loader": "^4.1.0", vite.config.js resolve: {alias: {// 设置路径~: path.resolve(__dirname, ./),// 设置别名: path.resolve(__dirname, ./src)},extensions: [.mjs, .js, .ts…

SpringMVC接收数据

一、访问路径设置: RequestMapping注解的作用就是将请求的URL地址和处理请求的方式(handler方法)关联起来&#xff0c;建立映射关系;SpringMVC接收到指定的请求&#xff0c;就会来找到在映射关系中对应的方法来处理这个请求 1.精准路径匹配: 在RequestMapping注解指定URL地址…

【微服务】Docker

一、Docker基础 1、依赖的兼容问题&#xff1a;Docker允许开发中将应用、依赖、函数库、配置一起打包&#xff0c;形成可移植镜像Docker应用运行在容器中&#xff0c;使用沙箱机制&#xff0c;相互隔离。 2、如何解决开发、测试、生产环境有差异的问题&#xff1a;Docker镜像…

【自用】管材流转项目前端重部署流程 vue2 webpackage4 vuecli4

一、配置 1.下载项目&#xff0c;使用 IDEA 打开&#xff0c;并配置 Nodejs 它提示我&#xff0c;需要 Node.js&#xff0c;因为 nodejs 14 的 installer 已经官网已经找不到了&#xff0c;使用 fnm 又太麻烦&#xff0c; 所以直接采用在 IDEA 中下载的方式就好了。 2.清除缓…

工程设计行业内外网文件交换解决方案:FileLink助力高效、安全的跨网协作

在工程设计行业&#xff0c;文件交换和信息共享是项目顺利推进的关键。尤其是涉及复杂的设计图纸、技术方案、合同文件等重要资料时&#xff0c;如何确保文件在内外网之间的高效、安全传输&#xff0c;直接影响到项目的进度和质量。FileLink正是为此而生&#xff0c;它为工程设…

Wwise SoundBanks内存优化

1.更换音频格式为Vorbis 2.停用多余的音频&#xff0c;如Random Container的随机脚步声数量降为2个 3.背景音乐勾选“Stream”。这样就让音频从硬盘流送到Wwise&#xff0c;而不是保存在内存当中&#xff0c;也就节省了内存 4.设置最大发声数Max Voice Instances 5.设置音频…

C 语言 “神秘魔杖”—— 指针初相识,解锁编程魔法大门(一)

文章目录 一、概念1、取地址操作符&#xff08;&&#xff09;2、解引用操作符&#xff08;*&#xff09;3、指针变量1、 声明和初始化2、 用途 二、内存和地址三、指针变量类型的意义1、 指针变量类型的基本含义2、 举例说明不同类型指针变量的意义 四、const修饰指针1、co…

Android 使用OpenGLES + MediaPlayer 获取视频截图

概述 Android 获取视频缩略图的方法通常有: ContentResolver: 使用系统数据库MediaMetadataRetriever: 这个是android提供的类&#xff0c;用来获取本地和网络media相关文件的信息ThumbnailUtils: 是在android2.2&#xff08;api8&#xff09;之后新增的一个&#xff0c;该类为…

博泽Brose EDI项目案例

Brose 是一家德国的全球性汽车零部件供应商&#xff0c;主要为全球汽车制造商提供机电一体化系统和组件&#xff0c;涵盖车门、座椅调节系统、空调系统以及电动驱动装置等。Brose 以其高质量的创新产品闻名&#xff0c;在全球拥有多个研发和生产基地&#xff0c;是全球第五大家…

python使用python-docx处理word

文章目录 一、python-docx简介二、基本使用1、新建与保存word2、写入Word&#xff08;1&#xff09;打开文档&#xff08;2&#xff09;添加标题&#xff08;3&#xff09;添加段落&#xff08;4&#xff09;添加文字块&#xff08;5&#xff09;添加图片&#xff08;6&#xf…

aws(学习笔记第十五课) 如何从灾难中恢复(recover)

aws(学习笔记第十五课) 如何从灾难中恢复 学习内容&#xff1a; 使用CloudWatch对服务器进行监视与恢复区域(region)&#xff0c;可用区(available zone)和子网(subnet)使用自动扩展(AutoScalingGroup) 1. 使用CloudWatch对服务器进行监视与恢复 整体架构 这里模拟Jenkins Se…

lwip raw、netcoon、socket三种接口编程的区别

目录 一、前言 二、LWIP 简介 三、LWIP RAW 编程 1.概念与原理 2.编程模型与流程 3.示例代码 4.优点与缺点 四、LWIP NETCONN 编程 1.概念与原理 2.编程模型与流程 3.示例代码 4.优点与缺点 五、LWIP SOCKET 编程 1.概念与原理 2.编程模型与流程 3.示例代码 …

【XGlassTerminal.js】快速 构建 炫酷 终端 网页 以及 Linux 模拟器 在线!!

XGlassTerminal.js XGlassTerminal.js 是一个用于构建前端终端样式的 JavaScript 库。它允许开发者轻松地创建一个具有终端风格的用户界面&#xff0c;并对用户输入的命令进行事件处理。 该库提供了丰富的功能&#xff0c;包括文本添加、命令处理、点击事件绑定等。 同时还支…

车辆传动系统的simulink建模与仿真,分析加速和刹车两个工况

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 车辆传动系统的simulink建模与仿真,分析加速和刹车两个工况。模型包括车辆模块&#xff0c;传动模块&#xff0c;发动机模块&#xff0c;换挡模块&#xff0c;刹车油门输入模块…

宝塔配置定时任务详解

文章目录 宝塔配置定时任务详解一、引言二、配置定时任务1、登录宝塔面板2、添加定时任务2.1、步骤 3、配置任务3.1、设置任务名称和执行周期3.2、设置执行命令 4、保存并测试 三、使用示例1、备份数据库2、清理日志文件 四、总结 宝塔配置定时任务详解 一、引言 在服务器管理…