【微服务】SpringBoot整合Resilience4j使用详解

news2024/11/19 4:19:21

目录

一、前言

二、熔断器出现背景

2.1 几个核心概念

2.1.1 熔断

2.1.2 限流

2.1.3 降级

2.2 为什么会出现熔断器

2.3 断路器介绍

2.3.1 断路器原理

三、Resilience4j介绍

3.1 Resilience4j概述

3.1.1 Resilience4j是什么

3.1.2 Resilience4j功能特性

3.2 Resilience4j核心组件

3.2.1 Bulkhead

3.3 Resilience4j状态机

3.4 几种服务熔断组件对比

四、springboot整合Resilience4j

4.1 集成过程

4.1.1 导入依赖

4.1.2 添加配置文件

4.1.3 添加配置类

4.1.4 测试业务

4.1.5 接口测试

4.2 参数解读补充

4.2.1 circuitbreaker常用配置参数

4.2.2 ratelimiter常用配置参数

4.2.3 retry常用配置参数

五、写在文末


一、前言

当微服务数量越来越多之后,保证微服务自身的高可用性就变得异常重要了,高可用也是服务治理中的重要一环,在保障高可用解决方案中,服务的熔断、限流与降级可以说是其中非常重要的一种手段。

在Java的微服务生态中,对于服务保护组件,像springcloud的Hystrix,springcloud alibaba的Sentinel,以及当Hystrix停更之后官方推荐使用的Resilience4j。

二、熔断器出现背景

很多同学在学习微服务限流组件时,容易对熔断、限流、降级这几个概念混淆,甚至在什么场景下使用哪种保护措施也缺乏深一定的认识,这一点有必要搞清楚。

2.1 几个核心概念

关于熔断、限流、降级这几个关键词,做一下详细的解释。

2.1.1 熔断

熔断,即Circuit Breaker,熔断是一种故障处理机制,用于防止故障在系统中蔓延。

当一个服务出现故障时,熔断器会立即中断对该服务的请求,防止服务的故障传播到其他的组件。通过熔断机制,系统可以快速发现问题并做出相应的处理,避免系统整体崩溃。

2.1.2 限流

Rate Limiting,限流是一种控制请求流量的机制,用于保护系统免受过载的影响。

通过限制请求的频率或数量,可以确保系统在处理请求时不会超出其承受范围,限流可有效地平滑系统的负载,并防止突发流量对系统的影响。

2.1.3 降级

Degradation,降级是一种在系统负载过高或出现故障时,临时关闭部分功能或服务,以保证系统整体业务的可用性和稳定性机制。

通过降级,可以确保系统在面临异常情况时依然能够正常运行,而不是完全崩溃。降级可以根据不同情况选择关闭不同的服务或功能,以最大程度地保障系统的核心功能。

在这几个概念对应的微服务治理中,服务熔断是基础,同时也是保护系统受到意外冲击最基本也最有效的措施。

2.2 为什么会出现熔断器

在微服务开发中,当微服务数量越来越多的时候,服务之间的调用链路也越来越复杂,当某个服务调用另一个服务时,如果服务提供者出现网络超时或其他故障,过多的请求这时候都打来时,不仅会造成服务提供者的资源被占用过多出现阻塞,同时服务调用者也会出现堆积最终造成无法正常提供服务。

在这种情况下,就需要一种保护机制,通过实现调用熔断,以达到保护服务调用者的目的。如下图,A服务调用B服务,B服务调用C服务,当C服务出现故障或超时时,大量A服务调用请求导致B服务大量超时,最终导致B服务出现故障,这种级联的故障蔓延,最终会导致起始处的服务被冲垮。

2.3 断路器介绍

断路器,也叫熔断器,英文:CircuitBreaker,CircuitBreaker的目的是保护分布式系统免受故障和异常,提高系统的可用性和健壮性。

具体来说,当一个组件或服务出现故障时,CircuitBreaker会迅速切换到开放OPEN状态(保险丝跳闸断电),阻止请求发送到该组件或服务从而避免更多的请求发送到该组件或服务。这可以减少对该组件或服务的负载,防止该组件或服务进一步崩溃,并使整个系统能继续正常运行。同时,CircuitBreaker还可以提高系统的可用性和健壮性,因为它可以在分布式系统的各个组件之间自动切换,从而避免单点故障的问题。

2.3.1 断路器原理

CircuitBreaker的核心原理如下图:

我们可以用状态机来实现 Circuit Breaker,它有以下三种状态:

  • 关闭(Closed)状态;

    • 默认情况下Circuit Breaker是关闭的,此时允许操作执行;

    • Circuit Breaker内部记录着最近失败的次数,如果对应的操作执行失败,次数就会续一次;

    • 如果在某个时间段内,失败次数(或者失败比率)达到阈值,Circuit Breaker会转换到开启(Open)状态;

    • 在开启状态中,CircuitBreaker会启用一个超时计时器,设这个计时器的目的是给集群相应的时间来恢复故障。当计时器时间到的时候,Circuit Breaker会转换到半开启(Half-Open)状态。

  • 开启(Open);

    • 在此状态下,执行对应的操作将会立即失败并且立即抛出异常。

  • 半开启(Half-Open);

    • 在此状态下,Circuit Breaker 会允许执行一定数量的操作,如果所有操作全部成功,Circuit Breaker就会假定故障已经恢复,它就会转换到关闭状态,并且重置失败次数;

    • 如果其中 任意一次 操作失败了,Circuit Breaker就会认为故障仍然存在,所以它会转换到开启状态并再次开启计时器(再给系统一些时间使其从失败中恢复)。

在实际执行过程中,几个状态的切换流程如下图:

三、Resilience4j介绍

3.1 Resilience4j概述

上面了详细解了CircuitBreaker的原理,可以认为CircuitBreaker定义了一套业务实现规则或规范,而具体的实现组件,则是Resilience4j,即CircuitBreaker只是一套规范接口,落地实现者是Resilience4j。

git代码:https://github.com/resilience4j/resilience4j

文档地址:https://resilience4j.readme.io/

3.1.1 Resilience4j是什么

Resilience4j是一款轻量级,易于使用的容错库,其灵感来自于Netflix Hystrix,但是专为Java 8和函数式编程而设计。轻量级,因为库只使用了Vavr,它没有任何其他外部依赖下。相比之下,Netflix Hystrix对Archaius具有编译依赖性,Archaius具有更多的外部库依赖性。

  • Resilience4j是一个轻量级、易于使用的容错库,其灵感来自Netflix Hystrix,但专为Java 8和函数式编程设计。

  • Resilience4j提供高阶函数(decorators)来增强任何功能接口、lambda表达式或方法引用,包括断路器、速率限制器、重试或舱壁。可以在任何函数接口、lambda表达式或方法引用上使用多个装饰器。

  • circuitbreaker组件实现了断路器功能,是基于内存的断路器,采用ConcurrentHashMap来实现。

3.1.2 Resilience4j功能特性

  1. 断路器(Circuit Breaker):在服务出现故障时自动熔断,防止请求继续失败导致雪崩效应。

  2. 限流(Rate Limiter):限制请求的并发数或速率,防止系统被过载。

  3. 重试(Retry):在请求失败时自动重试一定次数,增加系统的可靠性。

  4. 超时(Timeout):设置请求的最大执行时间,防止请求长时间阻塞。

  5. Bulkhead:通过限制同时执行的请求数量,保护系统的部分资源不被耗尽。

使用Resilience4j可以通过简单的注解或者编程方式来实现以上功能,从而保护应用程序免受故障的影响,帮助应用程序在面对故障和不稳定性时保持稳定性和可靠性。

3.2 Resilience4j核心组件

要使用Resilience4j,不需要引入所有依赖,只需要选择你需要的,Resilience4j提供了以下的核心模块和拓展模块:

组件名称功能
resilience4j-circuitbreakerCircuit breaking(熔断器)
resilience4j-ratelimiterRate limiting(限流器)
resilience4j-bulkheadBulkheading(隔离器)--依赖隔离&负载保护
resilience4j-retryAutomatic retrying (sync and async)(重试、同步&异步)
resilience4j-cacheResult caching(缓存)
resilience4j-timelimiterTimeout handling(超时处理)

3.2.1 Bulkhead

Bulkhead,即并发控制器(舱壁,Bulkhead),是用来控制并行(parallel)调用的次数。Resilience4j提供了两种舱壁模式的实现,可用于限制并发执行的次数:

  • SemaphoreBulkhead(信号量舱壁,默认),基于Java并发库中的Semaphore实现;

  • FixedThreadPoolBulkhead(固定 线程池舱壁),它使用一个有界队列和一个固定线程池。

由于基于信号量的Bulkhead能很好地在多线程和I/O模型下工作,所以选择介绍基于信号量的Bulkhead的使用。

3.3 Resilience4j状态机

Resilience4j是CircuitBreaker的具体实现,因此具备CircuitBreaker涉及到熔断的所有状态,在Resilience4j中,共有6种状态,在实际工作中就是在这6种状态之间转换。

  • CLOSED: 关闭状态,代表正常情况下的状态,允许所有请求通过,能通过状态转换为OPEN;

  • HALF_OPEN: 半开状态,即允许一部分请求通过,能通过状态转换为CLOSED和OPEN;

  • OPEN: 熔断状态,即不允许请求通过,能通过状态转为为HALF_OPEN;

  • DISABLED: 禁用状态,即允许所有请求通过,出现失败率达到给定的阈值也不会熔断,不会发生状态转换。

  • METRICS_ONLY: 和DISABLED状态一样,也允许所有请求通过不会发生熔断,但是会记录失败率等信息,不会发生状态转换。

  • FORCED_OPEN: 与DISABLED状态正好相反,启用CircuitBreaker,但是不允许任何请求通过,不会发生状态转换。

下面再对closed、open和half_open 这三种状态的切换做下补充:

  • closed -> open : 关闭状态到熔断状态,当失败的调用率(比如超时、异常等)默认50%,达到一定的阈值服务转为open状态,在open状态下,所有的请求都被拦截;

  • open-> half_open: 当经过一定的时间后,CircubitBreaker中默认为60s服务调用者允许一定的请求到达服务提供者;

  • half_open -> open: 当half_open状态的调用失败率超过给定的阈值,转为open状态;

  • half_open -> closed: 失败率低于给定的阈值则默认转换为closed状态;

3.4 几种服务熔断组件对比

常用的服务熔断,服务降级框架主要有Spring Cloud Hystrix、Spring Cloud Alibaba Sentinel、resilience4j,下面通过几个维度综合对比一下各自的特点,便于加深对各种组件的认识。

对比项SentinelHystrixResilience4j
开源Apache-2.0 licenseApache-2.0 licenseApache-2.0 license
更新更新频繁(latest:2.1.1, Aug 8th 2022)已停更更新较慢(latest:1.7.1, Jun 25th 2021)
特点轻量级,核心库无多余依赖,性能损耗小---基于Java8和函数式编程,轻量级容错库,无多余依赖
隔离策略信号量隔离信号量/线程池隔离信号量隔离
熔断降级策略异常比率/响应时间/异常数异常比率异常比率/响应时间
控制台实时监控、机器发现、规则管理等能力。提供监控查看不提供
系统自适应支持,结合应用的机器负载、CPU 使用率,整体平均响应时间、入口 QPS 和 并发线程数等维度进行限流操做不支持不支持
基于注解的支持支持支持支持
限流基于QPS、调用关系的限流有限的支持支持简单的Rtate Limiter模式

系统自适应

结合应用的机器负载、CPU 使用率,整体平均响应时间、入口QPS和并发线程数等几个维度的监控指标从而决定是否调用进行限流操做

四、springboot整合Resilience4j

上面详细介绍了Resilience4j的理论,接下来通过案例来看下如何在代码中集成并使用Resilience4j。

4.1 集成过程

4.1.1 导入依赖

Resilience4j与springboot整合提供了两个版本的依赖包,springboot2的版本和springboot3的版本,其中sptingboot2的版本java8就可以支持,本文选择sptingboot2的版本依赖。

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>io.github.resilience4j</groupId>
            <artifactId>resilience4j-all</artifactId>
            <version>1.7.0</version>
        </dependency>

        <dependency>
            <groupId>io.github.resilience4j</groupId>
            <artifactId>resilience4j-spring-boot2</artifactId>
            <version>1.7.0</version>
        </dependency>

4.1.2 添加配置文件

基本上Resilience4j的核心功能都可以在配置文件中通过官方提供的各种配置去完成,参考下面的配置信息,结合里面的注释加深对配置项的理解。

resilience4j.circuitbreaker:
  instances:
    backendA:
      registerHealthIndicator: true   # 是否启用健康检查
      slidingWindowSize: 10       #用于计算失败率的滑动窗口大小为10,即最近10次调用失败的情况会被考虑进去
      permittedNumberOfCallsInHalfOpenState: 3 # 断路器半开时允许最大的请求次数
      slidingWindowType: TIME_BASED #配置用于在CircuitBreaker关闭时记录调用结果的滑动窗口类型。 滑动窗口可以是基于计数或基于时间的。
      minimumNumberOfCalls: 5          # 熔断器开始计算失败率之前,至少需要的调用次数为5次
      waitDurationInOpenState: 5s      # 断路器打开后,尝试等待5秒进入半开状态
      failureRateThreshold: 20          # 当失败率达到20%时,断路器会打开,组织进一步的调用
      eventConsumerBufferSize: 10   #用于存储断路器相关事件的缓冲区大小为10,这些事件可用于被监控

#重试策略相关的配置
resilience4j.retry:
  instances:
    backendA:
      maxAttempts: 3              #最大重试次数
      waitDuration: 2s            #每次重试的时候间隔的等待时间
      enableExponentialBackoff: true
      exponentialBackoffMultiplier: 2
      retryExceptions:
        - java.lang.Exception

resilience4j.bulkhead:
  instances:
    backendA:
      maxConcurrentCalls: 10

resilience4j.thread-pool-bulkhead:
  instances:
    backendC:
      maxThreadPoolSize: 11      #配置最大线程池大小
      coreThreadPoolSize: 1     #配置核心线程池大小
      queueCapacity: 1          #配置队列的容量

#限流的配置
resilience4j.ratelimiter:
  instances:
    backendA:               # 限流器的名字
      limitForPeriod: 1     # 一个限制周期内可访问次数
      limitRefreshPeriod: 1s    # 限制周期,每个周期之后,速率限制器将重置回limitForPeriod值
      timeoutDuration: 10ms     # 线程等待允许执行时间
      registerHealthIndicator: true
      eventConsumerBufferSize: 100

server:
  port: 8081

4.1.3 添加配置类

自定义配置类,将配置文件中配置的每一种熔断器对应的项注册到spring的bean容器中,比如在配置文件中有一个实例名称为backendA;

import io.github.resilience4j.common.circuitbreaker.configuration.CircuitBreakerConfigCustomizer;
import io.github.resilience4j.common.ratelimiter.configuration.RateLimiterConfigCustomizer;
import org.springframework.context.annotation.Bean;

public class ResilienceConfig {

    @Bean
    public CircuitBreakerConfigCustomizer circuitBreakerConfigCustomizer() {
        return CircuitBreakerConfigCustomizer
                .of("backendA", builder -> builder.slidingWindowSize(10));
    }

    @Bean
    public RateLimiterConfigCustomizer rateLimiterConfigCustomizer() {
        return RateLimiterConfigCustomizer
                .of("backendA", builder -> builder.limitForPeriod(1));
    }
}

4.1.4 测试业务

在这里我们测试两个场景,第一个场景为重试,第二个场景为限流,对于下面的两个方法做如下的补充说明:

  • @CircuitBreaker,该注解里面有两个属性,name和fallbackMethod;

    • name,即配置文件中配置的那个实例名称;

    • fallbackMethod,出现错误时使用哪个降级方法;

  • @Retry,与@CircuitBreaker注解相同,也是两个相同的属性,具有类似的含义;

    • 一般来说,@CircuitBreaker注解和@Retry可以搭配使用,也可以单独使用@Retry;

import com.congge.entity.User;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
import io.github.resilience4j.retry.annotation.Retry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.Objects;

@Service
public class UserService {

    private Logger logger = LoggerFactory.getLogger(UserService.class);

    @CircuitBreaker(name = "backendA")
    @Retry(name = "backendA")
//    @RateLimiter(name = "backendA", fallbackMethod = "fallback")
    public User retry() {
        logger.info("backendA findUser");
        String res = new RestTemplate().getForObject("http://localhost:8088", String.class);
        if (Objects.nonNull(res)) {
            return new User("remote user", 18, "Man");
        }
        return new User("default user", 22, "Woman");
    }

    @CircuitBreaker(name = "backendA")
    @RateLimiter(name = "backendA",fallbackMethod = "fallback")
    public User limit() {
        return new User("remote user", 18, "Man");
    }

    public User fallback(Throwable e) {
        return new User("降级的用户", 18, "D");
    }
}

控制器类用于测试使用

@RestController
public class UserController {

    @Resource
    private UserService userService;

    @GetMapping("/retry")
    public User retry() {
        return userService.retry();
    }

    @GetMapping("/limit")
    public User limit() {
        return userService.limit();
    }
}

4.1.5 接口测试

重试功能测试,在第一个方法中,远程调用一个不存在的链接,理论上会失败,按照参数配置,调用失败后,会重试3次,如果3次之后仍然失败,则接口抛出异常(或使用降级的方法的返回结果)。

重试接口测试

接口经过一段时间之后失败

同时查看控制台日志输出,不难发现,重试了3次,3次时候输出了异常的堆栈信息。

限流接口测试

调用限流接口,在配置文件中默认的是每秒允许通过一个请求,当我们正常请求接口时,可以正常得到结果。

快速刷接口时,由于方法中添加了降级方法,将会得到降级的响应结果。

4.2 参数解读补充

通过上面的案例演示了使用Resilience4j进行接口的重试或限流操作,只需配置好核心的参数,并且在方法上添加相关的注解即可。

在实际开发中,对Resilience4j的使用,也是重点落在对配置文件中3个模块配置参数的调整,了解这些配置参数的具体含义才能结合实际场景合理使用,具体来说,主要是下面几部分:

  • circuitbreaker,断路器配置;

  • retry,重试配置;

  • ratelimiter,限流配置;

4.2.1 circuitbreaker常用配置参数

circuitbreaker的常用可配置参数项如下

配置参数默认值描述
failureRateThreshold50熔断器关闭状态和半开状态使用的同一个失败率阈值
ringBufferSizeInHalfOpenState10熔断器半开状态的缓冲区大小,会限制线程的并发量,例如缓冲区为10则每次只会允许10个请求调用后端服务
ringBufferSizeInClosedState100熔断器关闭状态的缓冲区大小,不会限制线程的并发量,在熔断器发生状态转换前所有请求都会调用后端服务
waitDurationInOpenState60(s)熔断器从打开状态转变为半开状态等待的时间
automaticTransitionFromOpenToHalfOpenEnabledfalse如果置为true,当等待时间结束会自动由打开变为半开,若置为false,则需要一个请求进入来触发熔断器状态转换
recordExceptionsempty需要记录为失败的异常列表
ignoreExceptionsempty需要忽略的异常列表
recordFailurethrowable -> true自定义的谓词逻辑用于判断异常是否需要记录或者需要忽略,默认所有异常都进行记录
slowCallRateThreshold100以百分比配置阈值。当呼叫持续时间大于等于或大于阈值时,CircuitBreaker 将呼叫视为慢速呼叫。 当慢速呼叫的百分比等于或大于阈值时,CircuitBreaker 转换为打开并开始短路呼叫
slowCallDurationThreshold60000(ms)配置持续时间阈值,超过该阈值呼叫被视为慢速并提高慢速呼叫率。
permittedNumberOfCallsInHalfOpenState10配置 CircuitBreaker 半开时允许的调用次数。
maxWaitDurationInHalfOpenState100配置在 CircuitBreaker 计算错误率或慢速调用率之前所需的最小调用次数(每个滑动窗口周期)。
waitDurationInOpenState100断路器在从打开转换为半打开之前应等待的时间
slidingWindowSize100如果滑动窗口是 COUNT_BASED,则记录并汇总最后一次调用。 如果滑动窗口是TIME_BASED,则记录并汇总最后几秒的调用。slidingWindowSize配置用于在 CircuitBreaker 关闭时记录调用结果的滑动窗口的大小。
slidingWindowTypeCOUNT_BASED配置用于在CircuitBreaker关闭时记录调用结果的滑动窗口类型。 滑动窗口可以是基于计数或基于时间的。

4.2.2 ratelimiter常用配置参数

ratelimiter的常用可配置参数项如下

配置参数默认值描述
timeoutDuration5s线程等待权限的默认等待时间
limitRefreshPeriod500ms权限刷新的时间,每个周期结束后,RateLimiter将会把权限计数设置为limitForPeriod的值
limiteForPeriod一个限制刷新期间的可用权限数

4.2.3 retry常用配置参数

retry的常用可配置参数项如下

配置参数默认值描述
maxAttempts3最大重试次数
waitDuration500ms固定重试间隔
intervalFunctionnumberOfAttempts -> waitDuration用来改变重试时间间隔,可以选择指数退避或者随机时间间隔
retryOnResultPredicateresult -> false自定义结果重试规则,需要重试的返回true
retryOnExceptionPredicatethrowable -> true自定义异常重试规则,需要重试的返回true
retryExceptionsempty需要重试的异常列表
ignoreExceptionsempty需要忽略的异常列表

五、写在文末

熔断、限流与降级作为微服务治理中的重要一环,有必要对其引起重视和关注,而Resilience4j吸收了主流熔断器的优势,具备更为灵活的特点,适用于普通的springboot项目,也能很方便的集成到微服务框架中,值得深入的学习和研究。

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

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

相关文章

巨型犰狳优化算法(Giant Armadillo Optimization,GAO)的无人机三维路径规划(MATLAB)

一、无人机路径规划模型介绍 无人机三维路径规划是指在三维空间中为无人机规划一条合理的飞行路径,使其能够安全、高效地完成任务。路径规划是无人机自主飞行的关键技术之一,它可以通过算法和模型来确定无人机的航迹,以避开障碍物、优化飞行时间和节省能量消耗。 二、算法介…

javase day01笔记

第一天课堂笔记 Java第三代高级语言中的面向对象的语言 b/s 浏览器/服务器c/s 客户端/服务端 1991年詹姆斯高斯林在sun公司开发的Java 常用的dos命令 磁盘操作系统&#xff1a;dos win &#xff0b; r -》 cmd dos命令 切换盘符&#xff1a;直接输入对应盘符目录操作&#x…

【R包开发:入门】 简介+ 包的结构

简介 本书的目的是教你如何开发包&#xff0c;以便你可以写出自己的包&#xff0c;而不只是使用别人的包。 为什么要写一个包&#xff1f; 一个令人信服的理由是&#xff0c;你想要与他人分享代码。把你的代码打成一个包&#xff0c;可以方便他人使用&#xff0c;因为他们像你…

vue中性能优化

目录 1. 编码优化 2. 源码优化 3. 打包优化 4. 利用 Vue Devtools 总结 Vue.js 作为一个强大的前端框架&#xff0c;提供了丰富的功能和工具来帮助开发者构建高效的 Web 应用。然而&#xff0c;在开发过程中&#xff0c;性能优化仍然是一个需要关注的问题。以下是对 Vue.j…

高级IO【select、poll、epoll】

高山仰止&#xff0c;景行行止 文章目录 五种IO模型阻塞I/O非阻塞I/OI/O复用信号驱动I/O异步I/O 同步通信与异步通信同步通信异步通信 非阻塞IO基于fcntl实现setNonblock函数注意事项 IO多路转接—select文件描述符集合timeval结构调用过程返回值缺点和局限性 IO多路转接—poll…

Java共享问题 、synchronized 线程安全分析、Monitor、wait/notify

文章目录 1.共享带来的问题1.1 临界区 Critical Section1.2 竞态条件 Race Condition 2. synchronized语法及理解2.1 方法上的 synchronized 3.变量的线程安全分析3.1.成员变量和静态变量是否线程安全&#xff1f;3.2.局部变量是否线程安全&#xff1f;3.2.1 局部变量线程安全分…

三阶导数在生活中应用

“鲍威尔还表示&#xff0c;美联储将在某个时候放慢&#xff08;利率&#xff09;加息步伐” 这是参考三阶导数&#xff08;贷款义务基础&#xff0c;利率一阶导数&#xff0c;利率变化二阶导数&#xff0c;利率变化速度三阶导数&#xff09;。 是否还有其他有趣的例子&#…

算法详解——leetcode150(逆波兰表达式)

欢迎来看博主的算法讲解 博主ID&#xff1a;代码小豪 文章目录 逆波兰表达式逆波兰表达式的作用代码将中缀表达式转换成后缀表达式文末代码 逆波兰表达式 先来看看leetcode当中的原题 大多数人初见逆波兰表达式的时候大都一脸懵逼&#xff0c;因为与平时常见的表达式不同&am…

华为配置DHCP Snooping防止DHCP Server仿冒者攻击示例

配置DHCP Snooping防止DHCP Server仿冒者攻击示例 组网图形 图1 配置DHCP Snooping防止DHCP Server仿冒者攻击组网图 DHCP Snooping简介配置注意事项组网需求配置思路操作步骤配置文件 DHCP Snooping简介 在一次DHCP客户端动态获取IP地址的过程中&#xff0c;DHCP Snoopi…

基于Vue的娱讯移动端APP前端设计与实现

目 录 摘 要 Abstract 引 言 1绪论 1.1课题背景及目的 1.1.1移动端APP发展简介 3 1.1.2移动端APP的优势 3 1.2前端开发相关技术 1.2.1前端开发工具介绍 3 1.2.2 前端开发相关技术介绍 4 1.3本章小结 2系统分析 2.1功能需求分析 2.2系统工作流程 2.3本章小结 3系统设…

Linux 之七:Linux 防火墙 和进程管理

防火墙 查看防火墙 查看 Centos7 的防火墙的状态 sudo systemctl status firewalld。 查看后&#xff0c;看到active(running)就意味着防火墙打开了。 关闭防火墙&#xff0c;命令为&#xff1a; sudo systemctl stop firewalld。 关闭后查看是否关闭成功&#xff0c;如果…

python的scripts文件夹作用

Windows系统&#xff1a; Scripts文件夹通常位于Python的安装目录下&#xff0c;如C:\Python\Scripts。该文件夹内包含了各种有用的工具&#xff0c;例如pip、virtualenv等&#xff0c;这些工具有助于管理和配置Python环境和依赖包。 Linux系统&#xff1a; 在Linux系统中&…

【大厂AI课学习笔记NO.69】使用开源管理仓库

了解了开源框架&#xff0c;开源项目&#xff0c;今天来学习开源管理仓库。 我们先说Git&#xff0c;开源的版本管理分布式系统。 GitHub&#xff0c;则是世界上最大的代码托管平台&#xff0c;面向开源和私有项目托管。 有的人总是分不清这两个&#xff0c;其实一个是版本管…

凌鲨微应用架构

微应用是静态网页加上凌鲨提供的扩展能力而形成的一种应用&#xff0c;主要特点是开发便捷&#xff0c;安全。 微应用架构 组件说明 名称 说明 微应用 webview窗口&#xff0c;显示web服务器上的页面 接口过滤器 根据权限配置,屏蔽非授权接口访问 接口提供者 tauri注入…

循序渐进丨MogDB 数据库特性之动态数据脱敏机制

数据脱敏是行之有效的数据库隐私保护方案之一&#xff0c;可以在一定程度上限制非授权用户对隐私数据的窥探。动态数据脱敏机制是一种通过定制化脱敏策略来实现对隐私数据保护的技术&#xff0c;可以在保留原始数据的前提下有效地解决非授权用户对敏感信息访问的问题。当管理员…

C#,蛇梯问题(Snake and Ladder Problem)的算法与源代码

1 蛇梯问题 Snake and Ladder Problem 给定一个蛇梯板&#xff0c;找出从源单元格或第一个单元格到达目标单元格或最后一个单元格所需的最小掷骰次数。基本上&#xff0c;玩家可以完全控制掷骰子的结果&#xff0c;并希望找出到达最后一个单元格所需的最小掷骰次数。 如果玩…

基于鳑鲏鱼优化算法(Bitterling Fish Optimization,BFO)的无人机三维路径规划

一、无人机路径规划模型介绍 无人机三维路径规划是指在三维空间中为无人机规划一条合理的飞行路径&#xff0c;使其能够安全、高效地完成任务。路径规划是无人机自主飞行的关键技术之一&#xff0c;它可以通过算法和模型来确定无人机的航迹&#xff0c;以避开障碍物、优化飞行…

gradle下载太慢者超时!国内镜像可以直接下载

# 解决Gradle下载过慢问题的有效方式&#xff1a;使用国内镜像站点 在开发过程中&#xff0c;我们经常会遇到Gradle下载速度缓慢或超时的问题。作为一个强大而流行的构建工具&#xff0c;Gradle是许多项目中必不可少的一部分。然而&#xff0c;由于官方下载地址可能受网络限制…

Windows10/11配置WSL(Ubuntu)环境

文章目录 WSL介绍WSL部署扩展&#xff1a;辅助工具Windosw Terminal安装下载 WSL介绍 传统方式获取Linux操作系统&#xff0c;是安装完整的虚拟机及镜像环境&#xff0c;例如虚拟机VMware 而使用WSL,可以以非常轻量化的方式&#xff0c;得到Linux系统环境 它无需单独虚拟一套硬…

React 19 Cheat Sheet

React 19让构建网站和应用程序变得更容易&#xff0c;更好。有了很酷的新东西&#xff0c;比如React编译器、Actions API和更好的Hooks&#xff0c;编写代码变得更快&#xff0c;管理应用程序的数据变得更简单 React 19让构建网站和应用程序变得更容易&#xff0c;更好。有了很…