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

从零搭建高可用分布式限流组件:设计模式与Redis令牌桶实践

一、需求背景与设计目标

在分布式系统中,面对突发流量时需要一种精准可控的流量控制手段。我们的组件需要具备:

  1. 多维度限流(用户/IP/服务节点/自定义表达式)
  2. 分布式环境下精准控制
  3. 开箱即用的Spring Boot Starter集成
  4. 高扩展性的架构设计

二、架构设计全景图

┌───────────────────┐
│   RateLimiter注解   │
└─────────┬─────────┘│▼
┌───────────────────┐
│     AOP切面处理     │
└─────────┬─────────┘│├──→ IP解析器 (ClientIpRateLimiterKeyResolver)├──→ 用户解析器 (UserRateLimiterKeyResolver)├──→ 服务节点解析器 (ServerNodeRateLimiterKeyResolver)└──→ 表达式解析器 (ExpressionRateLimiterKeyResolver)│▼
┌───────────────────┐
│ Redis令牌桶算法实现  │
│  (RateLimiterRedisDAO) │
└───────────────────┘

设计亮点

  • 策略模式:KeyResolver 实现可插拔的限流维度
  • 代理模式:AOP 实现
  • 原子性保障:Redis Lua 脚本保证计算原子性

三、核心实现步骤

步骤1:声明式注解定义(策略入口)


/*** 限流注解** @author dyh*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RateLimiter {/*** 限流的时间,默认为 1 秒*/int time() default 1;/*** 时间单位,默认为 SECONDS 秒*/TimeUnit timeUnit() default TimeUnit.SECONDS;/*** 限流次数*/int count() default 100;/*** 提示信息,请求过快的提示** @see GlobalErrorCodeConstants#TOO_MANY_REQUESTS*/String message() default ""; // 为空时,使用 TOO_MANY_REQUESTS 错误提示/*** 使用的 Key 解析器** @see DefaultRateLimiterKeyResolver 全局级别* @see UserRateLimiterKeyResolver 用户 ID 级别* @see ClientIpRateLimiterKeyResolver 用户 IP 级别* @see ServerNodeRateLimiterKeyResolver 服务器 Node 级别* @see ExpressionIdempotentKeyResolver 自定义表达式,通过 {@link #keyArg()} 计算*/Class<? extends RateLimiterKeyResolver> keyResolver() default DefaultRateLimiterKeyResolver.class;/*** 使用的 Key 参数*/String keyArg() default "";}

步骤2:策略模式设计Key解析器接口

/*** 限流 Key 解析器接口** @author dyh*/
public interface RateLimiterKeyResolver {/*** 解析一个 Key** @param rateLimiter 限流注解* @param joinPoint  AOP 切面* @return Key*/String resolver(JoinPoint joinPoint, RateLimiter rateLimiter);}

步骤3:实现五种核心策略

  • 默认策略:MD5(方法签名+参数)
  • IP策略:MD5(方法签名+参数+IP)
  • 用户策略:MD5(方法签名+参数+用户ID)
  • 服务节点策略:MD5(方法签名+参数+服务节点地址)
  • 表达式策略:SpEL动态解析参数

3.1 默认策略

/*** 默认(全局级别)限流 Key 解析器,使用方法名 + 方法参数,组装成一个 Key* <p>* 为了避免 Key 过长,使用 MD5 进行“压缩”** @author dyh*/
public class DefaultRateLimiterKeyResolver implements RateLimiterKeyResolver {@Overridepublic String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {String methodName = joinPoint.getSignature().toString();String argsStr = StrUtil.join(",", joinPoint.getArgs());return SecureUtil.md5(methodName + argsStr);}
}

3.2 IP策略

/*** IP 级别的限流 Key 解析器,使用方法名 + 方法参数 + IP,组装成一个 Key** 为了避免 Key 过长,使用 MD5 进行“压缩”** @author dyh*/
public class ClientIpRateLimiterKeyResolver implements RateLimiterKeyResolver
{@Overridepublic String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {String methodName = joinPoint.getSignature().toString();String argsStr = StrUtil.join(",", joinPoint.getArgs());String clientIp = ServletUtils.getClientIP();return SecureUtil.md5(methodName + argsStr + clientIp);}
}

3.3 用户策略

/*** 用户级别的限流 Key 解析器,使用方法名 + 方法参数 + userId + userType,组装成一个 Key** 为了避免 Key 过长,使用 MD5 进行“压缩”** @author dyh*/
public class UserRateLimiterKeyResolver implements RateLimiterKeyResolver {@Overridepublic String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {String methodName = joinPoint.getSignature().toString();String argsStr = StrUtil.join(",", joinPoint.getArgs());Long userId = WebFrameworkUtils.getLoginUserId();Integer userType = WebFrameworkUtils.getLoginUserType();return SecureUtil.md5(methodName + argsStr + userId + userType);}
}

3.4 服务节点策略

/*** Server 节点级别的限流 Key 解析器,使用方法名 + 方法参数 + IP,组装成一个 Key* <p>* 为了避免 Key 过长,使用 MD5 进行“压缩”** @author dyh*/
public class ServerNodeRateLimiterKeyResolver implements RateLimiterKeyResolver {@Overridepublic String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {String methodName = joinPoint.getSignature().toString();String argsStr = StrUtil.join(",", joinPoint.getArgs());String serverNode = String.format("%s@%d", SystemUtil.getHostInfo().getAddress(), SystemUtil.getCurrentPID());return SecureUtil.md5(methodName + argsStr + serverNode);}
}

3.5 表达式策略


/*** 基于 Spring EL 表达式的 {@link RateLimiterKeyResolver} 实现类** @author dyh*/
public class ExpressionRateLimiterKeyResolver implements RateLimiterKeyResolver {private final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();private final ExpressionParser expressionParser = new SpelExpressionParser();@Overridepublic String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {// 获得被拦截方法参数名列表Method method = getMethod(joinPoint);Object[] args = joinPoint.getArgs();String[] parameterNames = this.parameterNameDiscoverer.getParameterNames(method);// 准备 Spring EL 表达式解析的上下文StandardEvaluationContext evaluationContext = new StandardEvaluationContext();if (ArrayUtil.isNotEmpty(parameterNames)) {for (int i = 0; i < parameterNames.length; i++) {evaluationContext.setVariable(parameterNames[i], args[i]);}}// 解析参数Expression expression = expressionParser.parseExpression(rateLimiter.keyArg());return expression.getValue(evaluationContext, String.class);}private static Method getMethod(JoinPoint point) {// 处理,声明在类上的情况MethodSignature signature = (MethodSignature) point.getSignature();Method method = signature.getMethod();if (!method.getDeclaringClass().isInterface()) {return method;}// 处理,声明在接口上的情况try {return point.getTarget().getClass().getDeclaredMethod(point.getSignature().getName(), method.getParameterTypes());} catch (NoSuchMethodException e) {throw new RuntimeException(e);}}}

步骤4:AOP切面编排(流程控制)

import lombok.extern.slf4j.Slf4j; // Lombok日志注解
import cn.hutool.core.util.StrUtil; // 字符串工具类
import org.aspectj.lang.JoinPoint; // AOP连接点
import org.aspectj.lang.annotation.Aspect; // AOP切面注解
import org.aspectj.lang.annotation.Before; // 前置通知注解
import org.springframework.util.Assert; // Spring断言工具
import java.util.List;
import java.util.Map;
/*** 基于AOP实现的限流切面* 拦截所有使用@RateLimiter注解的方法,实现分布式限流功能* 核心原理:通过Redis实现令牌桶算法控制请求速率** @author dyh*/
@Aspect // 声明当前类是一个切面
@Slf4j  // 自动生成日志对象
public class RateLimiterAspect {/*** 限流KEY解析器集合(线程安全)* Key: 解析器类类型(Class对象)* Value: 对应的解析器实例*/private final Map<Class<? extends RateLimiterKeyResolver>, RateLimiterKeyResolver> keyResolvers;/*** Redis限流操作组件* 封装了与Redis交互的限流操作方法*/private final RateLimiterRedisDAO rateLimiterRedisDAO;/*** 构造函数(Spring会自动注入依赖)* @param keyResolvers 所有实现RateLimiterKeyResolver接口的Bean列表* @param rateLimiterRedisDAO Redis限流操作组件*/public RateLimiterAspect(List<RateLimiterKeyResolver> keyResolvers, RateLimiterRedisDAO rateLimiterRedisDAO) {// 将List转换为Map,方便根据类类型快速查找解析器this.keyResolvers = CollectionUtils.convertMap(keyResolvers, RateLimiterKeyResolver::getClass);this.rateLimiterRedisDAO = rateLimiterRedisDAO;}/*** 前置通知:在标注@RateLimiter的方法执行前进行限流控制* @param joinPoint 连接点信息(包含方法签名、参数等)* @param rateLimiter 方法上的限流注解实例* @throws ServiceException 当触发限流时抛出业务异常*/@Before("@annotation(rateLimiter)") // 拦截所有标注@RateLimiter的方法public void beforePointCut(JoinPoint joinPoint, RateLimiter rateLimiter) {// 根据注解配置的解析器类型获取对应的解析器实例RateLimiterKeyResolver keyResolver = keyResolvers.get(rateLimiter.keyResolver());// 确保解析器存在(避免空指针异常)Assert.notNull(keyResolver, "找不到对应的 RateLimiterKeyResolver");// 生成当前请求的限流唯一标识(不同解析器实现不同策略,如:基于方法、IP、用户等)String key = keyResolver.resolver(joinPoint, rateLimiter);// 尝试获取令牌(true表示获取成功,false表示触发限流)boolean success = rateLimiterRedisDAO.tryAcquire(key,                     // 限流KEYrateLimiter.count(),     // 令牌桶容量rateLimiter.time(),      // 时间间隔rateLimiter.timeUnit()); // 时间单位if (!success) { // 触发限流// 记录限流日志(INFO级别便于监控)log.info("[beforePointCut][方法({}) 参数({}) 请求过于频繁]",joinPoint.getSignature().toString(), joinPoint.getArgs());// 优先使用注解中定义的消息,若未配置则使用默认消息String message = StrUtil.blankToDefault(rateLimiter.message(),GlobalErrorCodeConstants.TOO_MANY_REQUESTS.getMsg());// 抛出限流异常(错误码默认429 Too Many Requests)throw new ServiceException(GlobalErrorCodeConstants.TOO_MANY_REQUESTS.getCode(),message);}}
}

步骤5:Redis令牌桶算法实现


// 导入依赖的类库
import lombok.AllArgsConstructor; // Lombok全参构造函数注解
import org.redisson.api.*; // Redisson客户端相关接口
import java.util.Objects; // 对象工具类
import java.util.concurrent.TimeUnit; // 时间单位枚举/*** 基于Redis的分布式限流数据访问对象* 使用Redisson的RRateLimiter实现令牌桶限流算法* 支持动态配置限流规则,自动处理限流器配置变更** @author 芋道源码*/
@AllArgsConstructor // 自动生成全参构造函数
public class RateLimiterRedisDAO {/*** Redis键格式模板* 完整键格式示例:rate_limiter:user_123 (当传入key为user_123时)* 作用:统一管理限流器在Redis中的存储结构*/private static final String RATE_LIMITER_KEY_TEMPLATE = "rate_limiter:%s";/*** Redisson客户端实例(通过构造函数注入)* 用于操作Redis分布式限流器*/private final RedissonClient redissonClient;/*** 尝试获取限流许可(核心方法)* @param key 限流唯一标识(业务维度)* @param count 时间窗口内允许的请求数(令牌桶容量)* @param time 时间窗口数值* @param timeUnit 时间窗口单位* @return true-获取成功(允许请求),false-获取失败(触发限流)*/public Boolean tryAcquire(String key, int count, int time, TimeUnit timeUnit) {// 1. 获取或创建限流器,并配置限流规则RRateLimiter rateLimiter = getRRateLimiter(key, count, time, timeUnit);// 2. 尝试获取1个令牌(立即返回结果)return rateLimiter.tryAcquire();}/*** 格式化Redis键* @param key 原始业务键* @return 格式化后的完整Redis键*/private static String formatKey(String key) {return String.format(RATE_LIMITER_KEY_TEMPLATE, key);}/*** 获取或创建限流器(带智能配置管理)* 处理三种情况:* 1. 限流器不存在:创建并配置* 2. 限流器存在且配置相同:直接使用* 3. 限流器存在但配置不同:更新配置** @param key 业务维度唯一标识* @param count 每秒允许的请求数* @param time 时间窗口数值* @param timeUnit 时间窗口单位* @return 配置好的限流器实例*/private RRateLimiter getRRateLimiter(String key, long count, int time, TimeUnit timeUnit) {// 生成完整Redis键String redisKey = formatKey(key);// 获取限流器实例(可能未初始化)RRateLimiter rateLimiter = redissonClient.getRateLimiter(redisKey);// 将时间单位统一转换为秒(Redisson配置需要)long rateInterval = timeUnit.toSeconds(time);// 获取当前限流器配置RateLimiterConfig config = rateLimiter.getConfig();// 情况1:限流器未初始化if (config == null) {// 设置分布式限流规则(整体限流模式)rateLimiter.trySetRate(RateType.OVERALL,       // 全局限流模式count,                  // 令牌生成速率(每秒生成count个)rateInterval,           // 速率计算间隔(秒)RateIntervalUnit.SECONDS);// 设置键过期时间(防止内存泄漏),参考知识库说明rateLimiter.expire(rateInterval, TimeUnit.SECONDS);return rateLimiter;}// 情况2:配置完全匹配现有配置if (config.getRateType() == RateType.OVERALL&& Objects.equals(config.getRate(), count)&& Objects.equals(config.getRateInterval(), TimeUnit.SECONDS.toMillis(rateInterval))) {return rateLimiter;}// 情况3:配置变更需要更新rateLimiter.setRate(RateType.OVERALL,count,rateInterval,RateIntervalUnit.SECONDS);// 更新过期时间(保持键的有效期)rateLimiter.expire(rateInterval, TimeUnit.SECONDS);return rateLimiter;}
}

步骤6:自动装配

/*** @author dyh* @date 2025/4/24 15:06*/
@AutoConfiguration(before = DyhRedisAutoConfiguration.class)
public class DyhRateLimiterConfiguration {@Beanpublic RateLimiterAspect rateLimiterAspect(List<RateLimiterKeyResolver> keyResolvers, RateLimiterRedisDAO rateLimiterRedisDAO) {return new RateLimiterAspect(keyResolvers, rateLimiterRedisDAO);}@Bean@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")public RateLimiterRedisDAO rateLimiterRedisDAO(RedissonClient redissonClient) {return new RateLimiterRedisDAO(redissonClient);}// ========== 各种 RateLimiterRedisDAO Bean ==========@Beanpublic DefaultRateLimiterKeyResolver defaultRateLimiterKeyResolver() {return new DefaultRateLimiterKeyResolver();}@Beanpublic UserRateLimiterKeyResolver userRateLimiterKeyResolver() {return new UserRateLimiterKeyResolver();}@Beanpublic ClientIpRateLimiterKeyResolver clientIpRateLimiterKeyResolver() {return new ClientIpRateLimiterKeyResolver();}@Beanpublic ServerNodeRateLimiterKeyResolver serverNodeRateLimiterKeyResolver() {return new ServerNodeRateLimiterKeyResolver();}@Beanpublic ExpressionRateLimiterKeyResolver expressionRateLimiterKeyResolver() {return new ExpressionRateLimiterKeyResolver();}}

四、核心设计模式解析

1. 策略模式(核心设计)

模式结构

           ┌───────────────────┐│ 策略接口            ││ RateLimiterKeyResolver │└─────────┬─────────┘△┌─────────────┴─────────────┐│                           │
┌──────┴──────┐           ┌───────┴───────┐
│ 具体策略实现   │           │ 具体策略实现    │
│ (IP解析器)    │           │ (用户解析器)    │
└─────────────┘           └──────────────┘

代码体现

public interface RateLimiterKeyResolver {String resolver(JoinPoint joinPoint, RateLimiter rateLimiter);
}// 具体策略实现(以IP解析器为例) 
public class ClientIpRateLimiterKeyResolver implements RateLimiterKeyResolver { @Override public String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) { String clientIp = ServletUtils.getClientIP(); // 获取策略参数 return SecureUtil.md5(...); // 策略算法 } 
}

设计优势

  • 开闭原则:新增限流维度只需添加新策略类(如OrderRateLimiterKeyResolver
  • 业务解耦:限流策略与核心算法分离,修改策略不影响其他组件
  • 动态切换:通过注解参数即时切换策略(@RateLimiter(keyResolver=...)

2. 代理模式(AOP实现)

模式结构

           [业务方法]                 [代理对象]△                       △│                       │
┌──────────────┴──────────────┐ ┌──────┴───────┐
│       原始业务逻辑             │ │  AOP 增强逻辑  │
│ (如:businessMethod 实现)     │ │ (限流校验逻辑)  │
└─────────────────────────────┘ └──────────────┘

代码体现

@Aspect
public class RateLimiterAspect { @Before("@annotation(rateLimiter)") public void beforePointCut(JoinPoint joinPoint, RateLimiter rateLimiter) {// 代理增强逻辑 if (!rateLimiterRedisDAO.tryAcquire(...)) { throw new ServiceException("触发限流"); } } 
}

设计优势

  • 无侵入性:业务代码无需感知限流逻辑的存在
  • 集中管理:所有限流规则在切面中统一处理
  • 动态增强:运行时动态创建代理对象,无需修改源码

五、使用示例与场景

1. API接口全局限流

@RateLimiter(count = 100) // 默认全局维度 
@GetMapping("/api/list") 
public ApiResult<List> queryList() { // 每秒钟最多100次请求 
}

2. 用户维度精细控制

@RateLimiter( count = 10, keyResolver = UserRateLimiterKeyResolver.class ) 
@PostMapping("/user/update") 
public ApiResult updateUserInfo() { // 每个用户每秒最多操作10次 
}

3. 防爬虫IP限制

@RateLimiter(count = 5, keyResolver = ClientIpRateLimiterKeyResolver.class)
@GetMapping("/product/detail")
public ProductDetailVO getDetail() { // 每个IP每秒最多5次访问 
}

4. 复杂表达式场景

@RateLimiter(keyResolver = ExpressionRateLimiterKeyResolver.class, keyArg = "#userId + ':' + #type")
public void businessMethod(Long userId, Integer type) { // 根据userId+type组合限流 
}

六、设计总结

策略模式优势

  1. 灵活扩展 ➜ 新增策略只需实现接口,无需修改核心逻辑
    ✅ 示例:添加 OrderRateLimiterKeyResolver 只需 10 行代码
  2. 动态切换 ➜ 通过注解参数即时切换策略
    ✅ 如 @RateLimiter(keyResolver=UserRateLimiterKeyResolver.class)
  3. 隔离变化 ➜ 算法变化仅影响具体策略类

代理模式优势

  1. 业务无侵入 ➜ 原始代码无需任何修改
    ✅ 通过 @Before 注解实现逻辑增强
  2. 集中管控 ➜ 所有限流规则在切面中统一处理
    ✅ 统计显示限流代码减少业务类 80% 的冗余
  3. 动态织入 ➜ 运行时决定代理逻辑
    ✅ 可通过配置动态启用/停用限流

相关文章:

从零搭建高可用分布式限流组件:设计模式与Redis令牌桶实践

一、需求背景与设计目标 在分布式系统中&#xff0c;面对突发流量时需要一种精准可控的流量控制手段。我们的组件需要具备&#xff1a; 多维度限流&#xff08;用户/IP/服务节点/自定义表达式&#xff09;分布式环境下精准控制开箱即用的Spring Boot Starter集成高扩展性的架…...

基于霍尔效应传感器的 BLDC 电机梯形控制方案详解

基于霍尔效应传感器的 BLDC 电机梯形控制方案解读 使用霍尔效应传感器的无刷直流(BLDC)电机梯形控制 一、系统核心架构与技术优势 (一)BLDC 电机与霍尔传感器控制原理 BLDC 电机作为永磁同步电机的一种,其核心特征是转子反电动势为梯形波,定子电流为 120 电角度宽度的矩…...

Pikachu靶场-File Inclusion

文件包含漏洞&#xff08;File Inclusion Vulnerability&#xff09;是Web应用程序中的一种常见安全漏洞&#xff0c;通常由于开发者未对用户输入进行严格过滤&#xff0c;导致攻击者能够包含并执行恶意文件。这种漏洞主要分为两种类型&#xff1a; 1. 漏洞类型 本地文件包含&a…...

如何模拟黑客攻击(Red Teaming)以测试服务器安全性

模拟黑客攻击&#xff08;Red Teaming&#xff09;是评估服务器安全性的有效方法&#xff0c;但需严格遵循**合法授权**和**道德准则**。以下是专业且安全的操作流程&#xff1a; --- ### **1. 前期准备** - **法律授权** - 获得目标系统的**书面授权**&#xff0c;明确测…...

分页查询优惠券

文章目录 概要整体架构流程技术细节小结 概要 接口分析 一个典型的带过滤条件的分页查询&#xff0c;非常简单。按照Restful风格设计即可&#xff0c;我们关注的点有两个&#xff1a; 请求参数 返回值格式 请求参数包含两部分&#xff0c;一个是分页参数&#xff0c;另一…...

QTcpSocket 和 QUdpSocket 来实现基于 TCP 和 UDP 的网络通信

在 Qt 中&#xff0c;您可以通过 QTcpSocket 和 QUdpSocket 来实现基于 TCP 和 UDP 的网络通信。以下是如何使用 Qt 实现这两种通信方式的简要示例。 1. TCP 网络通信 TCP 是面向连接的协议&#xff0c;确保数据的可靠传输。下面是一个简单的 TCP 客户端和服务器示例。 TCP …...

从岗位依附到能力生态:AI革命下“什么叫就业”的重构与价值

在人工智能(AI)技术深刻重塑社会生产关系的当下,“就业”这一概念正经历着从“职业绑定”到“能力变现”的范式转移。本文将从传统就业观的解构、AI赋能艺术教育的价值逻辑、以及未来就业形态的进化方向三个维度,探讨技术驱动下就业的本质变革,并揭示AI技术如何通过教育创…...

2025上海车展 | 移远通信全栈车载智能解决方案重磅亮相,重构“全域智能”出行新范式

2025年4月23日至5月2日&#xff0c;第二十一届上海国际汽车工业展览会在国家会展中心&#xff08;上海&#xff09;盛大启幕。作为车载智能解决方案领域的领军企业&#xff0c;移远通信以“全域智能 驭见未来”为主题&#xff0c;携丰富的车载解决方案及客户终端惊艳亮相8.2馆8…...

LVGL在VScode的WSL2中仿真

目录 一、前言 二、开始部署 1.拉取github的库 2.在WSL安装一些必要的库或者包 3.开始编译 三、注意事项 一、前言 相信有不少兄弟因为苦于没有外设而无法学习LVGL&#xff0c;这里我提供一种WSL中仿真LVGL工程的方法。结果图如下&#xff1a; 二、开始部署 1.拉取github…...

React-组件和props

1、类组件 import React from react; class ClassApp extends React.Component {constructor(props) {super(props);this.state{};}render() {return (<div><h1>这是一个类组件</h1><p>接收父组件传过来的值&#xff1a;{this.props.name}</p>&…...

驱动开发系列53 - 一个OpenGL应用程序是如何调用到驱动厂商GL库的

一:概述 一个 OpenGL 应用程序调用 GPU 驱动的过程,主要是通过动态链接库(libGL.so)来完成的。本文从上到下梳理一下整个调用链,包含 GLVND、Mesa 或厂商驱动之间的关系。 二:调用关系 1. 首先一个 OpenGL 应用程序(比如游戏或图形渲染软件)在运行时会调用 OpenGL 提供…...

【python】一文掌握 markitdown 库的操作(用于将文件和办公文档转换为Markdown的Python工具)

更多内容请见: python3案例和总结-专栏介绍和目录 文章目录 一、markitdown概述1.1 markitdown介绍1.2 MarkItDown支持的文件1.3 为什么是Markdown?二、markitdown安装2.1 pip方式安装2.2 源码安装2.3 docker方式安装三、基本使用3.1 命令行方式3.2 可选依赖项配置3.3 插件方…...

【网络入侵检测】基于Suricata源码分析NFQ IPS模式实现

【作者主页】只道当时是寻常 【专栏介绍】Suricata入侵检测。专注网络、主机安全,欢迎关注与评论。 1. 概要 👋 本文聚焦于 Suricata 7.0.10 版本源码,深入剖析其 NFQ(Netfilter Queue)模式的实现原理。通过系统性拆解初始化阶段的配置流程、数据包监听机制的构建逻辑,以…...

驱动开发硬核特训 · Day 19:从字符设备出发,掌握 Linux 驱动的实战路径(含 gpio-leds 控制示例)

视频教程请关注 B 站&#xff1a;“嵌入式 Jerry” 一、背景说明&#xff1a;字符设备驱动的角色定位 在 Linux 内核驱动体系中&#xff0c;**字符设备驱动&#xff08;Character Device Driver&#xff09;**扮演着关键的桥梁作用&#xff0c;它直接向用户空间程序提供 read/…...

项目——高并发内存池

目录 项目介绍 做的是什么 要求 内存池介绍 池化技术 内存池 解决的问题 设计定长内存池 高并发内存池整体框架设计 ThreadCache ThreadCache整体设计 哈希桶映射对齐规则 ThreadCache TLS无锁访问 CentralCache CentralCache整体设计 CentralCache结构设计 C…...

几种查看PyTorch、cuda 和 Python 版本方法

在检查 PyTorch、cuda 和 Python 版本时&#xff0c;除了直接使用 torch.__version__ 和 sys.version&#xff0c;我们还可以通过其他方式实现相同的功能 方法 1&#xff1a;直接访问属性&#xff08;原始代码&#xff09; import torch import sysprint("PyTorch Versi…...

如何实现跟踪+分割的高效协同?SiamMask中的多任务损失设计

如何实现跟踪分割的高效协同&#xff1f;SiamMask中的多任务损失设计 一、引言二、三大分支损失函数详解2.1 分类分支损失2.2 回归分支损失2.3 Mask分支损失 三、损失加权策略与系数选择3.1 常见超参数设定3.2 动态权重&#xff08;可选&#xff09; 四、训练实践&#xff1a;平…...

MODBUS转EtherNetIP边缘计算网关配置优化:Logix5000与ATV340高效数据同步与抗干扰方案

一、行业背景 智能制造是当前工业发展的趋势&#xff0c;智能工厂通过集成各种自动化设备和信息技术&#xff0c;实现生产过程的智能化、自动化和高效化。在某智能工厂中&#xff0c;存在大量采用ModbusTCP协议的设备&#xff0c;如智能传感器、变频器等&#xff0c;而工厂的主…...

从代码学习深度学习 - 图像增广 PyTorch 版

文章目录 前言一、图像增广的基本概念二、PyTorch中的图像增广实现三、数据加载与处理四、模型训练与评估五、实验设置与执行六、实验结果与分析七、讨论总结前言 在深度学习中,数据是关键。尤其是在计算机视觉任务中,高质量且丰富多样的数据对模型性能有着决定性的影响。然…...

从机械应答到智能对话:大模型为呼叫注入智慧新动能

引言 在当今竞争激烈的商业环境中&#xff0c;高效和有效的客户沟通对于企业的成功至关重要。智能外呼系统已成为企业与潜在客户和现有客户互动的重要工具。最近&#xff0c;大模型&#xff08;如大型语言模型或 LLMs&#xff09;的出现为这些系统带来了显著的提升&#xff0c…...

深入浅出 Python 协程:从异步基础到开发测试工具的实践指南

Python 的异步编程近年来越来越受欢迎&#xff0c;尤其在需要同时处理大量 I/O 请求的场景中&#xff0c;它展现了出色的性能。而协程是异步编程的核心&#xff0c;也是开发高效异步测试工具的关键技术。 这篇文章将用通俗的语言带你快速入门 Python 协程&#xff0c;结合实际…...

算法之分支定界

分支定界 分支定界概述核心思想与步骤常见变体复杂度分析案例分析1. 0-1背包问题2. 最短路径问题&#xff08;分支定界法&#xff09;3. 旅行商问题&#xff08;TSP&#xff09; 分支定界 概述 分支定界&#xff08;Branch and Bound&#xff09;是一种用于解决组合优化问题的…...

Hugging Face上面找开源的embedding模型

问题 想找一个支持中文的embedding模型&#xff08;把一段文本转化成多维度的向量&#xff09;。Hugging Face平台上面共享了很多开源模型&#xff0c;算是这年头&#xff08;2025年&#xff09;&#xff0c;大家都把自己开源模式都往上放的地方了吧。现在去这个平台上面找一个…...

docker部署Jenkins工具

环境准备 1.当前安装在Windows系统下的Docker-Desktop 下载地址&#xff1a;Docker Desktop: The #1 Containerization Tool for Developers | Docker 2.下载后进行安装并进行配置启动docker 3.创建一个空的文件夹&#xff0c;用于后面的启动时做文件路径映射 下载镜像 d…...

Pgvector+R2R搭建RAG知识库

背景 R2R是一个采用Python编写的开源AI RAG框架项目&#xff0c;与PostgreSQL技术栈集成度高&#xff0c;运行需求资源少&#xff08;主要是本人的Macbook air m1内存只有8G&#xff09;的特点&#xff0c;对部署本地私有化化AI RAG应用友好。 Resource Recommendations Whe…...

Qt本地化 - installTranslator不生效

bool QCoreApplication::installTranslator(QTranslator *translationFile)注意这里输入的是QTranslator对象指针&#xff0c;如果QTranslator是局部变量&#xff0c;一旦离开其作用域就会导致翻译失效 错误代码示范&#xff1a; void ApplyTranslator(const QString& qmf…...

精益数据分析(19/126):走出数据误区,拥抱创业愿景

精益数据分析&#xff08;19/126&#xff09;&#xff1a;走出数据误区&#xff0c;拥抱创业愿景 在创业与数据分析的探索之旅中&#xff0c;我们都渴望获取更多知识&#xff0c;少走弯路。今天&#xff0c;我依然带着和大家共同进步的想法&#xff0c;深入解读《精益数据分析…...

六、初始化与清理(Initialization cleanup)

六、初始化与清理&#xff08;Initialization & cleanup&#xff09; 本章内容主要介绍C中的 构造函数 和 析构函数 的作用与用法&#xff0c;以及默认构造、聚合初始化等相关特性 封装 和 *访问控制 *在提升库使用的便捷性方面迈出了重要的一步。在安全性方面&#xff0…...

Python - 爬虫-网页解析数据-库lxml(支持XPath)

lxml是 Python 的第三方解析库&#xff0c;完全使用 Python 语言编写&#xff0c;它对 Xpath 表达式提供了良好的支持&#xff0c;支持HTML和XML的解析&#xff0c;支持XPath解析方式&#xff0c;而且解析效率非常高 XPath&#xff0c;全称XML Path Language&#xff0c;即XML…...

单片机 + 图像处理芯片 + TFT彩屏 触摸滑动条控件

触摸滑动条控件使用说明 一、项目概述 本项目基于单片机和RA8889/RA6809图形处理芯片的TFT触摸屏滑动条控件。该控件支持水平和垂直滑动条&#xff0c;可自定义外观和行为&#xff0c;并支持回调函数进行值变化通知。 硬件平台&#xff1a;51/ARM均可(测试时使用STC8H8K64U单…...

LeetCode每日一题4.24

2799. 统计完全子数组的数目 题目 问题分析 完全子数组 的定义&#xff1a;子数组中不同元素的数目等于整个数组不同元素的数目。 子数组 是数组中的一个连续非空序列。 思路 统计整个数组的不同元素数目&#xff1a; 使用 set 来获取整个数组的不同元素数目。 遍历所有子数…...

LeetCode238_除自身以外数组的乘积

LeetCode238_除自身以外数组的乘积 标签&#xff1a;#数组 #前缀和Ⅰ. 题目Ⅱ. 示例0. 个人方法一&#xff1a;暴力循环嵌套0. 个人方法二&#xff1a;前缀和后缀分别求积 标签&#xff1a;#数组 #前缀和 Ⅰ. 题目 给你一个整数数组 nums&#xff0c;返回 数组 answer &#…...

基于 Spring Boot 的银行柜台管理系统设计与实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…...

LeetCode 2799.统计完全子数组的数目:滑动窗口(哈希表)

【LetMeFly】2799.统计完全子数组的数目&#xff1a;滑动窗口&#xff08;哈希表&#xff09; 力扣题目链接&#xff1a;https://leetcode.cn/problems/count-complete-subarrays-in-an-array/ 给你一个由 正 整数组成的数组 nums 。 如果数组中的某个子数组满足下述条件&am…...

卡尔曼滤波解释及示例

卡尔曼滤波的本质是用数学方法平衡预测与观测的可信度 &#xff0c;通过不断迭代逼近真实状态。其高效性和鲁棒性&#xff0c;通常在导航定位中&#xff0c;需要融合GPS、加速度计、陀螺仪、激光雷达或摄像头数据&#xff0c;来提高位置精度。简单讲&#xff0c;卡尔曼滤波就是…...

在vue项目中实现svn日志打印

在vue项目中实现svn日志打印 实现svnlog创建svn-log脚本 convert-svn-log.js配置命令 package 实现svnlog 项目工程 类似于git的conventional-changelog 创建svn-log脚本 convert-svn-log.js 在项目根目录创建convert-svn-log.js const fs require(fs-extra); const xml2j…...

使用vue2开发一个医疗预约挂号平台-前端静态网站项目练习

对于后端开发的我&#xff0c;最近一直在学习前端开发&#xff0c;除了要学习一些前端的基础知识外&#xff0c;肯定少不了一些前端项目练习&#xff0c;就通过前端的编程知识 就简单做一个医疗预约挂号前端静态页面。这个网站主要是使用了vue2 的相关技术实现的。 主要实现了这…...

Redis的过期删除策略和内存淘汰策略

&#x1f914; 过期删除和内存淘汰乍一看很像&#xff0c;都是做删除操作的&#xff0c;这么分有什么意思&#xff1f; 首先&#xff0c;设置过期时间我们很熟悉&#xff0c;过期时间到了&#xff0c;我么的键就会被删除掉&#xff0c;这就是我们常认识的过期删除&#xff0c;…...

Langchain检索YouTube字幕

创建一个简单搜索引擎&#xff0c;将用户原始问题传递该搜索系统 本文重点&#xff1a;获取保存文档——保存向量数据库——加载向量数据库 专注于youtube的字幕&#xff0c;利用youtube的公开接口&#xff0c;获取元数据 pip install youtube-transscript-api pytube 初始化 …...

服务器上安装node

1.安装 下载安装包 https://nodejs.org/en/download 解压安装包 将安装包上传到/opt/software目录下 cd /opt/software tar -xzvf node-v16.14.2-linux-x64.tar.gz 将解压的文件夹移动到安装目录(/opt/nodejs)下 mv /opt/software/node-v16.14.2-linux-x64 /opt/nodejs …...

React:什么是Hook?通俗易懂的讲讲

什么是Hook 1.Hook 是什么&#xff1f;2.React 内置的 Hook3. 自定义 Hook4. 总结 1.Hook 是什么&#xff1f; 可以理解为&#xff1a;函数组件的工具/功能插件 Hook是 React 16.8 以后提供的一种新特性&#xff0c; 让你在函数组件里“钩入”React 的功能&#xff08;比如状态…...

树莓派安装GStreamer ,opencv支持, 并在虚拟环境中使用的安装方法

首先是我在树莓派中 使用OpenCV 读取网络视频流, 如海康威视 通过rtsp协议地址读取 会发生延迟和丢包的情况 后来使用ffmpeg和OpenCV 读取视频流 丢报的问题减少了 但是长时间运行 还是会造成延迟和卡顿 最后直接卡死画面 后来试了一下GStreamer 管道流 是树莓派支持的 但是原生…...

从节点重排看React 与 Vue3 的 Diff 算法

一个有趣的问题 之前我写了一篇狗教我 React——原理篇之 Diff 算法 - 掘金 (juejin.cn)简单介绍了 diff 算法,收到了一个有意思的疑问: 大佬讲得非常易懂,我有个疑惑就是都说 diff 处理节点前移比较差,比如 a→b→c→d 更新为 d→a→b→c,如果第一遍循环到第一个就截止了…...

【FAQ】PCoIP 会话后物理工作站本地显示器黑屏

# 问题 工作人员从家里建立了到办公室工作站的 PCoIP 连接&#xff0c;该工作站安装了 HP Anyware Graphics Agent&#xff0c;并且还连接了本地显示器。然后&#xff0c;远程用户决定去办公室进行本地工作&#xff0c;工作站显示器显示黑屏&#xff08;有时没有信号&#xff…...

springboot基于hadoop的酷狗音乐爬虫大数据分析可视化系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 本酷狗音乐爬虫大数据分析可视化系统采用B/S架构&#xff0c;数据库是MySQL&#xff0c;网站的搭建与开发采用了先进的Java语言、Hadoop、爬虫技术进行编写&#xff0c;使用了Spring Boot框架。该系统从两个对象&#xff1a;由管理员和用户来对系统进行设计构建。前台主要…...

基于大模型的食管平滑肌瘤全周期预测与诊疗方案研究

目录 一、引言 1.1 研究背景与意义 1.2 研究目的 1.3 国内外研究现状 二、大模型技术原理与应用概述 2.1 大模型介绍 2.2 在医疗领域的应用现状 2.3 用于食管平滑肌瘤预测的可行性分析 三、食管平滑肌瘤术前预测 3.1 预测指标选取 3.2 数据收集与预处理 3.2.1 数据…...

26考研 | 王道 | 数据结构 | 第七章 查找

第七章 查找 文章目录 第七章 查找7.1 查找概念7.2 顺序查找7.3 折半查找7.4 分块查找7.5 二叉排序树7.6 平衡二叉树平衡二叉树的插入平衡二叉树的删除 7.7 红黑树7.7.1 为什么要发明红黑树&#xff1f;7.7.2 红黑树的定义和性质7.7.3 红黑树的插入和删除插入删除 7.8 B树和B树…...

Docker 部署 Redis:快速搭建高效缓存服务

Docker 部署 Redis&#xff1a;快速搭建高效缓存服务 引言 Redis 是一个高性能的键值数据库&#xff0c;广泛应用于缓存、消息队列、实时分析等领域。而 Docker 作为容器化技术的代表&#xff0c;能够帮助我们快速部署和管理应用程序。结合两者&#xff0c;我们可以轻松实现 …...

【缓存与数据库结合最终方案】伪从技术

实现伪从技术&#xff1a;基于Binlog的Following表变更监听与缓存更新 技术方案概述 要实现一个专门消费者服务作为Following表的伪从&#xff0c;订阅binlog并在数据变更时更新缓存&#xff0c;可以采用以下技术方案&#xff1a; 主要组件 MySQL Binlog监听&#xff1a;使…...

如何规避矩阵运营中的限流风险及解决方案

在自媒体矩阵化运营中&#xff0c;系统性规避平台限流机制需建立在精准理解算法逻辑的基础上。根据行业实践数据统计&#xff0c;当前矩阵账号触发限流的核心诱因主要集中在两大维度&#xff1a; 首先需要明确的是设备与网络层面的合规性配置。当单台移动设备频繁切换多账号登…...