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

SpringCloud Alibaba Sentinel 创建流控规则

一、前言

        接下来是开展一系列的 SpringCloud 的学习之旅,从传统的模块之间调用,一步步的升级为 SpringCloud 模块之间的调用,此篇文章为第十四篇,即介绍 SpringCloud Alibaba Sentinel 创建流控规则。

二、基本介绍

        我们在 sentinel 的管理界面上为我们的请求设置流量监控的规则,有两种方式,如下图:

        点击 + 号,配置流控规则,界面如下图,接下来详细介绍下可以配置的标签

2.1 资源名

        唯一名称,默认请求路径。即工程里面 controller 层方法上面的请求路径。

2.2 针对来源

        Sentinel 可以针对调用者进行限流,填写微服务名,默认 default (不区分来源)。

2.3 阈值类型

        QPS(每秒钟的请求数量):当调用该 api QPS 达到阀值的时候,进行限流。

        线程数:当调用该 api 的线程数达到阀值的时候,进行限流。

2.4 单机阈值

        一个具体的数字,为阀值类型所使用。

2.5 是否集群

        不需要集群。

2.6 流控模式

        1、直接:api 达到限流条件时,直接限流。

        2、关联:当关联的资源达到闻值时,就限流自己

        3、链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到闻值,就进行限流)[api 级别的针对来源]。

2.7 流控效果

        1、快速失败: 直接失败,抛异常

        2、Warm Up:根据 codeFactor ( 冷加载因子,默认 3 )的值,从阀值 / codeFactor,经过预热时长,才达到设置的 QPS 阀值。

        3、排队等待:匀速排队,让请求以匀速的速度通过,闻值类型必须设置为 QPS,否则无效。

三、流控模式

3.1 直接

        接下来我们配置一个系统默认的流控规则,即 QPS -直接-快速失败,如下图,表示 1s 内查询一次是没有问题的,但是在 1s 内点击超过一次就直接快速失败,报默认错误。

        快速点击访问 http://localhost:8401/testB,如下图,可以看到,第一次请求是没有任何问题的,

        但是当我们狂点的时候,就会返回给我们限流的提醒了,如下图:

        

        修改我们刚刚创建的流控规则,将 QPS -直接-快速失败 模式修改为  并发线程数 -直接-快速失败 ,如下图:

        快速点击访问 http://localhost:8401/testB,如下图,可以看到,一直没有报错信息

        这是因为 QPS 和并发线程数是两种不同的流控效果,即 QPS 有流控效果,而并发线程数没有流控效果,从上面配置时的两张图片对比就可以看的出来。

        当有一堆请求发送过来时(高并发场景),QPS 流控就会将请求全部拦截在门外,根本接触不到里面的路径,而并发流控则是将请求放进来,但是只能有一个请求得到处理,其他的请求直接失败报错。

        上面一直调用成功的原因是后台处理请求在一瞬间就完成了,为了演示流控的效果,我们修改下 FlowLimitController 的代码,延长下 testB() 方法的处理时间,代码如下:

@RestController
public class FlowLimitController {@GetMapping("/testA")
public String testA(){return "------testA";}@GetMapping("/testB")
public String testB(){try {Thread.sleep(800);} catch (InterruptedException e) {throw new RuntimeException(e);}return "------testB";}
}

        打开两个浏览器窗口,分别调用 http://localhost:8401/testB,如下图,第一次调用没有任何问题,如下图:

        第二次调用就返回异常信息了(点击的速度得快,要不演示不出来),如下:

3.2 关联

        当关联的资源达到阈值时,就限流自己,当与 A 关联的资源 B 达到阀值后,就限流 A 自己,举个简单的例子就是支付模块快爆炸了,就限流下订单模块。

        在 sentinel 的管理界面配置一个关联的限流规则,如下,当关联资源 /testBqps 阀值超过 1 时,就限流 /testARest 访问地址,当关联资源到阈值后限制配置好的资源名。

        测试之前先把  FlowLimitController 的代码改回来,如下:

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

        为了演示模拟的效果,我们需要使用 postman 进行并发密集访问 /testB,打开 postman,创建一个新的 collection,如下图:

        接下来创建一个新的请求,记得保存这个请求,如下图:

        接下来配置运行的参数,如下图:

        配置一个线程组,包含 20 个线程,每隔 0.3s 访问一次 

        然后调用 http://localhost:8401/testA ,可以发现 testA 挂了,如下图:

3.3 链路

        假设一个 controller 里面的两个服务都会调用同一个 service 层里面的服务,这样就会形成两条链路,但是由于 service 层的资源是有限的,我们可以通过配置链路的流控模式来保证某一条链路一直可以正常使用,但另一条链路可能就会多担待一点。

        它和我们的关联模式有点像,也是保证一个接口可以正常使用,而牺牲了另外一个接口。接下来我们使用代码来演示下。

        首先需要创建一个 service 层,并编写一个方法,这个方法是给 controller 层的两个方法提供服务的,并在方法上添加 @SentinelResource 注解,这个注解用于标记需要被流量控制、熔断降级以及系统保护等功能覆盖的方法或类。这个注解允许开发者自定义资源名称,并且可以配置异常处理逻辑和 fallback 函数。代码如下:

package com.springcloud.service;import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.stereotype.Service;@Service
public class FlowLimitService {@SentinelResource("todoService")public  void todoService(){System.out.println("....todoService....");}
}

        接下来需要在我们的配置文件里面添加一些配置,配置文件里面默认采用的是聚合的方式,我们这里改成 false,采用展开的模式,即我们有多少个链路都把它展示出来。

        接下来修改 controller 类的代码,让其调用 service 层的方法,如下:

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

        接下来打开 sentinel 的管理界面,首先调用 testA testB 服务,如下图:

        如果我们没有在配置文件里面配置 web-context-unify: false 这个标签,或者配置完了这个标签出现下面的这种情况。

        原因可能是因为 spring-cloud-starter-alibaba-sentinel 版本太低,将其改成下面的版本即可。

<!-- 流量控制sentinel依赖-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId><version>2.2.5.RELEASE</version>
</dependency>

         接下来配置链路的流控,我们对 testA 的链路进行限流,如下图:

        此时疯狂调用 http://localhost:8401/testB,如下图,没有任何反应,可以正常返回

        疯狂调用 http://localhost:8401/testA,如果频率高一些就会报错,如下图: 

         证明我们的链路调用限流成功了。

四、流控效果

4.1 快速失败

        这种流控效果上面我们做了大量的例子,就是直接失败,抛出异常,如下图:

4.2 Warm Up 预热

        当流量突然增大的时候,我们常常会希望系统从空闲状态到繁忙状态的切换的时间长一些。即如果系统在此之前长期处于空闲的状态,我们希望处理请求的数量是缓步的增多,经过预期的时间以后,到达系统处理请求个数的最大值。Warm Up(冷启动,预热)模式就是为了实现这个目的的。

        这个场景主要用于启动需要额外开销的场景,例如建立数据库连接等。

        它有一个公式:初始阈值 = (配置的阈值)除以( codeFactor 默认值为 3),

        经过预热时长后才会达到配置的阈值。这样讲很抽象,我们配置一个来展示下,首先把 controller 代码恢复成原来的样子,如下图:

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

        配置预热的流控效果,如下图,​我希望每秒钟可以承受 10 QPS,但是我给你慢慢的预热起来,由于冷加载默认因子是 310/3 =3 ,那么一开始单机的阈值就是 3,但是给了你一个缓冲预热的时间 5s,让你 5s 内,慢慢的从 3 过度到 10

        此时疯狂调用 http://localhost:8401/testB,可以发现一开始有成功有失败,但到后来就都是成功的了。

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

4.3 排队等待

        匀速排队方式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。该方式的作用如下图所示:

        这种方式主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求。

        注意:匀速排队模式暂时不支持 QPS > 1000 的场景。

        修改下 controller 类的代码,加一个日志打印的功能,如下:

@RestController
@Slf4j
public class FlowLimitController {@GetMapping("/testA")public String testA(){return "------testA";}@GetMapping("/testB")public String testB(){log.info(Thread.currentThread().getName()+"\t"+"testB");return "------testB";}
}

        配置排队等待的流控效果,如下图,设置单机阈值为 1,超时时间为 2s。​

         接下来使用 postman 进行多线程调用测试,和 5.2.2 小节用的方式一样,调用 collenction,如下图:

        查看控制台的日志信息,如下,可以看到,都是 1s 内调用一次,很舒服

五、降级规则

5.1 简介

        降级规则又称为熔断降级,除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。一个服务常常会调用别的模块,可能是另外的一个远程服务、数据库,或者第三方 API 等。例如,支付的时候,可能需要远程调用银联提供的 API;查询某个商品的价格,可能需要进行数据库查询。然而,这个被依赖服务的稳定性是不能保证的。如果依赖的服务出现了不稳定的情况,请求的响应时间变长,那么调用服务的方法的响应时间也会变长,线程会产生堆积,最终可能耗尽业务自身的线程池,服务本身也变得不可用。

        现代微服务架构都是分布式的,由非常多的服务组成。不同服务之间相互调用,组成复杂的调用链路。以上的问题在链路调用中会产生放大的效果。复杂链路上的某一环不稳定,就可能会层层级联,最终导致整个链路都不可用。因此我们需要对不稳定的弱依赖服务调用进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。熔断降级作为保护自身的手段,通常在客户端(调用端)进行配置。

        本文档针对 Sentinel 1.8.0 及以上版本。1.8.0 版本对熔断降级特性进行了全新的改进升级,请使用最新版本以更好地利用熔断降级的能力。

        Sentinel Hystrix 的原则是一致的:当调用链路中某个资源出现不稳定,例如,表现为 timeout,异常比例升高的时候,则对这个资源的调用进行限制,并让请求快速失败,避免影响到其它的资源,最终产生雪崩的效果。 

5.2 熔断策略

        熔点策略分为三种:慢调用比例、异常比例和异常数三种。

5.3 慢调用比例

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

        在 FlowLimitController 类中新增一个测试方法 testD,代码如下:

@RestController
@Slf4j
public class FlowLimitController {@GetMapping("/testA")public String testA() {return "------testA";}@GetMapping("/testB")public String testB() {log.info(Thread.currentThread().getName() + "\t" + "testB");return "------testB";}@GetMapping("/testD")public String testD() {//暂停几秒钟线程try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}log.info("testD 测试RT");return "------testD";}
}

        在 sentinel 中配置降级规则,如下图:

        设定允许的最大响应时间 RT = 900ms,统计最近 10000ms 内的请求,若请求超过 5 次,并且慢调用的比例超过 0.5,则触发熔断,熔断时长为 2s,然后进入 half-open 状态,放行一次请求做测试。

        接下来我们使用 postman 进行测试,使用 10 个线程调用我们的方法,如下图:

        等 postman 调用结束后,测试当前 testD 的状态,如下图,可以发现处于熔断状态了。

        等到 2s 之后,再次刷新浏览器,可以看到,又恢复正常了,如下图:

5.4 异常比例

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

        修改 FlowLimitController 类中的测试方法 testD,代码如下:

    @GetMapping("/testD")public String testD() {log.info("testD 测试异常调用");int age = 10 / 0;return "------testD";}

        在 sentinel 中配置降级规则,如下图:

        统计最近 10000ms 内的请求,若请求超过 5 次,并且异常的比例超过 0.5,则触发熔断,熔断时长为 3s,然后进入 half-open 状态,放行一次请求做测试。 

        我们先在浏览器访问一下方法,如下,可以看到返回的是错误的界面。

        接下里我们使用 postman 进行测试,使用 10 个线程调用我们的方法,如下图:

        调用结束后再次在浏览器访问 testD,可以看到,返回的是限流的界面,如下图:

        等到 3s 之后,再次访问,可以看到,又出现了错误的界面,如下:

5.5 异常数

        异常数 (ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。

        在 FlowLimitController 类中的新增测试方法 testE,代码如下:

    @GetMapping("/testE")public String testE() {log.info("testE 测试异常数");int age = 10 / 0;return "------testE";}

        在 sentinel 中配置降级规则,如下图: 

        统计最近 10000ms 内的请求,若请求超过 5 次,并且异常数超过 5 个,则触发熔断,熔断时长为 3s,然后进入 half-open 状态,放行一次请求做测试。 

        在浏览器多次访问 testE,可以发现,前五次返回的页面如下:

        等到第六次,返回的就是流控的界面了,如下:

六、热点参数限流

6.1 简介

        何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:

        1、商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制。

        2、用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制

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

6.2 案例演示

        在 FlowLimitController 类中的新增两个方法,代码如下,@SentinelResource 注解我们在 上面提到过,用于标记需要被流量控制、熔断降级以及系统保护等功能覆盖的方法或类。

        它里面有个 blockHandler 属性,用于指定兜底的方法,兜底方法分为系统默认和客户自定义两种,在之前的案例中,限流出问题后,都是用 sentinel 系统默认的提示:Blocked by Sentinel (flow limiting)。这次我们指定兜底的方法为下面的 deal_testHotKey

    @GetMapping("/testHotKey")@SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey")public String testHotKey(@RequestParam(value = "p1",required = false) String p1,@RequestParam(value = "p2",required = false) String p2) {return "------testHotKey";}public String deal_testHotKey (String p1, String p2, BlockException exception){// sentinel系统默认的提示:Blocked by Sentinel (flow limiting)return "------deal_testHotKey,o(╥﹏╥)o";}

        接下里我们在 sentinel 中配置热点规则,如下:

        限流模式只支持 QPS 模式,固定写死了。@SentinelResource 注解的方法参数索引,0 代表第一个参数,1 代表第二个参数,以此类推。单机阀值以及统计窗口时长表示在此窗口时间超过阀值就限流。

        上面配置的规则为:1sQPS 1,超过就限流,限流后调用 dealHandler testHotKey 支持方法。

        在浏览器访问:http://localhost:8401/testHotKey,怎么点击都不会出现限流的效果,因为并没有传输参数。

       在浏览器访问:http://localhost:8401/testHotKey?p1=a,如果 1s 点击一下就会出现下面的现象:

        如果点击频繁,就会出现限流的效果,如下:

       在浏览器访问:http://localhost:8401/testHotKey?p2=b,随便点,也不会出现限流的效果,因为我们没有对第二个参数进行配置,所以不用限流,如下:

6.3 特殊情况

        上述案例演示了第一个参数 p1,当 QPS 超过 1s 点击一次后马上被限流,但是我们期望当 p1 参数是某个特殊值时,它的限流值和平时不一样,比如说当 p1 的值等于 5 时,它的阈值可以达到 200,那么我们该如何配置呢?

        修改我们刚才配置的 sentinel 热点规则,打开参数例外项,需要注意的是:参数类型必须是基本类型或者 String,如下图:

       在浏览器访问:http://localhost:8401/testHotKey?p1=5,可以看到,无论点击多么频繁都不会出现限流的现象,如下图:

       在浏览器访问:http://localhost:8401/testHotKey?p1=4,可以看到,超过 1s 点击一次就会出现限流的现象,如下图,当 p1 不等于 5 的时候,阈值就是平常的 1

6.4 异常情况

        修改 FlowLimitController 类,手动添加一个异常试试,如下:

    @GetMapping("/testHotKey")@SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey")public String testHotKey(@RequestParam(value = "p1",required = false) String p1,@RequestParam(value = "p2",required = false) String p2) {int age = 10/0;return "------testHotKey";}public String deal_testHotKey (String p1, String p2, BlockException exception){// sentinel系统默认的提示:Blocked by Sentinel (flow limiting)return "------deal_testHotKey,o(╥﹏╥)o";}

        在浏览器访问:http://localhost:8401/testHotKey,可以看到,直接就报错了,如下图:

        这是因为 @SentinelResource 处理的是 Sentinel 控制台配置的违规情况,有 blockHandler 方法配置的兜底处理。而 int age = 10/0,这个是 java 运行时报出的运行时异常 RunTimeException@SentinelResource 不管。

        总结起来就是 @SentinelResource 主管配置出错,运行出错该走异常走异常。

七、系统规则

7.1 简介

        系统规则又称为系统自适应限流,是从应用级别的入口流量进行控制,从单台机器的 loadCPU 使用率、平均 RT、入口 QPS 和并发线程数等几个维度监控应用指标,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。前面我们所配置的限流都是方法级别的限流,而系统规则则是对整个应用进行限流的操作。

        系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。入口流量指的是进入应用的流量,比如 Web 服务或 Dubbo 服务端接收的请求,都属于入口流量。

7.2 分类

        1、Load 自适应(仅对 Linux/Unix-like 机器生效):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 maxQps * minRt 估算得出。设定参考值一般是 CPU cores * 2.5

        2、CPU usage1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。

        3、平均 RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。

        4、并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。

        5、入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。

7.3 案例演示

        在 sentinel 控制台新增一个入口 QPS 的系统规则,如下图:

        在浏览器访问 http://localhost:8401/testB,当 1s 点击一下时,效果如下图,没有任何问题

        当频繁点击时就会出现限流的效果,如下图:

相关文章:

SpringCloud Alibaba Sentinel 创建流控规则

一、前言 接下来是开展一系列的 SpringCloud 的学习之旅&#xff0c;从传统的模块之间调用&#xff0c;一步步的升级为 SpringCloud 模块之间的调用&#xff0c;此篇文章为第十四篇&#xff0c;即介绍 SpringCloud Alibaba Sentinel 创建流控规则。 二、基本介绍 我们在 senti…...

Mysql底层原理五:如何设计、用好索引

1.索引的代价 空间上的代价 时间上的代价 每次对表中的数据进⾏增、删、改操作时&#xff0c;都需要去修改各个B树索引。⽽且我们讲过&#xff0c;B树每层节点都是按照索引列的值从⼩到⼤的顺序排序⽽组成了双 向链表。不论是叶⼦节点中的记录&#xff0c;还是内节点中的记录&a…...

python学习杂记

做为一个接近40岁的人&#xff0c;开始学习python会有什么结果&#xff1f;反正很迷茫&#xff0c;思维方式也开始下降了&#xff0c;希望可以学得好吧 早期做的是前端开发&#xff0c;java也有所接触&#xff0c;但是都学得不精&#xff0c;后来转做项目管理&#xff0c;把技…...

C# Socket发送、接收结构体

Socket发送&#xff1a;Socket的使用 一、Socket发送结构体 结构体如下&#xff1a; [StructLayout(LayoutKind.Sequential, Pack 1)] public struct OutPoint_ST {public int LeftheartX;public int LeftHeartY;public float WidthHeart;public int RightHeartX;public in…...

ics-05-攻防世界

题目 点了半天只有设备维护中心能进去 御剑扫一下 找到一个css 没什么用 再点击云平台设备维护中心url发生了变化 设备维护中心http://61.147.171.105:65103/index.php?pageindex试一下php伪协议 php://filter/readconvert.base64-encode/resourceindex.php base64解一下…...

Web API(三)之事件流事件委托其他事件

Web API(三)之事件流&事件委托&其他事件 事件流捕获和冒泡事件捕获事件冒泡阻止冒泡解绑事件两种注册事件的区别事件委托其他事件页面加载事件元素滚动事件页面滚动事件-获取位置页面滚动事件-滚动到指定的坐标页面尺寸事件元素尺寸与位置元素尺寸与位置-尺寸...

SSL证书的作用是什么?

SSL证书让网站和用户之间安全传输信息&#xff0c;就像给网络对话加了一把密码锁。它主要做四件事&#xff1a; 1. 证明身份&#xff1a; - 像警察局一样&#xff0c;有个叫“证书颁发机构”的家伙负责检查网站是不是真的。网站要向它证明自己是谁&#xff08;比如&#xff0c;…...

皮具5G智能制造工厂数字孪生可视化平台,推进企业数字化转型

皮具5G智能制造工厂数字孪生可视化平台&#xff0c;推进企业数字化转型。随着信息技术的快速发展&#xff0c;数字化转型已成为企业提升竞争力、实现可持续发展的关键路径。皮具行业&#xff0c;作为一个传统的手工制造业&#xff0c;正面临着巨大的市场变革和技术挑战。如何在…...

RH850从0搭建Autosar开发环境【3X】- Davinci Configurator之Port模块配置详解(MCAL配置)

Port模块配置详解 前言一、如何添加Port模块?1.1 导入Port模块二、Port模块详细配置说明2.1 Port模块问题解决2.2 Port模块配置步骤2.2.1 数据手册查找Port对应的Group2.2.2 配置Port为CAN功能2.2.3 选择芯片型号总结前言 我们还差一个Port模块进行配置io的复用功能选择。就是…...

多叉树题目:子树中标签相同的结点数

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;子树中标签相同的结点数 出处&#xff1a;1519. 子树中标签相同的结点数 难度 5 级 题目描述 要求 给你一个树&#xff08;即一个连通的无向无环图…...

帝国CMS模板源码整站安装说明(图文)

安装步骤 第一步&#xff1a;先把得到的文件解压缩&#xff0c;把文件通过FTP传到空间里。&#xff08;请不要把类似www.lengleng.net这个文件夹传到FTP&#xff0c;请传这个大文件夹下面的所有文件夹和文件到空间根目录&#xff0c;请不要上传到2级目录&#xff0c;除非你自己…...

物联网系统未来的发展趋势

一、引言 物联网系统作为新一代的信息技术&#xff0c;正在逐渐改变我们的生活和工作方式。随着物联网技术的不断发展和应用场景的拓展&#xff0c;未来物联网系统的发展趋势将更加明显。本文将从技术、应用、安全等方面探讨物联网系统未来的发展趋势。 二、技术发展趋势 1.…...

基于支持 GPT 的服务的初创公司

Kafkai&#xff1a;多语言长篇内容生成&#xff0c;AI写作的新趋势 介绍 随着生成式预训练 Transformer (GPT) 的出现&#xff0c;技术世界正在见证范式转变。 这种人工智能驱动的创新不仅仅是一种转瞬即逝的趋势&#xff0c;而是一种趋势。 它已成为科技行业的基石&#xff0c…...

基于springboot实现教师人事档案管理系统项目【项目源码+论文说明】

基于springboot实现IT技术交流和分享平台系统演示 摘要 我国科学技术的不断发展&#xff0c;计算机的应用日渐成熟&#xff0c;其强大的功能给人们留下深刻的印象&#xff0c;它已经应用到了人类社会的各个层次的领域&#xff0c;发挥着重要的不可替换的作用。信息管理作为计算…...

上行上传rsync+inotify

引言 使用inotify通知接口&#xff0c;可以用来监控文件系统的各种变化情况&#xff0c;如文件存取、删除、移动、修改等。利用这一机制&#xff0c;可以非常方便地实现文件异动告警、增量备份&#xff0c;并针对目录或文件的变化及时作出响应。 将inotify机制与rsync工具相结合…...

借助ChatGPT写作:打造学术论文中的亮点与互动

ChatGPT无限次数:点击直达 打造学术论文中的亮点与互动 引言 学术论文是学术界交流思想、探讨问题和展示研究成果的重要形式。如何使学术论文在众多作品中脱颖而出&#xff0c;吸引读者的眼球并激发互动&#xff0c;是每位研究者都关注的问题。本文将介绍如何借助ChatGPT这一…...

逐步学习Go-sync.Mutex(详解与实战)

概述 Go中提供了互斥锁&#xff1a;sync.Mutex。sync.Mutex提供了以下方法&#xff1a; type Mutex // 加锁。如果已经有goroutine持有了锁&#xff0c;那么就阻塞等待直到持有锁 func (m *Mutex) Lock()// 尝试加锁。如果加锁成功就返回true&#xff0c;否则返回失败 func (m…...

每日三道面试题之 Java并发编程 (一)

1.为什么要使用并发编程 并发编程是一种允许多个操作同时进行的编程技术&#xff0c;这种技术在现代软件开发中非常重要&#xff0c;原因如下&#xff1a; 充分利用多核处理器&#xff1a;现代计算机通常都拥有多核处理器&#xff0c;通过并发编程&#xff0c;可以让每个核心独…...

车身稳定控制系统原理是什么?

车身稳定控制系统&#xff08;Electronic Stability Control&#xff0c;ESC&#xff09;是一种先进的车辆动态控制系统&#xff0c;其主要原理是通过传感器监测车辆的各项状态&#xff0c;包括车速、转向角度、侧倾角等&#xff0c;然后通过电子控制单元&#xff08;ECU&#…...

vue3前端加载动画 lottie-web 的简单使用案例

什么是 Lottie Lottie 是 Airbnb 发布的一款开源动画库&#xff0c;它适用于 Android、iOS、Web 和 Windows 的库。 它提供了一套从设计师使用 AE&#xff08;Adobe After Effects&#xff09;到各端开发者实现动画的工具流。 UED 提供动画 json 文件即可&#xff0c; 开发者就…...

基于java+springboot+vue实现的健身房管理系统(文末源码+Lw)23-223

摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装健身房管理系统软件来发挥其高效地信息处理的作用&#xf…...

10款白嫖党必备的ai写作神器,你都知道吗? #媒体#人工智能#其他

从事自媒体运营光靠自己手动操作效率是非常低的&#xff0c;想要提高运营效率就必须要学会合理的使用一些辅助工具。下面小编就跟大家分享一些自媒体常用的辅助工具&#xff0c;觉得有用的朋友可以收藏分享。 1.飞鸟写作 这是一个微信公众号 面向专业写作领域的ai写作工具&am…...

Docker工作流

1.工作流 开发应用编写Dockerfile构建Docker镜像运行Docker容器测试应用发布镜像到Hub迭代更新镜像 2.开发应用 首先你需要创建一个应用&#xff0c;这个应用可以是后端应用或者前端应用&#xff0c;任何语言都可以。 比如&#xff1a;我使用IDEA 创建一个Java后端应用&…...

深入浅出 -- 系统架构之分布式集群的分类

一、单点故障问题 集群&#xff0c;相信诸位对这个概念并不陌生&#xff0c;集群已成为现时代中&#xff0c;保证服务高可用不可或缺的一种手段。 回想起初集中式部署的单体应用&#xff0c;因为只有一个节点&#xff0c;因此当该节点出现任意类型的故障&#xff08;网络、硬件…...

Docker之镜像与容器的相关操作

目录 一、Docker镜像 搜索镜像 下载镜像 查看宿主机上的镜像 删除镜像 二、Docker容器 创建容器 查看容器 启停容器 删除容器 进入容器 创建/启动/进入容器 退出容器 查看容器内部信息 一、Docker镜像 Docker 运行容器前需要本地存在对应的镜像&#xff0c; 如…...

中科驭数超低时延网络解决方案入选2023年度金融信创优秀解决方案

近日&#xff0c;由中国人民银行领导、中国金融电子化集团有限公司牵头组建的金融信创生态实验室发布「2023年度第三期金融信创优秀解决方案」&#xff0c;中科驭数超低时延网络解决方案从众多方案中脱颖而出&#xff0c;成功入选&#xff0c;代表了该方案的技术创新和金融实践…...

应用方案 | DCDC电源管理芯片MC34063A

MC34063A 为一单片 DC-DC 变换集成电路&#xff0c;内含温度补偿的参考电压源&#xff08;1.25V&#xff09;、比较器、能有效限制电流及控制工作周期的振荡器&#xff0c;驱动器及大电流输出开关管等。外配少量元件&#xff0c;就能组成升压、降压及电压反转型 DC-DC 变换器。…...

【个人使用推荐】联机不卡顿 小白一键部署 大厂云服务器选购指南 16G低至26 幻兽帕鲁最大更新来袭

更新日期&#xff1a;4月8日&#xff08;半年档 价格回调&#xff0c;京东云采购季持续进行&#xff09; 本文纯原创&#xff0c;侵权必究 《最新对比表》已更新在文章头部—腾讯云文档&#xff0c;文章具有时效性&#xff0c;请以腾讯文档为准&#xff01; 【腾讯文档实时更…...

57 npm run build 和 npm run serve 的差异

前言 npm run serve 和 npm run build 的差异 这里主要是从 vue-cli 的流程 来看一下 我们经常用到的这两个命令, 他到传递给 webpack 打包的时候, 的一个具体的差异, 大致是配置了那些东西? 经过了那些流程 ? vue-cli 的 vue-plugin 的加载 内置的 plugin 列表如下, 依次…...

原生小程序开发性能优化指南

性能优化指南 1.骨架屏 业务可以在数据加载完成之前用骨架屏幕来占位&#xff0c;提升体验。 2.包大小优化 减小包中静态资源&#xff0c;例如图片文件&#xff0c;可将图片进行压缩降低文件体积。无用文件、函数、样式剔除。除了部分用于容错的图片必须放在代码包&#xf…...

做美食有哪些网站/淘宝推广平台有哪些

我们可能会收到类似于这样的短信&#xff0c;发现其中的链接并不是常规的网址链接&#xff0c;而是个短小精悍的短链接&#xff0c;产品中经常需要这样的需求&#xff0c;如果在给用户下发的短信中是一个很长的连接&#xff0c;用户体验肯定很差&#xff0c;因此我们需要实现长…...

在线资源/福州seo公司

这位华人在四十多岁时开始创业&#xff0c;白手起家从无到有&#xff0c;缔造出市值200亿美元的公司&#xff0c;去年他在全美100强CEO榜单排名中&#xff0c;位居榜首&#xff0c;超越了苹果CEO库克和脸谱CEO扎克伯格&#xff0c;成为获此殊荣的第一位华人。视频会议软件提供商…...

前端低代码开发/seo草根博客

面试题目&#xff1a;实现RANSAC的框架 Random Sample Consensus&#xff08;RANSAC&#xff09; 随机抽样一致算法&#xff0c;MRPT写得是比较好的&#xff0c;注意每次此迭代后需要更新迭代次数。见https://github.com/MRPT/mrpt/blob/master/libs/math/src/ransac.cpp&#…...

营销型网站建设费用/百度seo泛解析代发排名

手机屏幕失灵了怎么办呢?手机屏幕失灵的情况&#xff0c;相信有些朋友会遇到&#xff0c;那么要怎么解决呢?下文小编就为大家带来手机屏幕失灵的解决方法&#xff0c;有需要的朋友可以来下文了解下哦~手机屏幕失灵解决方法&#xff1a;方法一&#xff1a;1、关闭手机&#xf…...

网站服务器服务商/seo每日一贴

支持向量机在高维或无限维空间中构造超平面或超平面集合&#xff0c;其可以用于分类、回归或其他任务。直观来说&#xff0c;分类边界距离最近的训练数据点越远越好&#xff0c;因为这样可以缩小分类器的泛化误差。 调用sklearn.svm的svc函数&#xff0c;将MNIST数据集进行分类…...

网站建设方案书的内容/网络推广员每天的工作是什么

BEGIN_MESSAGE_MAP 把消息和函数指针联系起来 1首先要在窗口类的cpp文件手动添加消息响应机制&#xff0c; ON_MESSAGE(ID,Handler) // 消息映射 LRESULT Handler(WPARAM,LPARAM);//响应的函数 BEGIN_MESSAGE_MAP(CXXXDlg, CDialog) //{{AFX_MSG_MAP(CXXXDlg) //自定义消…...