Websocket——心跳检测
1. 前言:为什么需要心跳机制?
在现代的实时网络应用中,保持客户端和服务端的连接稳定性是非常重要的。尤其是在长时间的网络连接中,存在一些异常情况,导致服务端无法及时感知到客户端的断开,可能造成不必要的资源浪费,甚至是服务端的潜在错误。为了避免这种情况,我们需要一种机制来确保连接的有效性,这就是“心跳机制”。
心跳机制的必要性
心跳机制的作用在于周期性地检测连接是否仍然活跃。简单来说,心跳就像人类的心跳一样,不断“跳动”,如果在规定的时间内没有收到心跳信号,服务端就可以判断客户端可能已经断开连接,从而主动释放资源或者做出其他处理。
异常断开连接的场景
在正常情况下,前端和后端的连接断开是可以通过调用相关方法来通知对方的。例如,当用户关闭浏览器或者点击“退出”按钮时,前端可以主动向服务端发送断开连接的请求,服务端也可以通过监听断开事件来进行清理工作。
然而,如果用户的浏览器突然崩溃、网络中断或者关闭页面时,前端无法发送断开请求,服务端也无法及时感知到客户端已经下线。在这种情况下,服务端就需要一个手段来周期性地检查连接是否还存在。
服务端如何通过心跳保持客户端状态
为了应对这种情况,心跳机制便应运而生。心跳的基本原理是客户端定时发送一个简单的信号(通常是一个空的数据包)到服务端。服务端通过检测这个信号是否按时到达来判断客户端是否仍然连接。如果在规定时间内没有收到心跳包,服务端就认为该客户端可能已经断开,并可以主动关闭连接或执行其他操作。
Netty 作为一个高性能的网络框架,内置了非常方便的心跳机制实现工具——IdleStateHandler
。通过这个工具,开发者可以非常方便地设置心跳检测的时间间隔,以及如何处理空闲状态,从而确保网络连接的健康和稳定。
小结
心跳机制在分布式应用、即时通讯、在线游戏等场景中是非常关键的,它帮助服务端及时发现并处理客户端断开的情况,避免资源的浪费和潜在的服务异常。接下来,我们将深入介绍 Netty 如何利用心跳机制来维持连接的稳定性。
2. Netty 心跳机制的实现原理
Netty 提供了 IdleStateHandler
组件,它是处理心跳机制的关键工具。这个处理器能够帮助我们自动监测连接的空闲状态,并且根据设定的时间间隔触发心跳事件,从而帮助服务端检测客户端是否还保持连接。
2.1 IdleStateHandler 的作用
IdleStateHandler
是 Netty 提供的一个特殊的 ChannelHandler,主要作用是根据指定的时间,自动检测连接的空闲状态。它通过配置三个时间参数来定义空闲状态:
- readerIdleTime:如果在指定的时间内没有读取到数据,触发空闲事件;
- writerIdleTime:如果在指定的时间内没有写入数据,触发空闲事件;
- allIdleTime:如果在指定的时间内既没有读也没有写,触发空闲事件。
通常情况下,我们会使用 readerIdleTime 来进行心跳检测。也就是说,客户端需要定期发送数据包(通常是心跳包)给服务端,确保在规定时间内,服务端能够检测到客户端的活动。如果服务端在设定的时间内没有收到心跳包,就会触发相应的空闲事件(如 IdleStateEvent
),然后服务端可以采取关闭连接等措施。
2.2 工作原理
Netty 的心跳机制的工作过程通常如下:
- 客户端:每隔一定时间(如 10 秒),客户端向服务端发送一个“心跳包”,该包通常是一个简单的请求或一个空的数据包,目的是告诉服务端“我还活着”。
- 服务端:服务端在接收到客户端的心跳包后,更新连接的活跃状态,并且继续等待客户端的心跳信号。
- 超时检测:如果在规定的时间(如 30 秒)内,服务端没有收到客户端的心跳包,就会触发
IdleStateEvent
,并根据配置的事件类型,执行相关的处理逻辑。 - 断开连接:当服务端检测到客户端超过了心跳的最大空闲时间后,会主动断开连接,释放资源,避免无效连接占用资源。
2.3 Netty 实现步骤
通过 IdleStateHandler
实现心跳机制的步骤如下:
- 创建
IdleStateHandler
:在管道(Pipeline)中添加IdleStateHandler
,并配置读、写或总空闲时间。 - 自定义事件处理器:当空闲时间触发时,
IdleStateHandler
会触发IdleStateEvent
事件,开发者可以通过自定义事件处理器来处理这些事件。 - 关闭连接:当空闲事件触发时,服务端可以根据具体的业务逻辑决定是否关闭连接或执行其他操作。
2.4 IdleStateHandler
配置实例
假设我们希望每 30 秒检测一次连接,如果 30 秒内没有收到客户端的数据(读空闲),则认为该连接不再活跃,主动断开连接。那么我们可以在 Netty 服务器的 ChannelPipeline
中这样配置:
// 30秒内没有读数据即认为连接空闲,触发读空闲事件
pipeline.addLast(new IdleStateHandler(30, 0, 0, TimeUnit.SECONDS));
在这里,30
表示如果在 30 秒内没有接收到任何读操作的数据包,Netty 会触发一个 IdleStateEvent
,而 0
表示我们不关心写空闲和总空闲的状态。
小结
通过 IdleStateHandler
,Netty 提供了非常便捷的机制来处理心跳事件,确保服务端能够及时发现客户端是否断开。接下来的部分,我们将更深入地探讨如何自定义事件处理器,以及如何根据空闲事件的触发来处理连接的关闭或其他业务逻辑。
3. 自定义处理空闲事件
在使用 IdleStateHandler
配置了心跳检测后,我们需要编写一个自定义的事件处理器来响应空闲事件的触发。这个处理器将会监听并处理由 IdleStateHandler
触发的 IdleStateEvent
,并根据实际需求采取相应的操作。
3.1 IdleStateEvent
介绍
IdleStateEvent
是 Netty 提供的一个事件对象,表示连接进入了空闲状态。它由 IdleStateHandler
触发,常见的事件类型有:
reader_idle
:表示连接在指定的时间内没有读取到任何数据,即“读取空闲”;writer_idle
:表示连接在指定的时间内没有写入任何数据,即“写入空闲”;all_idle
:表示连接在指定的时间内既没有读也没有写,即“完全空闲”。
通常我们关心的主要是 reader_idle
类型的事件,因为我们希望通过客户端定期发送心跳包,服务端来验证连接是否活跃。
3.2 自定义事件处理器 NettyWebSocketServerHandler
接下来,我们编写一个 NettyWebSocketServerHandler
类,来处理客户端的请求并处理空闲事件。
public class NettyWebSocketServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {// 这里可以处理业务逻辑,比如接收来自客户端的数据包super.channelRead(ctx, msg);}@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {// 判断是否是 IdleStateEvent 空闲事件if (evt instanceof IdleStateEvent) {IdleStateEvent event = (IdleStateEvent) evt;// 处理读空闲事件if (event.state() == IdleState.READER_IDLE) {System.out.println("连接空闲,关闭连接:无数据读取!");// 如果超时没有读数据,认为该连接断开,关闭连接ctx.close(); // 关闭连接}}}
}
在上面的代码中,我们实现了 userEventTriggered
方法来处理 IdleStateEvent
事件。当事件类型为 READER_IDLE
(即读取空闲事件)时,我们输出日志并关闭连接。此时,服务端通过调用 ctx.close()
关闭连接,释放相关资源。
3.3 将 NettyWebSocketServerHandler
添加到管道
在 Netty
服务器的 ChannelPipeline
中,添加自定义的 NettyWebSocketServerHandler
处理器,使得它能处理客户端的空闲事件。
public class NettyWebSocketServer {public void start() throws InterruptedException {// 设置事件处理器链EventLoopGroup bossGroup = new NioEventLoopGroup(1); // 用于接收客户端连接EventLoopGroup workerGroup = new NioEventLoopGroup(); // 用于处理读写操作try {ServerBootstrap b = new ServerBootstrap();b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();// 添加空闲状态检测处理器,配置30秒没有读操作触发事件pipeline.addLast(new IdleStateHandler(30, 0, 0, TimeUnit.SECONDS));// 添加自定义的事件处理器来处理空闲事件pipeline.addLast(new NettyWebSocketServerHandler());}});// 绑定端口,启动服务器b.bind(8090).sync().channel().closeFuture().sync();} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
}
在 ChannelInitializer
中,我们首先添加了 IdleStateHandler
,配置了读空闲的时间为 30 秒。然后,我们添加了自定义的 NettyWebSocketServerHandler
来处理空闲事件。
3.4 处理空闲事件后进行用户下线操作
除了关闭连接外,我们还可以在空闲事件发生时进行更复杂的操作,例如清理用户会话、推送离线通知等。
假设我们有一个用户管理的类来保存当前活跃的 WebSocket 连接,当连接空闲时,我们不仅关闭连接,还可以将该用户从在线列表中移除。
public class UserManager {private static Map<String, Channel> activeUsers = new ConcurrentHashMap<>();public static void addUser(String userId, Channel channel) {activeUsers.put(userId, channel);}public static void removeUser(String userId) {activeUsers.remove(userId);}
}public class NettyWebSocketServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {if (evt instanceof IdleStateEvent) {IdleStateEvent event = (IdleStateEvent) evt;if (event.state() == IdleState.READER_IDLE) {// 这里假设可以通过 channel 获取用户的 IDString userId = (String) ctx.channel().attr(UserSession.USER_ID).get();System.out.println("用户 " + userId + " 超时,关闭连接!");// 移除该用户UserManager.removeUser(userId);// 关闭连接ctx.close();}}}
}
在这个修改版的 NettyWebSocketServerHandler
中,我们假设每个连接都有一个 userId
,通过 channel
的 attr
方法获取用户 ID,断开连接时将该用户从 UserManager
中移除。
小结
Netty 的心跳机制和空闲事件处理功能非常强大,它通过 IdleStateHandler
自动检测连接的空闲状态,帮助服务端发现和处理长时间不活动的客户端连接。通过自定义的事件处理器,我们可以在空闲事件触发时,进行连接关闭、资源清理、用户下线等操作,确保服务器能够及时响应并释放资源。
4. 心跳机制的优化与扩展
在实现了基本的心跳检测后,我们可以进一步对心跳机制进行优化和扩展。心跳机制的设计不仅仅是为了检测连接是否存活,还可以用于其他优化,例如:
4.1 调整心跳时间间隔
默认情况下,我们在 Netty 服务器端设置了 IdleStateHandler(30, 0, 0)
,即 30 秒内没有收到客户端的消息,就会触发 READER_IDLE
事件。但在实际应用中,我们可以根据业务需求调整心跳的频率:
- 如果服务器的负载较高,可以适当增加心跳间隔,例如 1 分钟检测一次,减少无用的心跳消息,降低服务器压力。
- 如果对在线状态的准确性要求较高,可以缩短心跳间隔,例如 10~15 秒检测一次,以便尽快发现连接异常。
心跳间隔需要根据实际业务进行权衡:间隔太短会增加服务器负担,间隔太长可能会导致掉线检测不及时。
4.2 采用双向心跳
目前我们的设计是 由客户端定期发送心跳包,服务器被动检测。但在一些场景下,例如 移动端网络不稳定、浏览器休眠、弱网环境等,可能会导致客户端心跳发送失败或延迟。为此,我们可以采用 双向心跳 机制,即:
- 客户端主动发送心跳(例如每 10 秒发送一次)。
- 服务器也定期主动向客户端发送心跳请求,如果客户端在规定时间内没有响应,则认为连接已断开。
这样可以 确保双向通信的可靠性,避免单方面心跳导致的误判。
4.3 结合 Redis 或数据库存储用户在线状态
在多服务器(集群)环境下,单个服务器维护的连接信息可能会不够准确。例如,某个用户可能已经断线,但由于服务器没有立即感知,导致用户状态仍然是“在线”。
为了解决这个问题,我们可以:
- 将用户的心跳时间存入 Redis,每次收到心跳更新 Redis 中的时间戳。
- 其他服务器可以通过 Redis 检测用户是否长时间没有发送心跳,从而更准确地判断用户在线状态。
这样,即使用户的 WebSocket 连接在某个服务器上断开了,整个系统仍然可以通过 Redis 统一管理用户的在线状态。
4.4 结合 Netty 的自定义 ChannelHandler
除了 IdleStateHandler
之外,我们还可以自定义一个 HeartbeatHandler
来进行更加灵活的心跳控制。例如:
- 记录心跳次数,如果 连续 3 次心跳超时,才真正断开连接,避免短暂的网络抖动影响用户体验。
- 结合 流量控制,如果服务器在高负载状态下,可以适当放宽心跳检测标准,防止误判导致大规模掉线。
通过这些优化,我们可以让 心跳机制更加智能、灵活、稳定,提高 WebSocket 连接的可靠性,为后续的即时通讯、推送等功能提供坚实的基础。
5. 具体实现心跳检测
在前面的介绍中,我们提到了 Netty 提供的 IdleStateHandler
组件,它可以帮助我们 检测连接是否空闲。现在,我们来看它的 具体实现。
5.1 服务器端的心跳检测
在 NettyWebSocketServer
中,我们已经添加了 IdleStateHandler(30, 0, 0)
,即 如果 30 秒内没有收到客户端的消息,就会触发 READER_IDLE
事件。
但是,仅仅触发事件是不够的,我们还需要在 Handler
中监听这个事件,并进行相应的处理。
步骤 1:继承 SimpleChannelInboundHandler<TextWebSocketFrame>
我们需要自定义一个 NettyWebSocketServerHandler
,用于处理心跳事件 和 WebSocket 消息:
public class NettyWebSocketServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {if (evt instanceof IdleStateEvent) {IdleStateEvent event = (IdleStateEvent) evt;if (event.state() == IdleState.READER_IDLE) {System.out.println("【心跳超时】关闭连接:" + ctx.channel().remoteAddress());ctx.channel().close();}} else {super.userEventTriggered(ctx, evt);}}@Overrideprotected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) {System.out.println("收到消息:" + msg.text());ctx.writeAndFlush(new TextWebSocketFrame("服务器已收到消息"));}
}
代码解析
-
监听
IdleStateEvent
事件:event.state() == IdleState.READER_IDLE
说明 30 秒内没有收到消息,意味着客户端可能已经断线,我们就 手动关闭连接。
-
处理正常的 WebSocket 消息:
channelRead0
方法用于处理 客户端发来的普通消息,这里简单打印出来,并返回一个 确认消息。
5.2 客户端的心跳发送
为了防止服务器误判掉线,客户端需要定期发送心跳消息。
前端(JavaScript)可以这样实现:
let socket = new WebSocket("ws://localhost:8090/ws");socket.onopen = function () {console.log("WebSocket 连接成功");setInterval(() => {if (socket.readyState === WebSocket.OPEN) {socket.send("ping");}}, 10000); // 每 10 秒发送一次心跳
};socket.onmessage = function (event) {console.log("收到服务器消息: " + event.data);
};socket.onclose = function () {console.log("WebSocket 连接关闭");
};
代码解析
- 建立 WebSocket 连接,监听
onopen
事件。 - 每 10 秒发送
"ping"
消息,保持连接活跃。 - 监听服务器的
onmessage
事件,打印服务器返回的消息。 - 监听
onclose
事件,一旦连接断开,前端可以尝试重新连接。
6. 服务器如何区分心跳和普通消息?
在 channelRead0
方法中,我们目前对所有消息都进行了打印和回写。
但在实际应用中,我们需要 区分普通消息和心跳消息,避免误处理:
@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) {String text = msg.text();if ("ping".equals(text)) {System.out.println("收到客户端心跳");ctx.writeAndFlush(new TextWebSocketFrame("pong")); // 返回心跳确认} else {System.out.println("收到普通消息:" + text);ctx.writeAndFlush(new TextWebSocketFrame("服务器已收到消息:" + text));}
}
改进点
- 如果收到
"ping"
,说明是 心跳消息,直接返回"pong"
,避免误处理。 - 如果收到普通消息,进行正常的逻辑处理。
7. 心跳机制测试
-
正常连接时:
- 前端每 10 秒发送
"ping"
,服务器返回"pong"
,连接保持活跃。
- 前端每 10 秒发送
-
如果前端关闭网页:
- 服务器在 30 秒后触发
READER_IDLE
事件,自动断开连接。
- 服务器在 30 秒后触发
-
如果网络异常:
- 服务器仍然可以在 30 秒后感知到超时,并清理资源,保证不会有 无效连接 长时间占用服务器资源。
这样,我们就完成了 基于 Netty 的 WebSocket 心跳检测,并且实现了 前端心跳发送、后端心跳检测、心跳超时处理等功能。
相关文章:
Websocket——心跳检测
1. 前言:为什么需要心跳机制? 在现代的实时网络应用中,保持客户端和服务端的连接稳定性是非常重要的。尤其是在长时间的网络连接中,存在一些异常情况,导致服务端无法及时感知到客户端的断开,可能造成不必要…...
量子计算驱动的金融衍生品定价革命:突破传统蒙特卡洛模拟的性能边界
引言:金融计算的算力困局 某国际投行采用128量子位处理器对亚洲期权组合定价时,其量子振幅估计算法在2.7秒内完成传统GPU集群需要68小时的计算任务。在蒙特卡洛路径模拟实验中,量子随机游走算法将10,000维衍生品的价格收敛速度提升4个数量级…...
文心智能体平台已全面接入DeepSeek模型,全部免费!
文心智能体平台已全面接入DeepSeek模型!即日起,您可以在创建智能体时,自由选择所需要的模型,欢迎大家体验。 ✅ 零成本体验:当前阶段所有用户可免费使用DeepSeek模型。 ✅ 智能适配:4款DeepSe…...
DuodooBMS源码解读之 odoo_phoenix_alarm模块
Odoo18 扩展模块声光报警器用户使用手册 一、模块概述 本扩展模块是基于 Odoo18 原生系统进行开发的,主要用于实现与上位声光报警设备的通讯功能。通过该模块,用户可以方便地向设备发送指令,控制设备的声音、灯光等操作。本手册将详细介绍该…...
docker从容器中cp到本地、cp本地到容器
在 Docker 中,你可以使用 docker cp 命令从容器中复制文件到本地主机。以下是具体步骤: 1. 查找容器 ID 或名称 首先,你需要知道容器的 ID 或名称。你可以使用以下命令列出所有正在运行的容器: docker ps 这将显示所有正在运行…...
网络工程师 (49)UDP协议
前言 UDP协议,即用户数据报协议(User Datagram Protocol),是一种无连接的、不可靠的、面向报文的传输层通信协议。 一、基本特点 无连接性:UDP在发送数据之前不需要与目标设备建立连接,也无需在数据发送结束…...
1.20作业
1 mfw(git泄露) ./git,原本以为点了链接下了index文件,就可以打开看源码,结果解析不了 老老实实用了githacker githacker --url --output 1 assert() 断言(assert)的用法 | 菜鸟教程 命令注入: /?page).system(cat ./templates/fl…...
HTML/CSS中交集选择器
1.作用:选中同时符合多个条件的元素 交集就是或的意思 2.语法:选择器1选择器2选择器3......选择器n{} 3.举例: /* 选中:类名为beauty的p元素,此种写法用的非常的多 */p.beauty{color: red;}/* 选中:类名包含rich和beauty的元素 */.rich.beauty{color: blue;} 4.注意: 1.有标签…...
迅为RK3568开发板篇Openharmony配置HDF控制UART-实操-HDF驱动配置UART-修改HCS配置
对于不同的平台,需要在对应的平台目录修改对应的 hcs 文件,接下来示例为在 rk3568下新增 uart4 uart9 uart7 的修改方法。 修改 vendor/hihope/rk3568/hdf_config/khdf/device_info/device_info.hcs 文件,device_info.hcs 中添加以下内容&…...
实时股票行情接口与WebSocket行情接口的应用
实时股票行情接口与WebSocket行情接口的应用 实时股票行情接口是量化交易和投资决策的核心工具之一,行情接口的种类和功能也在不断扩展。介绍几种常见的行情接口,包括实时股票行情接口、Level2行情接口、WebSocket行情接口以及量化行情接口,…...
k8s故障处理经典案例(Classic Case of k8s Fault Handling)
k8s故障处理经典案例 问题描述 kubernetes版本:v1.22.5 部分Pod在新版本发布后一直处于ContainerCreating状态,经过kubectl delete命令删除后一直Terminating状态。 排查过程 遇到问题先查日志 首先进入宿主机,查看三个日志,…...
关于uniApp的面试题及其答案解析
我的血液里流淌着战意!力量与智慧指引着我! 文章目录 1. 什么是uniApp?2. uniApp与原生小程序开发有什么区别?3. 如何使用uniApp实现条件编译?4. uniApp支持哪些平台,各有什么特点?5. 在uniApp中…...
给老系统做个安全检查——Burp SqlMap扫描注入漏洞
背景 在AI技术突飞猛进的今天,类似Cursor之类的工具已经能写出堪比大部分程序员水平的代码了。然而,在我们的代码世界里,仍然有不少"老骥伏枥"的系统在兢兢业业地发光发热。这些祖传系统的代码可能早已过时,架构可能岌…...
langchain系列 - FewShotPromptTemplate 少量示例
导读 环境:OpenEuler、Windows 11、WSL 2、Python 3.12.3 langchain 0.3 背景:前期忙碌的开发阶段结束,需要沉淀自己的应用知识,过一遍LangChain 时间:20250220 说明:技术梳理,针对FewShotP…...
【C语言】fgetpos函数用法介绍
目录 一、函数概述 二、核心参数与数据类型 三、典型应用场景 四、与 ftell() 的对比 五、错误处理与调试 六、进阶示例:多位置标记与恢复 七、注意事项 八、总结 fgetpos() 是C标准库中用于文件操作的关键函数之一,其核心功能是获取文件流的当前…...
《算法基础入门:最常用的算法详解与应用(持续更新实战与面试题)》
1. 排序算法 排序算法是将一组数据按特定的顺序排列起来的算法,常见的有: 冒泡排序(Bubble Sort)选择排序(Selection Sort)插入排序(Insertion Sort)归并排序(Merge So…...
YOLOv11-ultralytics-8.3.67部分代码阅读笔记-split_dota.py
split_dota.py ultralytics\data\split_dota.py 目录 split_dota.py 1.所需的库和模块 2.def bbox_iof(polygon1, bbox2, eps1e-6): 3.def load_yolo_dota(data_root, split"train"): 4.def get_windows(im_size, crop_sizes(1024,), gaps(200,), im_rate_t…...
如何使用Python快速开发一个带管理系统界面的网站-解析方案
如果你想用 Python 开发一个 管理系统界面 的网站,并且希望界面美观,可以考虑以下几个框架和库: 1. Streamlit(快速、简洁) 适合:数据分析、仪表盘、内部管理系统特点: 写法简单,类…...
25年HVV关于0day的面试题
以下是对0day漏洞如何防,基本上是每次HVV中大家都会提到的,今天总结了100day防护手段。 《网安面试指南》https://mp.weixin.qq.com/s/RIVYDmxI9g_TgGrpbdDKtA?token1860256701&langzh_CN 5000篇网安资料库https://mp.weixin.qq.com/s?__bizMzkw…...
【C# 数据结构】队列 FIFO
目录 队列的概念FIFO (First-In, First-Out)Queue<T> 的工作原理:示例:解释: 小结: 环形队列1. **FIFO?**2. **环形缓冲队列如何实现FIFO?**关键概念: 3. **环形缓冲队列的工作过程**假设…...
git 克隆及拉取github项目到本地微信开发者工具,微信开发者工具通过git commit、git push上传代码到github仓库
git 克隆及拉取github项目到本地微信开发者工具,微信开发者工具通过git commit、git push上传代码到github仓库 git 克隆及拉取github项目到本地 先在自己的用户文件夹新建一个项目文件夹,取名为项目名 例如这样 C:\Users\HP\yzj-再打开一个终端页面&…...
【机器学习】多元线性回归算法和正规方程解求解
多元线性方差和正规方差解 一、摘要二、多元线性回归介绍三、正规方程解的求解及代码实现 一、摘要 本文围绕多元线性回归的正规方程解展开,为初学者系统介绍了相关基本概念、求解方法、实际应用以及算法封装要点。 首先,深入阐释了正规方程解这一多元…...
在Linux上创建一个Docker容器并在其中执行Python脚本
在Linux上创建一个Docker容器并在其中执行Python脚本的过程,涉及多个方面的内容,包括安装Docker、编写Dockerfile、构建镜像、运行容器等。 1. 安装Docker 在Linux上使用Docker之前,你需要确保系统已安装Docker。Docker支持的Linux发行版有…...
Linux C 静态库如何生成并使用
1. 编写源文件 首先创建一个简单的示例项目,包含一个头文件和一个源文件。 头文件 my_lib.h // my_lib.h #ifndef MY_LIB_H #define MY_LIB_H// 函数声明 int add(int a, int b);#endif 源文件 my_lib.c #include <stdio.h>void print_hello() {printf(&q…...
清华大学deepseek教程第四版 DeepSeek+DeepResearch 让科研像聊天一样简单(附下载)
deepseek使用教程系列 DeepSeekDeepResearch 让科研像聊天一样简单(附下载) https://pan.baidu.com/s/1VMgRmCSEzNvhLZQc8mu6iQ?pwd1234 提取码: 1234 或 https://pan.quark.cn/s/f3d4511b790a...
请解释 Vue 中的生命周期钩子,不同阶段触发的钩子函数及其用途是什么?
vue生命周期钩子详解(Vue 3版本) 一、生命周期阶段划分 Vue组件的生命周期可分为四大阶段,每个阶段对应特定钩子函数: 创建阶段:初始化实例并准备数据挂载阶段:将虚拟DOM渲染为真实DOM更新阶段ÿ…...
输入搜索、分组展示选项、下拉选取,el-select 实现:即输入关键字检索,返回分组选项,选取跳转到相应内容页 —— VUE 项目-全局模糊检索
后端数据代码写于下一篇:输入搜索、分组展示选项、下拉选取,全局跳转页,el-select 实现 —— 后端数据处理代码,抛砖引玉展思路 【效果图】:分组展示选项 【去界面操作感受一下】—> 便捷简洁的企业官网 【录制效…...
Transformer为什么需要多头注意力(Multi-Head Attention)?如果没有多头会怎么样?
直接回答 关键点: Transformer 中的多头注意力(Multi-Head Attention)允许模型同时关注输入数据的不同方面,提升性能。 如果没有多头,模型可能无法捕捉复杂关系,表现会下降。 什么是多头注意力ÿ…...
VUE中的组件加载方式
加载方式有哪些,及如何进行选择 常规的静态引入是在组件初始化时就加载所有依赖的组件,而懒加载则是等到组件需要被渲染的时候才加载。 对于大型应用,可能会有很多组件,如果一开始都加载,可能会影响首屏加载时间。如…...
Linux自启动fastapi服务
步骤一 在/etc/systemd/system/文件夹下创建pyod.service(其中/path/to/conda/bin/activate要改为activate实际存放位置,例如miniconda的实际存放位置为/root/miniconda3/bin/activate) [Unit] DescriptionPyOD Uvicorn Service Afternetwo…...
C++与Python:两种编程语言的区别
C和Python都是当今编程领域广泛使用的语言,它们各有特色,适用于不同的开发场景。本文将从语言特性、性能、学习难度、应用领域等多个方面探讨C与Python之间的区别。 一、语言特性 类型系统: C:是一种静态类型语言…...
进程线程的创建、退出、回收
1. 进程相关知识点 1.1 进程创建 fork(): 功能:创建一个子进程。 返回值: 父进程中返回子进程的 PID。 子进程中返回 0。 失败返回 -1。 特点:子进程是父进程的副本,拥有独立的内存空间。 vfork():…...
深度学习-6.用于计算机视觉的深度学习
Deep Learning - Lecture 6 Deep Learning for Computer Vision 简介深度学习在计算机视觉领域的发展时间线 语义分割语义分割系统的类型上采样层语义分割的 SegNet 架构软件中的SegNet 架构数据标注 目标检测与识别目标检测与识别问题两阶段和一阶段目标检测与识别两阶段检测器…...
低概率发生调用`pthread_cond_wait`的线程没有被唤醒
低概率发生调用pthread_cond_wait的线程没有被唤醒 背景: 你是否也踩过坑,在A线程调用pthread_cond_wait等待,在B线程调用pthread_cond_signal唤醒A线程进行工作处理,然后在某一次用户产品反馈中发现了低概率问题。A线程像是卡住…...
MATLAB学习之旅:数据插值与曲线拟合
在MATLAB的奇妙世界里,我们已经走过了一段又一段的学习旅程。从基础的语法和数据处理,到如今,我们即将踏入数据插值与曲线拟合这片充满魅力的领域。这个领域就像是魔法中的艺术创作,能够让我们根据现有的数据点,构建出更加丰富的曲线和曲面,从而更好地理解和描述数据背后…...
Python复习
第一章 Python概述 python特点 优点: 简单易学;开发效率高;典型的工具语言;强大丰富的模块库;优秀的跨平台; 缺点: 执行效率不高;代码不能加密;用缩进区分语句关系&…...
通信系统中物理层与网络层联系与区别
在通信系统中,物理层和网络层是OSI(开放系统互连)模型中的两个重要层次,分别位于协议栈的最底层和第三层。它们在功能、职责和实现方式上有显著的区别,但同时也在某些方面存在联系。以下是物理层与网络层的联系与区别的…...
go 错误处理 error
普通错误处理 // 包路径 package mainimport ("errors""fmt" )func sqrt(f1, f2 float64) (float64, error) {if f2 < 0 {return 0, errors.New("error: f2 < 0")}return f1 / f2, nil }func sqrt1(f1, f2 float64) {if re, err : sqrt(f…...
Redis 缓存穿透、击穿、雪崩:问题与解决方案
在使用 Redis 作为缓存中间件时,系统可能会面临一些常见的问题,如 缓存穿透、缓存击穿 和 缓存雪崩。这些问题如果不加以解决,可能会导致数据库压力过大、系统响应变慢甚至崩溃。本文将详细分析这三种问题的起因,并提供有效的解决…...
Spring容器初始化扩展点:ApplicationContextInitializer
目录 一、什么是ApplicationContextInitializer? 1、核心作用2、适用场景 二、ApplicationContextInitializer的使用方式 1、实现ApplicationContextInitializer接口2、注册初始化器 三、ApplicationContextInitializer的执行时机四、实际应用案例 1、动态设置环境…...
冯·诺依曼体系结构、理解操作系统管理
在谈操作系统概念之前,先简单讲解一下冯诺伊曼体系结构,理解了在硬件层面上数据流的走向,这对后续的理解有很大的帮助。 文章目录 一.冯诺依曼结构冯诺依曼体系结构内存存在的意义 二.理解操作系统管理操作系统的作用管理的本质系统调用 一.…...
Linux初体验:从零开始掌握操作系统的发展与多样性
Linux初体验:从零开始掌握操作系统的发展与多样性 前言一、什么是Linux?1. Linux的定义2. Linux的组成 二、Linux的发展历史1. Unix的诞生2. Linux的诞生3. Linux的普及 三、Linux的发行版1. **Ubuntu**2. **CentOS**3. **Debian**4. **Fedora**5. **Arc…...
文心一言大模型的“三级跳”:从收费到免费再到开源,一场AI生态的重构实验
2025年2月,百度文心大模型接连抛出两枚“重磅炸弹”:4月1日起全面免费,6月30日正式开源文心大模型4.5系列。这一系列动作不仅颠覆了李彦宏此前坚持的“闭源优势论”13,更标志着中国AI大模型竞争进入了一个全新的阶段——从技术壁垒…...
技术教程 | 如何实现1v1音视频通话(含源码)
今天,给大家讲一下怎么实现1v1音视频通话,以下是教程内容: 开发环境 开发环境要求如下: 环境要求说明JDK 版本1.8.0 及以上版本Android API 版本API 21、Android Studio 5.0 及以上版本CPU架构ARM 64、ARMV7IDEAndroid Studio其…...
mysql实时同步到es
测试了多个方案同步,最终选择oceanu产品,底层基于Flink cdc 1、实时性能够保证,binlog量很大时也不产生延迟 2、配置SQL即可完成,操作上简单 下面示例mysql的100张分表实时同步到es,优化备注等文本字段的like查询 创…...
Linux-ubuntu系统移植之Uboot启动流程
Linux-ubuntu系统移植之Uboot启动流程 一,Uboot启动流程1.Uboot的两阶段1.1.第一阶段1.11.硬件初始化1.12.复制 U-Boot 到 RAM1.13.跳转到第二阶段 1.2.第二阶段1.21.C 语言环境初始化1.22. 硬件设备初始化1.23. 加载环境变量1.24. 显示启动信息1.25. 等待用户输入&…...
《Operating System Concepts》阅读笔记:p62-p75
《Operating System Concepts》学习第 10 天,p62-p75 总结,总计 14 页。 一、技术总结 1. system call (1) 定义 The primary interface between processes and the operating system, providing a means to invoke services made available by th…...
【Java场景题】MySQL死锁排查
大家好,今天XiXi给大家分享一个MySQL死锁排查的实验,文章主要有: 通过show engine innodb status,查看最近一次死锁信息开启innodb_print_all_deadlocks,在错误日志中能够记录所有死锁信息通过解析binlog日志定位死锁…...
JSON格式,C语言自己实现,以及直接调用库函数(一)
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。以下为你提供不同场景下常见的 JSON 格式示例。 1. 简单对象 JSON 对象是由键值对组成,用花括号 {} 包裹&…...
leetcode刷题第十三天——二叉树Ⅲ
本次刷题顺序是按照卡尔的代码随想录中给出的顺序 翻转二叉树 226. 翻转二叉树 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*//*总体思路就是,对于每一个结点&…...