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. 前言:为什么需要心跳机制? 在现代的实时网络应用中,保持客户端和服务端的连接稳定性是非常重要的。尤其是在长时间的网络连接中,存在一些异常情况,导致服务端无法及时感知到客户端的断开,可能造成不必要…...

Javascript使用Sodium库实现 aead_xchacha20poly1305_ietf加密解密,以及与后端的密文交互
Node.js环境安装 sodium-native (其他库可能会出现加密解密失败,如果要使用不一样的库,请自行验证) npm install sodium-native 示例代码,使用的是 sodium-native v4.3.2 (其他版本可能会有变化,如果要使用,请自行验…...
视频mp4垂直拼接 水平拼接
视频mp4垂直拼接 水平拼接 pinjie_v.py import imageio import numpy as np import os import cv2def pinjie_v(dir1,dir2,out_dir):os.makedirs(out_dir, exist_okTrue)# 获取目录下的所有视频文件video_files_1 [f for f in os.listdir(dir1) if f.endswith(.mp4)]video_fi…...

跟着李沐老师学习深度学习(十二)
循环神经网络 序列模型 序列数据 实际中很多数据是有时序结构的 比如:电影的评价随时间变化而变化 拿奖后评分上升,直到奖项被忘记看了很多好电影后,人们的期望变高季节性:贺岁片、暑期档导演、演员的负面报道导致评分变低 核心思想&#…...

MFC中CString的Format、与XML中的XML_SETTEXT格式化注意
1、在MFC中导入 "msxml6.dll",并使用其中的XML_SETTEXT函数,此调用在进行格式化的时候,调用的还是CString.Format()函数! 2、用double类型的数据,格式化整形数%d之前,必须将double强转为int&…...
如何设计合理的树状结构表:平衡查询效率与维护效率
树状结构广泛应用于数据建模中,例如 商品分类、组织架构、权限管理 等场景。合理设计树形结构的数据库表,能够有效提升 查询效率 和 维护效率。本文将探讨如何在设计时平衡这两者,详细介绍常用的几种树状结构存储方式及其适用场景。 一、树状…...
Springboot的简单推荐实现
以springboot 推荐社团招新为例子 使用 Spring Boot 构建社团招新推荐系统,用户注册后选择兴趣,系统根据兴趣推荐社团。 实现包括用户注册、兴趣选择和基于标签匹配的推荐算法。 系统使用 JPA 管理数据库,Spring Security 确保安全࿰…...

SpringBoot速成概括
视频:黑马程序员SpringBoot3Vue3全套视频教程,springbootvue企业级全栈开发从基础、实战到面试一套通关_哔哩哔哩_bilibili 图示:...
springboot多实例部署时,@Scheduled注释的方法重复执行
问题:springboot多实例部署时,Scheduled注释的方法重复执行 在 Spring Boot 中要实现 Redis 的SET NX EX命令,可以借助 Spring Data Redis 来完成。SET NX EX命令用于在键不存在时设置键值对,并同时设置过期时间。 <dependen…...

蓝桥杯15 填空题
1.握手问题: 思路:首先当所有人都握过手,由于一次握手相当于两个人都握手过,所以容易发现这是一个组合问题,为(50*49)/2,而其中有7个人没有相互握过手,那么减去ÿ…...

快速入门——第三方组件element-ui
学习自哔哩哔哩上的“刘老师教编程”,具体学习的网站为:10.第三方组件element-ui_哔哩哔哩_bilibili,以下是看课后做的笔记,仅供参考。 第一节 组件间的传值 组件可以有内部Data提供数据,也可由父组件通过prop方式传…...
力扣-贪心-455 分发饼干
思路 用小饼干去喂胃口小的孩子,不满足条件的时候,去喂胃口稍微大点的孩子,尽可能多满足孩子 class Solution { public:int findContentChildren(vector<int>& g, vector<int>& s) {sort(g.begin(), g.end());sort(s.b…...

【多模态处理篇二】【深度揭秘:DeepSeek视频理解之时空注意力机制解析】
一、为啥要搞视频理解这事儿 咱先唠唠为啥视频理解这么重要哈。现在这互联网时代,视频那可是铺天盖地的。你刷短视频平台,看在线电影,玩游戏直播,到处都是视频。但是计算机它一开始可不懂视频里到底是啥意思,它看到的就是一堆像素点和声音信号。 视频理解呢,就是要让计…...

网络运维学习笔记 017 HCIA-Datacom综合实验01
文章目录 综合实验1实验需求总部特性 分支8分支9 配置一、 基本配置(IP二层VLAN链路聚合)ACC_SWSW-S1SW-S2SW-Ser1SW-CoreSW8SW9DHCPISPGW 二、 单臂路由GW 三、 vlanifSW8SW9 四、 OSPFSW8SW9GW 五、 DHCPDHCPGW 六、 NAT缺省路由GW 七、 HTTPGW 综合实…...

数据结构:实验题目:单链表归并。将两个非递减次序排列的单链表归并为一个非递增次序排列的单链表,并计算表长。要求利用原来两个单链表的结点存放合并后的单链表。
输出样例如图: 代码如下: #include<stdio.h>#include<stdlib.h>//链表节点结构 typedefstructListNode{intval;structListNode*next; } ListNode;// 创建新节点 ListNode* createNode(int val){ListNode* newNode (ListNode*)malloc(sizeo…...
请求go构建缓存,go clean -cache
go clean -cache go 构建时会产生很多缓存, 一般是目录:/Users/xxx/Library/Caches/go-build 此目录README: This directory holds cached build artifacts from the Go build system. Run "go clean -cache" if the directory …...
Windows和Linux下,通过C++实现获取蓝牙版本号
在 C 中获取蓝牙版本号,不同的操作系统有不同的实现方式,下面分别介绍在 Windows 和 Linux 系统下的实现方法。 Windows 系统 在 Windows 系统中,可以使用 Windows API 来与蓝牙设备交互,获取蓝牙版本号。以下是一个示例代码&…...
【网络】如何划分子网、计算子网掩码、确定网络地址、广播地址和可用主机地址范围?
当然!让我们一步一步详细介绍如何划分子网、计算子网掩码、确定网络地址、广播地址和可用主机地址范围。假设我们从一个 10.0.0.0/24 的网络开始,并且需要为每个子网提供 50 个主机地址。 问题概述: 我们有一个网络 10.0.0.0/24。我们希望为…...
内核数据结构用法(2)list
list 在 Linux 内核中,链表操作是通过一组宏和函数来实现的,这些操作通常用来管理和遍历链表。以下是一些常用的链表函数和宏的具体用法。 1. 定义链表节点 首先,你需要定义一个包含 struct list_head 的结构体: #include <…...
【数据分析】2.数据分析业务全流程
业务流程方法论:3阶段6步骤 一、课程核心内容结构 1. 方法论概述 目标:系统性地解决商业中的关键问题框架:分为三个阶段,每个阶段包含两个步骤适用场景:适用于数据分析师、业务经理等需要通过数据分析支持决策的从业…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...

Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...
Spring Security 认证流程——补充
一、认证流程概述 Spring Security 的认证流程基于 过滤器链(Filter Chain),核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤: 用户提交登录请求拦…...

【Veristand】Veristand环境安装教程-Linux RT / Windows
首先声明,此教程是针对Simulink编译模型并导入Veristand中编写的,同时需要注意的是老用户编译可能用的是Veristand Model Framework,那个是历史版本,且NI不会再维护,新版本编译支持为VeriStand Model Generation Suppo…...
Python实现简单音频数据压缩与解压算法
Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中,压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言,提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...

在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例
目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码:冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...
[特殊字符] 手撸 Redis 互斥锁那些坑
📖 手撸 Redis 互斥锁那些坑 最近搞业务遇到高并发下同一个 key 的互斥操作,想实现分布式环境下的互斥锁。于是私下顺手手撸了个基于 Redis 的简单互斥锁,也顺便跟 Redisson 的 RLock 机制对比了下,记录一波,别踩我踩过…...