Netty学习专栏(二):Netty快速入门及重要组件详解(EventLoop、Channel、ChannelPipeline)
文章目录
- 前言
- 一、快速入门:5分钟搭建Echo服务器
- 二、核心组件深度解析
- 2.1 EventLoop:颠覆性的线程模型
- EventLoop 设计原理
- 核心 API 详解
- 代码实践:完整使用示例
- 2.2 Channel:统一的网络抽象层
- Channel 核心架构
- 核心 API 详解
- 代码实践:完整应用案例
- 2.3 ChannelPipeline:责任链模式的完美实践
- Pipeline 设计原理
- 核心 API 详解
- 事件传播机制
- 总结
前言
在传统Java NIO编程中,开发者需要直面Selector、Channel、ByteBuffer等底层组件,处理线程同步、粘包拆包、资源回收等复杂问题。Netty通过精妙的核心组件设计,将这些底层细节封装为可扩展的高性能框架。本文将从快速入门案例出发,逐层剖析Netty的核心组件设计哲学。
一、快速入门:5分钟搭建Echo服务器
Echo服务器是一种接收客户端请求并原样返回数据的网络服务,常用于网络调试、协议验证和延迟测试。
public class NettyEchoServer {public static void main(String[] args) throws InterruptedException {// 1. 创建线程组(Reactor模型)EventLoopGroup bossGroup = new NioEventLoopGroup(1); // 接收连接EventLoopGroup workerGroup = new NioEventLoopGroup(); // 处理I/Otry {// 2. 服务端启动器ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) // 3. 指定Channel类型.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) {// 4. 责任链模式添加处理器ch.pipeline().addLast(new EchoServerHandler());}});// 5. 绑定端口并启动ChannelFuture future = bootstrap.bind(8080).sync();future.channel().closeFuture().sync();} finally {workerGroup.shutdownGracefully();bossGroup.shutdownGracefully();}}
}// 6. 自定义业务处理器
class EchoServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) {// 7. 直接回写接收到的数据ctx.writeAndFlush(msg); }
}
关键组件解析
EventLoopGroup:Reactor线程组的具象化实现
ServerBootstrap:服务端启动入口
NioServerSocketChannel:TCP协议的Channel封装
ChannelPipeline:处理器责任链容器
ChannelHandler:业务逻辑处理单元
二、核心组件深度解析
2.1 EventLoop:颠覆性的线程模型
基本概念:EventLoop是Netty异步事件驱动模型的核心执行单元,本质为单线程执行器,负责绑定线程与Channel,处理I/O事件、用户任务及定时任务。
传统NIO痛点:
- 需要手动创建Selector线程。
- 读写操作与业务逻辑线程混杂。
- 难以处理Selector空轮询Bug。
Selector在无IO事件时被异常唤醒(select()返回0),导致CPU空转至100%。
while(true) {int readyChannels = selector.select(); // 无事件时异常返回0if(readyChannels == 0) continue; // 死循环
}
Netty解决方案:
// 每个EventLoop绑定一个线程
EventLoopGroup group = new NioEventLoopGroup(2);
group.next().execute(() -> System.out.println(Thread.currentThread().getName()));
- 单线程多路复用:一个EventLoop处理多个Channel的所有I/O事件。
- 无锁化设计:保证Channel操作的线程安全性。
- 任务队列机制:支持定时任务与普通任务调度。
性能对比:在10万并发连接测试中,Netty的EventLoop模型比传统NIO线程池吞吐量提升300%
EventLoop 设计原理
Reactor 模式演进:
Netty 的 EventLoop 基于 Reactor 线程模型,经历了三次演进:单 Reactor 单线程 → 单 Reactor 多线程 → 主从 Reactor 多线程。
Netty 采用主从 Reactor 多线程模型:
// 主 Reactor (处理连接请求)
EventLoopGroup bossGroup = new NioEventLoopGroup(1); // 从 Reactor (处理I/O操作)
EventLoopGroup workerGroup = new NioEventLoopGroup();
核心运行机制:
每个 EventLoop 包含三个核心部分:
- Selector:监听注册的 Channel 事件
- Task Queue:存放普通任务
- Scheduled Task Queue:存放定时任务
核心 API 详解
类继承体系:
io.netty.util.concurrent└─ EventExecutor└─ EventLoop └─ SingleThreadEventLoop└─ NioEventLoop
关键方法说明:
- void execute(Runnable task):用于提交异步任务,适用非I/O操作处理。
- ScheduledFuture<?> schedule(Runnable task, long delay, TimeUnit unit):单次定时任务。
- ScheduledFuture<?> scheduleAtFixedRate(…):固定速率周期任务,适用定时状态上报。
- ScheduledFuture<?> scheduleWithFixedDelay(…):固定间隔周期任务,适用异步批处理。
配置参数:
new NioEventLoopGroup(int nThreads, // 线程数(默认CPU核心数*2)Executor executor, // 自定义线程工厂SelectorProvider selectorProvider // 底层Selector实现
);
代码实践:完整使用示例
混合任务处理:
public class EventLoopDemo {public static void main(String[] args) {EventLoopGroup group = new NioEventLoopGroup(2);// 提交普通任务group.next().execute(() -> {System.out.println("[普通任务] 执行线程: " + Thread.currentThread().getName());});// 提交定时任务ScheduledFuture<?> future = group.next().scheduleAtFixedRate(() -> System.out.println("[定时任务] 时间: " + LocalTime.now()),1, 1, TimeUnit.SECONDS);// 10秒后关闭group.next().schedule(() -> {future.cancel(true);group.shutdownGracefully();}, 10, TimeUnit.SECONDS);}
}
网络应用集成:
serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) {ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) {// 获取当前Channel绑定的EventLoopEventLoop eventLoop = ctx.channel().eventLoop();// 提交耗时任务到业务线程池businessExecutor.execute(() -> {Object result = processData(msg);// 将结果写回原EventLoopeventLoop.execute(() -> ctx.writeAndFlush(result));});}});}});
总结:
Netty 的 EventLoop 通过以下设计实现高性能:
- 线程绑定机制:保证 Channel 操作的线程安全。
- 任务优先级调度:优化 I/O 与任务处理顺序。
- 灵活扩展能力:支持自定义线程模型。
2.2 Channel:统一的网络抽象层
基本概念: Channel是Netty网络通信的核心抽象,封装了底层Socket连接的读写、配置和状态管理能力,支持TCP、UDP、HTTP等多种协议。
传统NIO缺陷:
- API不一致性:SocketChannel与ServerSocketChannelAPI不一致。
- 状态管理缺失:缺少统一的生命周期事件通知。
- 扩展性差:新增协议需完全重新实现。
- 零拷贝支持不足:FileChannel.transferTo()存在平台限制。
Netty的Channel体系:
统一抽象层├── TCP: NioSocketChannel├── UDP: NioDatagramChannel └── 扩展协议: Http2StreamChannel
// 可切换的传输实现
channel = new NioSocketChannel(); // TCP
channel = new OioSocketChannel(); // 阻塞式
channel = new EpollSocketChannel(); // Linux原生Epoll
- 统一API:所有传输类型使用相同接口。
- 零拷贝支持:通过FileRegion实现高效文件传输。
- 细粒度状态管理:通过ChannelFuture监听连接状态变化。
Channel 核心架构
类继承体系:
io.netty.channel├─ Channel│ ├─ AbstractChannel│ │ ├─ AbstractNioChannel│ │ │ ├─ NioSocketChannel│ │ │ └─ NioServerSocketChannel│ │ └─ AbstractOioChannel└─ ChannelConfig
组件关系:
Netty的Channel作为网络通信的核心抽象,通过ChannelPipeline管理一系列ChannelHandler(每个Handler对应一个ChannelHandlerContext),由绑定的EventLoop(关联特定线程)驱动I/O事件处理,通过ChannelConfig控制参数配置,所有异步操作通过ChannelFuture通知结果,形成高效的事件驱动处理链。
核心 API 详解
Channel 关键方法:
- ChannelFuture write(Object msg):异步写入数据,适用发送响应数据。
- Channel flush():立即刷新缓冲区,用于强制数据发送。
- ChannelFuture close(): 安全关闭连接,用于终止通信。
- Channel read():触发读操作,用于流量控制。
- ChannelPipeline pipeline():获取处理链,用于动态修改处理器。
ChannelConfig 配置参数:
// 典型配置示例
channel.config().setConnectTimeoutMillis(3000) // 连接超时.setTcpNoDelay(true) // 禁用Nagle算法.setSoLinger(0) // 关闭时立即释放.setWriteBufferWaterMark(new WriteBufferWaterMark(32*1024, 64*1024));
Nagle算法通过延迟发送小数据包(等待数据积累或ACK响应)以减少网络碎片化,强制数据缓存机制可能导致 20-200ms延迟,对实时性敏感场景造成性能瓶颈。
网络 I/O 全流程解析:
连接建立流程:
1. 创建Channel → 2. 注册到EventLoop → 3. 触发ChannelActive事件 → 4. 加入Pipeline处理链
数据读取流程:
1. 内核数据到达 → 2. EventLoop触发读事件 → 3. 读取到ByteBuf → 4. 传播到Pipeline → 5. 业务Handler处理
数据写出流程:
1. 调用channel.write() → 2. 数据存入发送队列 → 3. EventLoop执行flush → 4. 转换为JDK ByteBuffer → 5. 系统调用写入Socket
代码实践:完整应用案例
自定义Channel初始化:
public class CustomChannelInitializer extends ChannelInitializer<SocketChannel> {@Overrideprotected void initChannel(SocketChannel ch) {// 配置TCP参数ch.config().setTcpNoDelay(true);// 构建处理链ChannelPipeline pipeline = ch.pipeline();pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1024, 0, 4));pipeline.addLast("decoder", new StringDecoder());pipeline.addLast("encoder", new StringEncoder());pipeline.addLast("businessHandler", new BusinessHandler());}
}// 使用示例
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.childHandler(new CustomChannelInitializer());
高级特性:零拷贝文件传输:
public void sendFile(Channel channel, File file) throws IOException {try (RandomAccessFile raf = new RandomAccessFile(file, "r")) {FileRegion region = new DefaultFileRegion(raf.getChannel(), 0, file.length());channel.writeAndFlush(region).addListener(future -> {if (future.isSuccess()) {System.out.println("文件发送成功");} else {future.cause().printStackTrace();}});}
}
状态监听与异常处理:
ChannelFuture connectFuture = bootstrap.connect("127.0.0.1", 8080);
connectFuture.addListener(new ChannelFutureListener() {@Overridepublic void operationComplete(ChannelFuture future) {if (future.isSuccess()) {System.out.println("连接建立成功");future.channel().writeAndFlush("Hello");} else {System.err.println("连接失败: " + future.cause());}}
});// 全局异常处理
pipeline.addLast(new ExceptionHandler() {@Overrideprotected void handleException(ChannelHandlerContext ctx, Throwable cause) {cause.printStackTrace();ctx.close();}
});
关键机制解析:
Channel 注册机制:
// 底层注册逻辑(AbstractChannel)
public final void register(EventLoop eventLoop, ChannelPromise promise) {// 1. 绑定Channel与EventLoopthis.eventLoop = eventLoop;// 2. 执行实际注册eventLoop.execute(() -> {doRegister();pipeline.invokeHandlerAddedIfNeeded();safeSetSuccess(promise);pipeline.fireChannelRegistered();});
}
写缓冲区水位控制:
当待发送数据超过高水位线(默认64KB)时:
- 触发ChannelWritabilityChanged事件
- 自动停止读取新数据(channel.config().setAutoRead(false))
- 待数据量低于低水位线(32KB)后恢复
2.3 ChannelPipeline:责任链模式的完美实践
基本概念: ChannelPipeline 是 Netty 中处理网络事件的核心组件,采用链式模型协调多个处理器(ChannelHandler)的协作。
传统NIO问题
- 编解码器与业务逻辑耦合
- 异常处理路径不清晰
- 协议扩展困难
Netty Pipeline工作机制:
pipeline.addLast("decoder", new StringDecoder()); // 入站处理器
pipeline.addLast("encoder", new StringEncoder()); // 出站处理器
pipeline.addLast("logic", new BusinessHandler()); // 业务处理器
- 双向传播:区分Inbound(入站)与Outbound(出站)事件。
- 动态编排:运行时动态增删处理器。
- 异常冒泡:异常沿Pipeline自动传播。
Pipeline 设计原理
ChannelPipeline 是 Netty 中处理 I/O 事件的核心责任链机制,基于拦截过滤器模式实现。其核心设计特点:
- 双向链表结构: 每个 ChannelHandler 通过 ChannelHandlerContext 连接。
- 事件分方向传播:
- Inbound 事件(如连接建立、数据到达):从 head 流向 tail。
- Outbound 事件(如连接关闭、数据写出):从 tail 流向 head。
- 运行时动态修改: 支持 handler 的热插拔。
核心 API 详解
关键操作方法:
- addFirst():添加到链头。
- addLast():添加到链尾。
- addBefore():在指定handler前添加。
- remove():移除handler。
- replace():替换handler。
特殊处理器类型:
// 共享handler(需标记为@Sharable)
@Sharable
public class SharedHandler extends ChannelInboundHandlerAdapter {}// 懒加载handler(避免重复创建)
pipeline.addLast(new ChannelInitializer<Channel>() {protected void initChannel(Channel ch) {// 实际handler在首次连接时创建}
});
事件传播机制
入站事件流程:
1. channelActive()
2. channelRead()
3. exceptionCaught()↓
head → [Decoder] → [BusinessLogic] → tail
出站事件流程:
1. write()
2. flush()
3. close()↓
tail ← [Encoder] ← [Compressor] ← head
代码示例:完整事件处理:
public class EchoServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelActive(ChannelHandlerContext ctx) {System.out.println("连接建立: " + ctx.channel());}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) {// 入站数据处理String input = (String) msg;System.out.println("收到: " + input);// 触发出站写入(从当前handler向前传播)ctx.writeAndFlush("Echo: " + input);}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {cause.printStackTrace();ctx.close(); // 触发出站关闭}
}
ChannelPipeline 通过以下设计实现高效处理:
- 零拷贝事件传播:避免数据在handler间复制
- 精细的流量控制:通过水位线机制防止OOM
- 热插拔架构:支持运行时动态调整处理链
总结
Netty 通过 EventLoop 实现高效线程调度,以事件驱动模型处理 I/O 操作;Channel 作为网络通信的核心抽象,封装了协议细节与状态管理;ChannelPipeline 以责任链模式组织 ChannelHandler,实现数据编解码、业务逻辑与异常处理的模块化协作。三者形成「事件调度 → 网络操作 → 数据处理」的高效协作链路,解决了传统 NIO 的复杂度与性能瓶颈。
下节预告:我们将深入剖析 ByteBuf 内存管理机制,揭秘 Netty 如何通过「内存池化+零拷贝」优化数据缓冲性能,并对比分析 ChannelHandler 的不同实现类型,演示如何通过 Bootstrap 实现优雅的客户端/服务端启动配置。
相关文章:
Netty学习专栏(二):Netty快速入门及重要组件详解(EventLoop、Channel、ChannelPipeline)
文章目录 前言一、快速入门:5分钟搭建Echo服务器二、核心组件深度解析2.1 EventLoop:颠覆性的线程模型EventLoop 设计原理核心 API 详解代码实践:完整使用示例 2.2 Channel:统一的网络抽象层Channel 核心架构核心 API 详解代码实践…...
27-FreeRTOS的任务管理
一、FreeRTOS的任务概念 在FreeRTOS中,任务(Task)是操作系统调度的基本单位。每个任务都是一个无限循环的函数,它执行特定的功能。任务可以被看作是一个轻量级的线程,具有自己的堆栈和优先级。下面是如何定义一个任务函…...
upload-labs靶场通关详解:第14关
一、分析源代码 这一关的任务说明已经相当于给出了答案,就是让我们上传一个图片木马,可以理解为图片中包含了一段木马代码。 function getReailFileType($filename){$file fopen($filename, "rb");$bin fread($file, 2); //只读2字节fclose…...
supervisor的进程监控+prometheus+alertmanager实现告警
supervisor服务进程监控实现告警 前提:部署了prometheus(配置了rules文件夹),alertmanager,webhook,python3环境 [roottest supervisor_prometheus]# pwd /opt/supervisor_prometheus [roottest supervisor_prometheus]# ls supervisor_exporter.py supervisor_int…...
HarmonyOS 鸿蒙应用开发基础:父组件调用子组件方法的几种实现方案对比
在ArkUI声明式UI框架中,父组件无法直接调用子组件的方法。本文介绍几种优雅的解决方案,并作出对比分析,分析其适用于不同场景和版本需求。帮助开发者在开发中合理的选择和使用。 方案一:Watch装饰器(V1版本适用&#x…...
Enhancing Relation Extractionvia Supervised Rationale Verifcation and Feedback
Enhancing Relation Extraction via Supervised Rationale Verification and Feedback| Proceedings of the AAAI Conference on Artificial Intelligencehttps://ojs.aaai.org/index.php/AAAI/article/view/34631 1. 概述 关系抽取(RE)任务旨在抽取文本中实体之间的语义关...
等离子体隐身技术和小型等离子体防御装置设计
相信大家前不久都看到了关于国防科大团队关于等离子体防御的相关文章,恰好也在做相关的研究,所以想向对这个问题感兴趣的朋友聊一聊这里面的一些基本原理和研究现状。 等离子体与电磁波的相互作用 等离子体会对电磁波产生吸收和反射作用,通常…...
PCB设计教程【入门篇】——电路分析基础-电路定理
前言 本教程基于B站Expert电子实验室的PCB设计教学的整理,为个人学习记录,旨在帮助PCB设计新手入门。所有内容仅作学习交流使用,无任何商业目的。若涉及侵权,请随时联系,将会立即处理 一、电路基本概念 连接线与节点 …...
C++-继承
1.继承的概念及定义 1.1继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象 程序设计的层…...
25.5.22学习总结
ST表(Sparse Table,稀疏表)是一种用于高效解决静态区间最值查询(RMQ)问题的数据结构。其核心思想是通过预处理每个长度为2^j的区间的最值,使得查询时只需合并两个子区间的最值即可得到结果,从而…...
接口自动化测试框架(pytest+allure+aiohttp+ 用例自动生成)
🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 近期准备优先做接口测试的覆盖,为此需要开发一个测试框架,经过思考,这次依然想做点儿不一样的东西。 接口测试是比较讲究效率的…...
FastAPI在 Nginx 和 Docker 环境中的部署
目录 实现示例1. 项目结构2. FastAPI 应用 (app/main.py)3. 依赖文件 (app/requirements.txt)4. Dockerfile5. Nginx 配置 (nginx/nginx.conf)6. Docker Compose 配置 (docker-compose.yml) 使用方法修改代码后更新 实现示例 接下来创建一个简单的示例项目,展示如何…...
08 接口自动化-用例管理框架pytest之fixtrue,conftest.py,allure报告以及logo定制
文章目录 一、使用fixture实现部分前后置1.function级别:在每个函数的前后执行2.class级别:在每个类的前后执行一次3.module级别:在每个模块的前后执行一次4.package、session级别,一般是和connftest.py文件一起使用 二、当fixture的级别为pa…...
Appium+python自动化(二)- 环境搭建—下
简介 我这里已经将android的测试开发环境已经搭建准备完毕。上一篇android测试开发环境已经准备好, 那么接下来就是appium的环境安装和搭建了。 搭建环境安装过程中切勿浮躁,静下心来一个一个慢慢地按照步骤一个个来。 环境装好后,可以用真机…...
浅谈测试驱动开发TDD
目录 1.什么是TDD 2.TDD步骤 3.TDD 的核心原则 4.TDD 与传统开发的对比 5.TDD中的单元测试和集成测试区别 6.总结 1.什么是TDD 测试驱动开发(Test-Driven Development,简称 TDD) 是一种软件开发方法论,核心思想是 “先写测试…...
MVC和MVVM架构的区别
MVC和MVVM都是前端开发中常用的设计模式,都是为了解决前端开发中的复杂性而设计的,而MVVM模式则是一种基于MVC模式的新模式。 MVC(Model-View-Controller)的三个核心部分:模型、视图、控制器相较于MVVM(Model-View-ViewModel)的三个核心部分…...
网络安全-等级保护(等保) 3-1-1 GB/T 28448-2019 附录A (资料性附录)测评力度附录C(规范性附录)测评单元编号说明
附录A (资料性附录)测评力度 A.1 概述 测评力度是在等级测评过程中实施测评工作的力度,体现为测评工作的实际投入程度,具体由测评的广度和深度来反映。测评广度越大,测评实施的范围越大,测评实施包含的测评对象就越多。测评深度…...
MySQL 可观测性最佳实践
MySQL 简介 MySQL 是一个广泛使用的开源关系型数据库管理系统(RDBMS),以其高性能、可靠性和易用性而闻名,适用于各种规模的应用,从小型网站到大型企业级系统。 监控 MySQL 指标是维护数据库健康、优化性能和确保数据…...
深入解析Spring Boot与Redis集成:高效缓存与性能优化
深入解析Spring Boot与Redis集成:高效缓存与性能优化 引言 在现代Web应用中,缓存技术是提升系统性能的重要手段之一。Redis作为一种高性能的内存数据库,广泛应用于缓存、会话管理和消息队列等场景。本文将详细介绍如何在Spring Boot项目中集…...
《C 语言字符串操作从入门到实战(下篇):strncpy/strncat/strstr 等函数原理与实现》
目录 七. strncpy函数的使用与模拟实现 7.1 strncpy函数理解 7.2 strncpy函数使用示例 7.3 strncpy函数模拟实现 八. strncat函数的使用与模拟实现 8.1 strncat函数理解 8.2 strncat函数使用示例 8.3 strncat函数模拟实现 九. strncmp函数的使用 9.1 strncmp函数理…...
百度智能云千帆AppBuilder RAG流程技术文档
一、概述 本文档旨在详细阐述百度智能云千帆AppBuilder的RAG(Retrieval-Augmented Generation,检索增强生成)流程,包括API对接、知识库维护以及文档资料管理等关键环节。通过本流程,开发者可以高效地构建基于大模型的…...
程序编辑器快捷键总结
程序编辑器快捷键总结 函数跳转 函数跳转 Creator : F2VSCode : F12visual Studio : F12...
MySQL中实现大数据量的快速插入
一、SQL语句优化 1. 批量插入代替单条插入 单条插入会频繁触发事务提交和日志写入,效率极低。批量插入通过合并多条数据为一条SQL语句,减少网络传输和SQL解析开销。 -- 低效写法:逐条插入 INSERT INTO table (col1, col2) VALUE…...
从零基础到最佳实践:Vue.js 系列(8/10):《性能优化与最佳实践》
引言 Vue.js 是一个轻量、灵活且易于上手的现代前端框架,因其响应式数据绑定和组件化开发而广受欢迎。然而,随着项目规模的增长,性能问题逐渐显现,例如首屏加载缓慢、页面渲染卡顿、内存占用过高等。性能优化不仅能提升用户体验&…...
欧拉降幂(JAVA)蓝桥杯乘积幂次
这个题可以使用欧拉降幂,1000000007是质数,所以欧拉函数值为1000000006. import java.util.Scanner; // 1:无需package // 2: 类名必须Main, 不可修改public class Main {public static void main(String[] args) {Scanner scanner new Scanner(System…...
Mysql的MVCC机制
MySQL的MVCC机制主要通过以下几个关键要素来工作: 数据版本与隐藏列 - MySQL InnoDB存储引擎会在每行数据中添加几个隐藏列,用于实现MVCC。其中包括 DB_TRX_ID 列,记录最后一次修改该行数据的事务ID; DB_ROLL_PTR 列ÿ…...
spring中的BeanFactoryAware接口详解
一、接口定义与核心作用 BeanFactoryAware 是 Spring 框架提供的一个回调接口,允许 Bean 在初始化阶段获取其所属的 BeanFactory 实例。该接口定义如下: public interface BeanFactoryAware {void setBeanFactory(BeanFactory beanFactory) throws Bea…...
mysql 创建用户,创建数据库,授权
创建一个远程用户 create user test% identified by test1111; 创建一个数据库并指定编码 create database testdb CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; 授权 grant all privileges on testdb.* to test%; 应用更改: FLUSH PRIVILEGES; 注意…...
Android 网络全栈攻略(三)—— 从三方库原理来看 HTTP
前面两篇文章我们介绍了 HTTP 协议的请求方法、请求码以及常用的请求头/响应头的知识。本篇会从 OkHttp 配置的角度来看这些框架是如何实现 HTTP 协议的,目的是加深对 HTTP 的理解,并学习协议是如何落地的。我们会选取 OkHttp 中与协议实现相关的源码作为…...
BlazeMeter录制jmeter脚本
文章目录 chrome安装blazeMeter插件开始录制 chrome安装blazeMeter插件 开始录制 1、点击重置按钮 2、输入名称 3、点击开始录制 4、打开浏览器操作 5、回到录制页面点击stop(注意,不要在第四步操作的那个窗口点停止) 6、点击save 7、保存jmeter脚本 8、将jmeter脚…...
SQL的RAND用法和指定生成随机数的范围
SQL中的RAND函数能够满足多种随机数生成的需求。通过合理地使用种子、结合一些SQL语句,我们可以实现灵活的随机数生成。在数据填充、数据处理、数据分析中经常需要用RAND生成的随机数。 用法1 生成随机浮点数,其返回值在0(包括0)…...
PHP7内核剖析 学习笔记 第七章 面向对象
面向对象编程,简称OOP,是一种程序设计思想。面向对象把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。面向对象一直是软件开发领域内比较热门的话题,它更符合人类看待事物的一般规律。与Java不同,PHP并…...
地信GIS专业关于学习、考研、就业方面的一些问题答疑
整理了地信GIS专业学生问得最多的几个问题:关于GIS专业学习、考研以及就业方面;大家可以一起来探讨一下。 学习方面 1、 作为一名GISer需要哪些核心素养或能力? 答:GIS是个交叉学科,涉及到地理学、地质学、测绘、遥感…...
构建可重复的系统 - SRE 的 IaC 与 CI/CD 基础
构建可重复的系统 - SRE 的 IaC 与 CI/CD 基础 还记得我们在第一篇提到的 SRE 核心原则之一——减少琐事 (Toil) 吗?想象一下手动配置服务器、部署应用程序、管理网络规则……这些任务不仅耗时、重复,而且极易出错。当系统规模扩大时,手动操作很快就会变得难以为继。SRE 的核…...
CQF预备知识:一、微积分 —— 1.2.2 函数f(x)的类型详解
文中内容仅限技术学习与代码实践参考,市场存在不确定性,技术分析需谨慎验证,不构成任何投资建议。 📖 数学入门全解 本教程为复习课程,旨在帮助读者复习数学知识。教程涵盖以下四个主题: 微积分线性代数微…...
PyQt学习系列03-动画与过渡效果
PyQt学习系列笔记(Python Qt框架) 第三课:PyQt的动画与过渡效果 一、动画与过渡效果概述 1.1 动画与过渡的区别 动画(Animation):用于描述对象属性随时间变化的过程(如位置、颜色、大小&…...
偏微分方程数值方法指南及AI推理
偏微分方程(PDE)是我们用来描述科学、工程和金融领域中各种现象的语言——从流体流动和热传递到波的传播和金融衍生品的定价。然而,这些方程的解析解通常难以获得,尤其是在处理复杂几何形状或非线性行为时。这时,数值方…...
flask允许跨域访问如何设置
flask允许跨域访问 在Flask中,允许跨域访问通常涉及到CORS(跨源资源共享)策略。Flask本身并不直接提供CORS支持,但你可以通过安装和使用第三方库如Flask-CORS来轻松实现跨域资源共享。 安装Flask-CORS 首先,你需要安装Flask-CORS。你可以使用pip来安装它: pip instal…...
深度学习模型部署:使用Flask将图像分类(5类)模型部署在服务器上,然后在本地GUI调用。(全网模型部署项目步骤详解:从模型训练到部署再到调用)
个人github对应项目链接: https://github.com/KLWU07/Image-classification-and-model-deployment 1.流程总览 2.图像分类的模型—Alexnet 3.服务器端部署及运行 4.本地PyCharm调用—GUI界面 一、流程总览 本项目方法还是使用Flask 库,与之前一篇机器学…...
在Pycharm中如何安装Flask
(推荐)方法一:在Pycharm中创建项目之后,再安装Flask 1:在创建Pycharm时,解释器类型选择第一个:项目venv(自动生成的虚拟环境),在左下角选择终端(…...
基于Scikit-learn与Flask的医疗AI糖尿病预测系统开发实战
引言 在精准医疗时代,人工智能技术正在重塑临床决策流程。本文将深入解析如何基于MIMIC-III医疗大数据集,使用Python生态构建符合医疗AI开发规范的糖尿病预测系统。项目涵盖从数据治理到模型部署的全流程,最终交付符合DICOM标准的临床决策支…...
解决前端路由切换导致Keycloak触发页面刷新问题
使用window.location.href进行页面跳转时,浏览器会完全刷新页面,这会导致当前的JavaScript上下文被清空。 如果你的登录状态依赖于某些临时存储(如LocalStorage或sessionStorage),而这些存储在页面刷新后未正确初始化或丢失,就会导致用户被认为未登录。触发keycloak再次登录导…...
基于大模型的胫腓骨干骨折全周期预测与治疗方案研究报告
目录 一、引言 1.1 研究背景与意义 1.2 研究目的与创新点 1.3 国内外研究现状 二、大模型技术原理与应用基础 2.1 大模型的基本架构与算法 2.2 医疗数据的收集与预处理 2.2.1 数据收集 2.2.2 数据预处理 2.3 模型训练与优化 2.3.1 模型训练过程 2.3.2 参数调整与超…...
智慧交通的核心引擎-车牌识别接口-车牌识别技术-新能源车牌识别
在数字化与智能化浪潮席卷交通运输领域的今天,车牌识别接口功能正以其精准、高效的特性,成为构建智慧交通体系的关键技术支撑。通过自动采集、识别车牌信息并实现数据互通,该功能已被深度融入交通管理、物流运输、出行服务等多个场景…...
小白的进阶之路系列之三----人工智能从初步到精通pytorch计算机视觉详解上
计算机视觉是教计算机看东西的艺术。 例如,它可能涉及构建一个模型来分类照片是猫还是狗(二元分类)。 或者照片是猫、狗还是鸡(多类分类)。 或者识别汽车出现在视频帧中的位置(目标检测)。 或者找出图像中不同物体可以被分离的位置(全视分割)。 计算机视觉应用在…...
手写简单的tomcat
首先,Tomcat是一个软件,所有的项目都能在Tomcat上加载运行,Tomcat最核心的就是Servlet集合,本身就是HashMap。Tomcat需要支持Servlet,所以有servlet底层的资源:HttpServlet抽象类、HttpRequest和HttpRespon…...
院校机试刷题第九天:P1042乒乓球、回顾代码随想录第二天
定位一下刷题计划:刷题全面——代码随想录过一遍,刷到模拟题——刷洛谷普及组-。所以还是每天刷一个代码随想录,外加两道洛谷,题目先从官方题单【算法1-1】开始。 一、P1042乒乓球 1.解题思路 关键点1:输入形式 输…...
如何在 Mac M4 芯片电脑上卸载高版本的 Node.js
文章目录 一、确认 Node.js 的安装方式二、卸载 Node.js 的通用步骤1. 通过官方安装包(.pkg)安装的 Node.js2. 通过 Homebrew 安装的 Node.js3. 通过 nvm 安装的 Node.js 三、验证是否卸载成功四、推荐使用 nvm 管理 Node.js 版本五、常见问题1. 卸载后仍…...
基础IO详解
FILE 1.FILE是文件的用户级数据结构,创建在堆上 2.FILE里有维护一个用户级缓冲区,这个用户级缓冲区是为了减少系统调用的次数 3.进程一般会有三个标准FILE*流,stdin,stdout,stderr,对应文件描述符一般是…...
QT入门基础
QT作为一个C的GUI框架,编程语法和C都差不多,上手还是比较快的。但是学习一个新的技术,总有一些新的概念是不清楚的,所以需要先了解一下这些概念。 1、QT软件系 QT:安装时会指定某个版本的QT,这个QT指QT库…...