主流熔断方案选型指南

主流熔断方案选型

1. Netflix Hystrix (经典但已停止维护)

适用场景:传统Spring Cloud项目,需要快速集成熔断功能

优点

  • 成熟稳定,社区资源丰富

  • 与Spring Cloud Netflix套件无缝集成

  • 提供熔断、降级、隔离等完整功能

缺点

  • 已停止维护

  • 配置相对复杂

2. Resilience4j (推荐替代方案)

适用场景:新项目或替代Hystrix的项目

优点

  • 轻量级,函数式编程风格

  • 模块化设计(熔断、限流、重试、降级等可单独使用)

  • 持续维护更新

缺点

  • 社区生态相对Hystrix较小

Spring Cloud OpenFeign 默认整合的是 Hystrix(已废弃) 或 Resilience4j,取决于 Spring Cloud 版本。

  • Spring Cloud 2020.x 之后

    • Hystrix 移除

    • 推荐使用 Resilience4j 作为 Feign 的容错机制

3. Sentinel (阿里开源)

适用场景:需要丰富流量控制功能的分布式系统(例如流控、熔断、热点、授权、系统规则)

优点

  • 丰富的流量控制手段(熔断、限流、系统保护)

  • 实时监控和控制台

  • 阿里大规模生产验证

缺点

  • 学习曲线较陡

  • 文档主要为中文

 熔断选型概览

选型技术/框架特点适用场景
HystrixNetflix Hystrix(已维护停止)经典、成熟、线程隔离,配置复杂,Spring Cloud 2020+ 已移除老项目维护
Resilience4jJava8+ 函数式,轻量无线程池隔离新项目推荐,性能优Spring Boot/Spring Cloud 2020+
SentinelAlibaba Sentinel规则丰富,适合流控+熔断,适配 Dubbo、Spring Cloud微服务高并发治理
Spring Cloud CircuitBreakerSpring Cloud 封装,默认整合 Resilience4j 或 Sentinel标准方案与 Spring Cloud 配合使用

选型建议

  1. 传统项目维护:如果已经是Spring Cloud Netflix技术栈,继续使用Hystrix

  2. 新项目:推荐使用Resilience4j,它更现代且维护良好

  3. 高流量复杂场景:考虑Sentinel,特别是有丰富流量控制需求的系统

一、hystrix实现

1.添加配置文件application.yml

# application.yml
hystrix:command:GlobalCircuitBreaker:execution:isolation:thread:timeoutInMilliseconds: 5000circuitBreaker:requestVolumeThreshold: 20sleepWindowInMilliseconds: 10000errorThresholdPercentage: 50threadpool:default:coreSize: 50maxQueueSize: 1000queueSizeRejectionThreshold: 500

命令属性 (hystrix.command.GlobalCircuitBreaker)

  1. execution.isolation.thread.timeoutInMilliseconds: 5000

    • 设置命令执行的超时时间为5000毫秒(5秒)

    • 如果命令执行超过这个时间,将被标记为超时失败

  2. circuitBreaker.requestVolumeThreshold: 20

    • 熔断器触发的最小请求数量阈值(滚动窗口内)

    • 只有在20个请求之后,熔断器才会根据错误率判断是否开启

  3. circuitBreaker.sleepWindowInMilliseconds: 10000

    • 熔断器开启后的休眠时间(10秒)

    • 熔断开启后,经过这段时间会允许一个测试请求尝试访问服务

  4. circuitBreaker.errorThresholdPercentage: 50

    • 错误百分比阈值(50%)

    • 当滚动窗口内请求的错误率超过这个百分比时,熔断器将开启

线程池属性 (hystrix.threadpool.default)

  1. coreSize: 50

    • 线程池核心线程数

    • 表示可以同时处理的最大并发请求数

  2. maxQueueSize: 1000

    • 线程池队列最大容量

    • 当所有核心线程都忙时,请求会被放入队列,直到达到此上限

  3. queueSizeRejectionThreshold: 500

    • 队列拒绝阈值

    • 即使maxQueueSize是1000,当队列达到500时就会开始拒绝新请求

    • 这是为防止队列过满而设置的安全阀值

2.添加Application上开启注解

@EnableCircuitBreaker  // 启用Hystrix断路器
@EnableHystrixDashboard // 可选:启用Hystrix仪表盘
public class AuthApplication {@BeanRestTemplate restTemplate() {return new RestTemplate();}public static void main(String[] args) {log.info("启动授权模块...............................................");SpringApplication.run(AuthApplication.class, args);}
}

3. 自定义注解,方便使用

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CustomHystrix {String groupKey() default "DefaultGroup";String commandKey() default "";String fallbackMethod() default "";/*** 设置命令执行的超时时间为3000毫秒(5秒)* 如果命令执行超过这个时间,将被标记为超时失败* @return*/int timeout() default 3000;boolean circuitBreaker() default true;/*** 熔断器触发的最小请求数量阈值(滚动窗口内)** 只有在20个请求之后,熔断器才会根据错误率判断是否开启* @return*/int requestVolumeThreshold() default 20;/*** 熔断器开启后的休眠时间(10秒)** 熔断开启后,经过这段时间会允许一个测试请求尝试访问服务* @return*/int sleepWindow() default 5000;/*** 错误百分比阈值(50%)** 当滚动窗口内请求的错误率超过这个百分比时,熔断器将开启* @return*/int errorThresholdPercentage() default 50;boolean semaphore() default false;
}

 4, 创建Hystrix切面

import com.cbim.auth.annotion.CustomHystrix;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.exception.HystrixRuntimeException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;@Aspect
@Component
@ConditionalOnClass(HystrixCommand.class)
public class HystrixAspect {// 默认配置private static final HystrixCommand.Setter defaultSetter = HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("DefaultGroup")).andCommandKey(HystrixCommandKey.Factory.asKey("DefaultCommand")).andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(3000).withCircuitBreakerRequestVolumeThreshold(20).withCircuitBreakerSleepWindowInMilliseconds(5000));@Around("@annotation(com.cbim.auth.annotion.CustomHystrix)")public Object hystrixCommand(ProceedingJoinPoint joinPoint) throws Throwable {Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();CustomHystrix annotation = method.getAnnotation(CustomHystrix.class);// 动态配置HystrixCommand.Setter setter = buildSetter(annotation);return new HystrixCommand<Object>(setter) {@Overrideprotected Object run() throws Exception {try {return joinPoint.proceed();} catch (Throwable throwable) {throw new Exception(throwable);}}@Overrideprotected Object getFallback() {try {if (!annotation.fallbackMethod().isEmpty()) {Method fallbackMethod = joinPoint.getTarget().getClass().getMethod(annotation.fallbackMethod(), method.getParameterTypes());return fallbackMethod.invoke(joinPoint.getTarget(), joinPoint.getArgs());}return null;} catch (Exception e) {throw new HystrixRuntimeException(HystrixRuntimeException.FailureType.COMMAND_EXCEPTION,this.getClass(),"Fallback failure",e,null);}}}.execute();}private HystrixCommand.Setter buildSetter(CustomHystrix annotation) {return HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(annotation.groupKey())).andCommandKey(HystrixCommandKey.Factory.asKey(annotation.commandKey())).andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(annotation.timeout()).withCircuitBreakerEnabled(annotation.circuitBreaker()).withCircuitBreakerRequestVolumeThreshold(annotation.requestVolumeThreshold()).withCircuitBreakerSleepWindowInMilliseconds(annotation.sleepWindow()).withCircuitBreakerErrorThresholdPercentage(annotation.errorThresholdPercentage()).withExecutionIsolationStrategy(annotation.semaphore() ?HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE :HystrixCommandProperties.ExecutionIsolationStrategy.THREAD));}
}

5. 在userServiceImpl中

	@CustomHystrix(groupKey = "OrderService",fallbackMethod = "getOrderFallback",timeout = 2000)public String health() {try {Thread.sleep(5000);} catch (InterruptedException e) {}log.info("health check");return "success";}public String getOrderFallback() {return "被熔断了,请稍后重试";}

6, 进行测试

GET http://localhost:9999/health

二、 Resilience4j

核心模块

  1. resilience4j-circuitbreaker - 断路器模式

    • 防止应用程序在远程服务/资源故障时不断尝试执行可能失败的操作

    • 提供三种状态:关闭、打开和半开

    • 支持自定义失败率阈值、等待时间和环形缓冲区大小

  2. resilience4j-ratelimiter - 速率限制

    • 控制对某些操作的调用频率

    • 支持自定义限制刷新周期、限制持续时间和超时设置

  3. resilience4j-bulkhead - 舱壁隔离

    • 限制并发执行的数量

    • 提供两种实现:

      • 信号量隔离(SemaphoreBulkhead)

      • 固定线程池隔离(ThreadPoolBulkhead)

  4. resilience4j-retry - 自动重试

    • 为失败的操作提供自动重试机制

    • 支持自定义重试次数、等待间隔和异常条件

  5. resilience4j-timelimiter - 超时控制(仅仅只能在异步任务中使用

    • 为异步操作设置时间限制

    • 防止长时间运行的操作阻塞调用者

执行顺序:Retry → CircuitBreaker → RateLimiter → Bulkhead

思考

一、 ratelimiter 和Bulkhead是否有冲突?

不冲突

模式作用控制维度
Bulkhead (舱壁隔离)限制并发数量,并隔离资源并发调用数(同一时刻允许的最大请求数)
RateLimiter (限流)限制单位时间的请求次数,保护服务免受过载QPS 或 TPS(单位时间允许的请求数)
  • RateLimiter:限流保护,避免流量超标

  • Bulkhead:并发隔离,防止某服务独占资源

二、Bulkhead 和数据库连接池是否重复

Bulkhead 和数据库连接池的区别与联系

维度Bulkhead数据库连接池
本质作用应用层的并发调用隔离,限制方法级别同时执行的调用数连接资源的复用与管理,控制最大数据库连接数
控制范围微服务线程(或者调用)层面数据库连接资源层面
工作目标防止某个接口/服务过载导致线程池或业务资源耗尽限制数据库最大连接数,防止数据库过载
触发点请求进入服务时,根据配置限制并发数量请求申请数据库连接时,根据连接池大小控制
重叠部分可能重叠限制调用并发数控制实际连接数量
是否重复不算重复,是应用层和资源层的多层保护-

为什么 Bulkhead 不等于数据库连接池,且二者都必不可少?

  • 数据库连接池 限制最大连接数,保障数据库端资源不被耗尽。

  • Bulkhead 在业务调用层限制并发,防止线程池被过度占用,避免线程等待数据库连接时线程积压,造成系统阻塞甚至雪崩。

举例:
假设数据库连接池大小是 10,若没有 Bulkhead 限制,系统可能会有 100 个线程同时请求数据库,导致大量线程在等待连接,线程池耗尽。

加上 Bulkhead 限制为 20,业务接口最多允许 20 个并发调用访问数据库,从而保护线程池和数据库连接池都不被耗尽。

  • Bulkhead 与数据库连接池是不同层次的保护机制,彼此互补,不冲突不重复

  • 设计时需要合理设置两者参数,协同保护微服务的线程资源和数据库资源

在微服务中防止某个业务占用完整的数据库连接池。

三、retry 重试和 ribbon是否重复?

1. 两者的区别
Resilience4j Retry:
  • 应用层面:在业务逻辑层或服务调用层实现

  • 功能全面:支持自定义重试策略(固定间隔、指数退避等)

  • 异常过滤:可配置针对特定异常才重试

  • 上下文感知:可以获取重试次数等上下文信息

  • 组合弹性:可与熔断、限流等其他弹性模式组合使用

Ribbon Retry:
  • 网络层面:在HTTP客户端层实现

  • 功能基础:主要处理网络层面的瞬时故障

  • 自动重试:对连接失败、超时等自动重试

  • 负载均衡:与Ribbon的负载均衡策略结合

2. 是否重复?

不完全是重复,而是不同层次的容错机制:

  • Ribbon重试解决的是"网络层面"的瞬时故障(如TCP连接失败、请求超时)

  • Resilience4j Retry解决的是"业务层面"的临时故障(如依赖服务返回5xx错误)

四、RateLimiter限流与Gateway限流的关系

1. 两者的区别

Resilience4j RateLimiter:

  • 应用级别:保护单个服务实例

  • 精细控制:可针对不同方法/接口设置不同限流规则

  • 快速失败:超出限制立即拒绝或等待

  • 组合弹性:可与熔断、重试等组合使用

Gateway限流(如Spring Cloud Gateway RedisRateLimiter):

  • 全局级别:在API网关层实现

  • 集群限流:基于Redis等实现分布式限流

  • 入口控制:保护整个系统入口

  • 网关特性:与路由、鉴权等网关功能集成

2. 是否重复?

不是重复,而是不同层次的流量控制:

  • Gateway限流是"全局第一道防线",防止流量洪峰冲击系统

  • Resilience4j限流是"服务内部精细控制",防止单个服务过载

  • Ribbon重试:快速重试(ms级),解决网络抖动

  • Resilience4j重试:带退避策略(s级),解决服务暂时不可用

实现

1,添加配置文件application.yml

resilience4j:circuitbreaker:instances:userService:registerHealthIndicator: true  # 是否注册健康指标(供Actuator监控)failureRateThreshold: 50     # 失败率阈值百分比,达到此值将触发熔断minimumNumberOfCalls: 2      # 计算失败率前所需的最小调用次数automaticTransitionFromOpenToHalfOpenEnabled: true  # 是否自动从OPEN转为HALF_OPENwaitDurationInOpenState: 5s   # OPEN状态持续时间,之后尝试转为HALF_OPENpermittedNumberOfCallsInHalfOpenState: 3  # HALF_OPEN状态下允许的调用次数slidingWindowType: TIME_BASED # 滑动窗口类型(COUNT_BASED基于调用次数,TIME_BASED基于时间)slidingWindowSize: 4        # 滑动窗口大小(基于次数则为调用次数,基于时间则为秒数)recordExceptions:             # 记录为失败的异常列表- org.springframework.web.client.HttpServerErrorException- java.io.IOException- java.util.concurrent.TimeoutException- java.lang.RuntimeExceptionignoreExceptions:            # 忽略不计为失败的异常列表- com.cbim.exception.CbimExceptionretry:instances:userServiceRetry:maxAttempts: 3              # 最大重试次数(包括初始调用)waitDuration: 500ms         # 重试之间的等待时间retryExceptions:            # 触发重试的异常列表- org.springframework.web.client.ResourceAccessException- java.lang.RuntimeExceptionignoreExceptions:- java.lang.IllegalArgumentExceptionratelimiter:instances:userServiceRateLimiter:limitForPeriod: 10          # 限制每个刷新周期内的调用数量limitRefreshPeriod: 1s      # 限制刷新周期timeoutDuration: 100ms      # 等待获取许可的最大时间bulkhead:instances:userServiceBulkhead:maxConcurrentCalls: 2      # 最大并发调用数maxWaitDuration: 0       # 尝试进入舱壁时的最大等待时间timelimiter:instances:userServiceTimeLimiter:timeoutDuration: 1s         # 方法调用超时时间cancelRunningFuture: true   # 是否取消正在执行的Future
management:endpoint:health:show-details: always  # 显示详细信息group:circuitbreakers:include: circuitBreakers  # 创建专门的分组endpoints:web:exposure:include: health,circuitbreakers  # 暴露所需端点health:circuitbreakers:enabled: true  # 启用熔断器健康指示器
logging:level:io.github.resilience4j: DEBUGorg.springframework.aop: DEBUG

2.在pom文件中添加依赖

        <!-- Resilience4j核心依赖 --><dependency><groupId>io.github.resilience4j</groupId><artifactId>resilience4j-spring-boot2</artifactId><version>1.7.1</version></dependency><dependency><groupId>io.github.resilience4j</groupId><artifactId>resilience4j-circuitbreaker</artifactId><version>1.7.1</version></dependency><dependency><groupId>io.github.resilience4j</groupId><artifactId>resilience4j-retry</artifactId><version>1.7.1</version></dependency><dependency><groupId>io.github.resilience4j</groupId><artifactId>resilience4j-ratelimiter</artifactId><version>1.7.1</version></dependency><dependency><groupId>io.github.resilience4j</groupId><artifactId>resilience4j-bulkhead</artifactId><version>1.7.1</version></dependency><dependency><groupId>io.github.resilience4j</groupId><artifactId>resilience4j-timelimiter</artifactId><version>1.7.1</version></dependency><!-- Spring AOP支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>

3.编写controller代码

package com.cbim.order.controller;import com.cbim.auth.service.UserService;
import com.cbim.order.annotion.Resilient;
import io.github.resilience4j.bulkhead.BulkheadFullException;
import io.github.resilience4j.bulkhead.annotation.Bulkhead;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
import io.github.resilience4j.retry.annotation.Retry;
import io.github.resilience4j.timelimiter.annotation.TimeLimiter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.cbim.order.entity.User;
import org.springframework.web.client.ResourceAccessException;import javax.annotation.Resource;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;@RestController
@RequestMapping("/users")
@Slf4j
public class UserController {@Resourceprivate UserService userService;/*** for i in {1..20}; do curl http://172.19.80.1:9997/users/3; done* @param id* @return*/@GetMapping("/{id}")
//    @Resilient(fallbackMethod = "getUserFallback")@CircuitBreaker(name = "userService", fallbackMethod = "getUserFallback")@RateLimiter(name = "userServiceRateLimiter")@Bulkhead(name = "userServiceBulkhead")public ResponseEntity<User> getUser(@PathVariable Long id){User user = userService.getUserById(id);return ResponseEntity.ok(user);}// 多个fallback方法可以根据异常类型区分处理private ResponseEntity<User> getUserFallback(Long id, Exception e) {log.warn("Fallback triggered for user id: {}, exception: {}", id, e.getClass().getSimpleName());User fallbackUser = new User(id, "Fallback User", "fallback@example.com");return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS).body(fallbackUser);}private ResponseEntity<User> getUserFallback(Long id, BulkheadFullException e) {log.warn("Bulkhead full for user id: {}", id);User fallbackUser = new User(id, "System Busy", "try.again.later@example.com");return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body(fallbackUser);}public ResponseEntity<User> getUserFallback(Long id, Throwable t){log.warn("Fallback called for user id {} due to {}", id, t.toString());return ResponseEntity.ok(new User(23L, "Fallback User", "fallback@example.com"));}/*** TimeLimiter 仅仅只能使用异步函数,同步函数无法使用* @param id* @return*/@TimeLimiter(name = "userServiceTimeLimiter", fallbackMethod = "getUserFallback2")@GetMapping("/TL/{id}")public CompletableFuture<ResponseEntity<User>> getUser2(@PathVariable Long id){return CompletableFuture.supplyAsync(() -> {if (id == 0) {throw new RuntimeException("Simulated failure");}User user = userService.getUserById(id);return ResponseEntity.ok(user);});}public CompletableFuture<ResponseEntity<User>> getUserFallback2(Long id, Throwable t){log.warn("Fallback called due to {}", t.toString());return CompletableFuture.completedFuture(ResponseEntity.ok(new User(0L, "Fallback User", "fallback@example.com")));}}

4. service 和其实现代码

public interface UserService {User getUserById(Long id);
}
@Slf4j
@RefreshScope
@Service
public class UserServiceImpl implements UserService {private AtomicInteger counter = new AtomicInteger(0);@Override@Retry(name = "userServiceRetry")public User getUserById(Long id)  {int attempt = counter.incrementAndGet();System.out.println("Attempt: " + attempt);try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}if (id % 3 == 0) { // 模拟30%失败率throw new RuntimeException("Simulated error");}return new User(id, "qinqingqing01", "123456");}
}

5.进行测试验证

for i in {1..11}; do curl http://172.19.80.1:9997/users/3; done

for i in {1..11}; do curl http://172.19.80.1:9997/users/TL/1; done

在测试之前需要确定断路器是否生效

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

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

相关文章

Django中get()与filter()对比

在 Django 中&#xff0c;get() 和 filter() 是 QuerySet API 中用于检索数据的两个核心方法&#xff0c;它们的功能和使用场景有明显区别。以下是详细对比&#xff1a; 1. 核心区别特性get()filter()返回值单个对象&#xff08;模型实例&#xff09;查询集&#xff08;QuerySe…

MySQL锁(一) 概述与分类

1.1 MySQL锁的由来 客户端发往 MySQL 的一条条 SQL 语句&#xff0c;实际上都可以理解成一个个单独的事务&#xff08;一条sql语句默认就是一个事务&#xff09;。而事务是基于数据库连接的&#xff0c;每个数据库连接在 MySQL 中&#xff0c;又会用一条工作线程来维护&#x…

PyTorch里的张量及张量的操作

张量的简介 张量是多重线性映射在给定基下的坐标表示&#xff0c;可视为向量和矩阵的泛化。 0 维张量&#xff1a;标量&#xff08;如 5&#xff09;1 维张量&#xff1a;向量&#xff08;如 [1, 2, 3]&#xff09;2 维张量&#xff1a;矩阵&#xff08;如 [[1, 2], [3, 4]]&…

向量数据库Faiss vs Qdrant全面对比

Faiss vs Qdrant 全面对比表 向量数据库是一种相对较新的方式,用于与来自不透明机器学习模型(如深度学习架构)派生的抽象数据表示进行交互。这些表示通常被称为向量或嵌入(embeddings),它们是用于训练机器学习模型完成诸如情感分析、语音识别、目标检测等任务的数据的压…

2025年AIR SCI1区TOP,缩减因子分数阶蜣螂优化算法FORDBO,深度解析+性能实测

目录1.摘要2.蜣螂优化算法DBO原理3.改进策略4.结果展示5.参考文献6.代码获取7.算法辅导应用定制读者交流1.摘要 传统DBO存在探索与开发能力失衡、求解精度低以及易陷入局部最优等问题。因此&#xff0c;本文提出了带有缩减因子分数阶蜣螂优化算法&#xff08;FORDBO&#xff0…

爬虫逆向之JS混淆案例(全国招标公告公示搜索引擎 type__1017逆向)

案例https://ctbpsp.com/#/ 截至2025.07.19可用 定位加密位置 加密位置&#xff1a; 定位方式&#xff0c;XHR&#xff0c;跟栈 跟栈 QL打断点&#xff0c;重新断住 分析为&#xff0c;一个函数传入四个参数 var QL QI[d9(Nv.mQ)](QJ, Qh, Qv, this[d9(Nv.m9)][0xa1a * …

Hive常用命令总结

一、数据库操作 -- 创建数据库&#xff08;默认路径&#xff09; CREATE DATABASE IF NOT EXISTS myhive;-- 指定路径创建数据库 CREATE DATABASE myhive2 LOCATION /myhive2;-- 查看数据库信息 DESC DATABASE myhive;-- 删除数据库&#xff08;强制删除表&#xff09; DROP DA…

Spring整合MyBatis详解

Spring整合MyBatis详解一、整合优势与核心思路1.1 整合优势1.2 核心整合思路二、环境搭建与依赖配置2.1 开发环境2.2 Maven依赖配置三、整合配置&#xff08;核心步骤&#xff09;3.1 数据库配置文件&#xff08;db.properties&#xff09;3.2 Spring配置文件&#xff08;sprin…

Windows CMD(命令提示符)中最常用的命令汇总和实战示例

CMD命令汇总 下面是 Windows CMD&#xff08;命令提示符&#xff09;中最常用的命令汇总&#xff0c;共 30 个&#xff0c;包含说明和典型代码示例&#xff0c;适合日常开发、系统操作、文件管理、网络诊断等场景。一、文件与目录操作&#xff08;最常用&#xff09;命令说明示…

嵌入式硬件篇---舵机(示波器)

舵机是一种高精度的角度控制执行器件&#xff0c;广泛应用于机器人、航模、自动化设备等领域。其核心特点是能通过控制信号精准定位到特定角度&#xff08;通常范围为 0-180&#xff0c;部分可到 360 连续旋转&#xff09;。常见的舵机类型可根据结构、控制方式、用途等维度划分…

嵌入式硬件篇---按键

按键是电子系统中最基础的人机交互部件&#xff0c;通过机械或电子方式实现电路通断或状态切换。根据结构和工作原理的不同&#xff0c;常见按键可分为机械按键、薄膜按键、触摸按键等&#xff0c;以下详细介绍其工作原理、应用场景及电路特点&#xff1a;一、机械按键&#xf…

试用SAP BTP 06:AI服务-Data Attribute Recommendation

创建实例 方法一&#xff1a;BTP主控室-子账户-服务市场 输入实例配置信息&#xff0c;下一步 不用参数&#xff0c;下一步 审核实例&#xff0c;点击创建 实例创建完成后&#xff0c;创建服务键值 输入键值名称&#xff0c;点击 创建 方法二&#xff08;建议&#xff09;&…

训诂学中的“形音义互求”对NLP、知识图谱、注意力机制的启示

一、训诂学与现代人工智能结合的学术价值与技术潜力1. ​​训诂学的核心优势与AI语义分析的契合点​​训诂学作为中国传统学术中研究古代文献语义的核心学科&#xff0c;其方法论和理论框架对自然语言处理&#xff08;NLP&#xff09;的深层语义分析具有深刻的启发性和技术补充…

http基础一

1. HTTP是什么&#xff1f; HTTP&#xff08;超文本传输协议&#xff0c;HyperText Transfer Protocol&#xff09;是一种用于从万维网服务器传输超文本到本地浏览器的协议。它是无状态的客户端-服务器协议&#xff0c;通常在Web浏览器和Web服务器之间用于传输网页、图片、视频…

西门子 S7-1500 系列 PLC CPU 选型全指南:从类型到实战

在西门子 S7-1500 系列 PLC 的系统构建中&#xff0c;CPU 作为核心控制单元&#xff0c;其选型直接决定了自动化系统的性能、功能扩展性和适用场景。本文将系统解析 S7-1500 系列 CPU 的类型划分、核心参数、典型型号功能及选型流程&#xff0c;助你精准匹配工业控制需求。一、…

PaddleOCR 与 PaddleX 调试

PaddleOCR 与 PaddleX 调试1.安装1.1 环境准备1.2用Conda创建虚拟环境2.测试2.1发票测试2.2 手写汉字识别3.PaddleOCR 与 PaddleX 对比3.1 基于 PaddleX 部署 OCR 服务1.安装 PP OCR 文档 1.1 环境准备 根据自己操作系统按网上指导安装 ccache ccache --version是否已安装 …

imx6ull-系统移植篇11——U-Boot 移植(下)

目录 前言 移植过程 添加开发板默认配置文件 添加开发板对应的头文件 添加开发板对应的板级文件夹 修改Makefile 文件 修改imximage.cfg 文件 修改Kconfig 文件 修改MAINTAINERS 文件 修改 U-Boot 图形界面配置文件 编译 uboot LCD 驱动修改 修改源文件 修改头文…

30天打牢数模基础-模拟退火算法讲解

二、完整Python代码 import random import mathdef rastrigin(x, y):"""二维Rastrigin函数&#xff08;目标函数&#xff0c;需最小化&#xff09;参数&#xff1a;x: 自变量xy: 自变量y返回&#xff1a;函数值f(x,y)"""return 20 x**2 y**2 …

论文阅读 - FastInst

文章目录1 概述2 模型说明2.1 总体架构2.2 轻量pixel decoder2.3 实例激活引导的Query2.4 双路径更新策略2.5 GT掩码引导学习2.6 损失函数3 效果1 概述 FastInst是一种基于query的实时实例分割方法&#xff0c;它能以32.5FPS的实时速度在COCO测试集上达到40.5的AP。在实例分割…

Elasticsearch 9.x 高可用集群部署教程(3 主节点 + 3 数据节点)

Elasticsearch 9.x 高可用集群部署教程(3 主节点 + 3 数据节点) 1. 集群架构规划 生产环境中的 Elasticsearch 集群需要高可用性和容错能力。以下是基于 3 主节点 + 3 数据节点的架构规划: 节点分布: 主节点(Master Nodes):3 台(master-node-1, master-node-2, maste…