MsgTrans 2.0 Beta 1发布
MsgTrans是多协议高性能网络库,现在MsgTrans 2.0 Beta 1已经发布。这是一次面向生产级实时网络的系统性重构,而非在1.x上继续堆叠功能。MsgTrans继续通过统一API支持TCP、WebSocket和QUIC,但2.0重新设计了事件传递、请求生命周期、写入确认、连接代际、资源限制、优雅关闭、协议扩展和公共API。其目标明确:网络库不应只在正常环境里工作,还必须在弱网、拥塞、重连、超时、慢消费者和异常关闭下给出确定、可验证的结果。
一套业务代码,覆盖三种网络环境
MsgTrans 2.0让业务层不再绑定具体协议。同一套消息、请求响应和会话处理逻辑,可以部署在三种传输之上。
| 协议 | 推荐场景 | 核心价值 |
| --- | --- | --- |
| QUIC | 移动网络、弱网、高延迟、丢包环境 | 更适合互联网与低延迟传输 |
| TCP | 稳定内网、服务间通信、长连接网关 | 成熟、稳定、行为可预测 |
| WebSocket | 浏览器、HTTP代理、防火墙限制、只放行普通Web流量的环境 | HTTP基础设施兼容性更强 |
| 自定义协议 | 专用硬件、私有链路、定制传输 | 通过 `msgtrans::spi` 接入统一传输层 |
业务无需为不同协议维护三套请求状态机、会话生命周期和错误处理逻辑。
2.0的核心变化:可靠性成为架构属性
1. 有界事件主干,不再静默丢消息
MsgTrans 2.0删除了核心数据路径中的广播事件总线,改为每连接独立的有界事件管道和Session Actor:Connection → bounded channel → SessionActor → SessionHandler。慢消费者只会对自己的连接形成背压,不再影响其他连接。数据、诊断和控制事件被拆分为不同平面:数据事件有界、背压、不得丢弃;诊断事件允许在压力下丢弃,绝不挤占业务数据;关闭事件不排在数据队列后面,保证连接能够及时退出。旧广播主干在内部饱和测试中曾复现约91%的消息丢失,2.0直接移除了这条结构性风险。
2. 请求生命周期只有一个真相源
2.0使用统一的Request Registry管理请求状态:Pending → Responding → Responded → SendFailed;Pending → TimedOut;Pending → SessionClosed;Pending → Dropped。状态迁移使用原子操作,保证:一个请求最多只有一个响应者成功;重复响应不会产生第二个网络包;超时、断线和发送失败具有不同语义;会话关闭时立即清理关联请求;取消调用方Future不会留下永久Pending或Responding;迟到响应不会完成另一条新请求。`Responder`携带不可伪造的 `RequestToken`,业务方无法手动构造消息ID或绕过请求注册表。
3. 彻底关闭重连ABA与旧连接污染
每次连接都会获得独立、单调递增的Session ID。连接和代际信息存储在同一个原子生命周期槽中。旧连接迟到的Response、ConnectionClosed或异步发送,只能影响旧代会话,无法触碰重连后的新连接。请求ID由传输层按会话分配,并且拒绝回绕。宁可明确返回资源耗尽,也不会复用仍可能存在迟到响应的ID空间。
4. `Ok` 终于代表真实成功
2.0不再把"进入发送队列"包装成"发送成功"。所有正式 `send` 路径都是write-confirmed:let receipt = client.send(b"hello").await?; 只有底层写循环确认字节已经写入传输层,调用才返回成功。如果只需要排队、不等待写入,可以显式使用:client.send_detached(b"hello").await?; 两种语义通过命名直接区分,不再出现真假难辨的 `Ok(())`。请求超时现在返回真正的 `Err`,不再伪装成"成功但没有数据"。广播则返回 `BroadcastReport`,明确报告成功数量和每个会话的失败原因。
5. 可等待、可证明的确定性关闭
`shutdown()`不再只是设置一个停止标记。2.0使用受控任务所有权和生命周期监督器,等待:listener停止;scanner退出;actor与事件泵结束;会话资源释放;连接许可全部归还;监听端口真正释放。关闭结果通过 `ShutdownReport` 返回:let report = server.shutdown().await?; assert!(report.infra_stopped); assert!(report.permits_restored); assert!(report.clean); 这解决了Ctrl+C后QUIC或其他监听端口长时间不能重新绑定、幽灵会话占用连接配额、后台任务脱离服务器生命周期等问题。
严格、安全、统一的协议边界
Strict成为默认策略
`FramePolicy::Strict`现在是默认值。以下输入都会被视为协议错误并关闭连接:未知Packet Type;未知Compression Type;WebSocket文本帧;尾随多余字节;非法固定头;超过限制的扩展头或Payload;无法解压的数据;声明长度与实际帧不一致。需要兼容1.x宽松行为时,仍可显式选择 `FramePolicy::Lenient`。
三协议共享同一套尺寸限制
TCP、WebSocket、QUIC不再各自维护不同的隐藏上限。`ServerLimits`和 `ClientLimits`统一控制:最大Payload;最大扩展头;最大帧尺寸;写入截止时间;事件管道容量;出站队列容量;Actor邮箱容量。同一个包不会再出现"WebSocket可以发,TCP却突然断开"的协议差异。
压缩不再可能制造损坏帧
压缩通过 `SendOptions` 和 `RequestOptions` 指定,由传输层在Payload完成后统一处理:let options = SendOptions::new().biz_type(7).compression(CompressionType::Zstd); 如果构建时没有启用对应codec,发送会明确失败,而不是把原始数据挂上"已压缩"标志继续发出。入站解压只在共享事件边界执行一次。TCP、WebSocket、QUIC、客户端、服务端和自定义协议的上层消费者看到的始终是明文Payload与自洽的包头。
性能优化不是用可靠性换吞吐
MsgTrans 2.0的性能方向不是盲目追求微基准数字,而是在稳定语义下减少热路径成本:`Bytes` 驱动的Payload与零拷贝切片解码;编码路径消除重复 `Vec` 和 `freeze` 拷贝;QUIC读取缓冲减少无意义清零;每连接独立Actor,降低跨连接共享竞争;`ConnectionWriter` 将写路径从连接状态锁中分离;等待队列和写入回执时不持有连接锁;压缩和解压只执行一次;广播选项在扇出前只准备一次;有界队列防止慢连接无限吞噬内存;TCP、WebSocket、QUIC Cargo feature真正裁剪协议依赖。当前三协议压力测试均保持零传输错误,架构重构前后未观察到显著吞吐回退。
更小、更诚实的公共API
2.0删除了大量"看起来能用、实际上未接线"或暴露内部实现的接口。公共面现在只有两部分:`msgtrans::*`:应用开发API;`msgtrans::spi::*`:协议扩展API。内部Transport、Request Registry、Session Actor、协议适配器和状态机不再泄漏到公共命名空间。公共API由快照纳入CI。一旦接口发生变化,构建会直接失败,避免文档和实现静默漂移。
1.x用户必须关注的升级点
MsgTrans 2.0保持wire format不变,规范的1.x与2.0节点可以互通。但Rust公共API是有意进行的breaking change。
SessionHandler拆分
单向消息和请求不再混在同一个入口:async fn on_message(&self, session_id: SessionId, packet: Packet, sender: SessionSender); async fn on_request(&self, session_id: SessionId, packet: Packet, responder: Responder); 请求只能通过消费式 `Responder` 回应。
Packet字段私有化
packet.message_id(); packet.biz_type(); packet.payload(); packet.into_payload(); packet.try_encode()?; 编码成为可失败操作,超限数据不会再被静默截断。
发送参数拆分
let send = SendOptions::new().biz_type(7).compression(CompressionType::Zstd); let request = RequestOptions::new().biz_type(7).timeout(Duration::from_millis(500)); Raw Packet发送入口已经删除,调用方无法再伪造Request类型和消息ID。
WebSocket TLS类型化
旧的 `verify_tls: bool` 被替换为:ClientTls::SystemRoots;ClientTls::CustomCa(pem);ClientTls::Insecure;每个选项都有真实实现,`Insecure` 只适合开发环境。
深层import迁移
应用类型统一从crate root导入:use msgtrans::{Packet, ClientEvent, Responder}; 协议实现者使用:use msgtrans::spi::{Connection, ConnectionWriter, EventSink}; 完整迁移说明可查看相关文档。
适用场景
MsgTrans 2.0尤其适合:即时通信、消息推送和实时协作;移动网络与弱网传输;游戏长连接和状态同步;内网微服务通信;IoT设备与网关;同时面向App、浏览器和后端服务的多协议网关;需要请求响应、单向消息、广播与断线重连的实时系统;需要自定义传输协议,但希望复用会话和请求生命周期的基础设施。如果项目只是普通REST API,或者只需要短连接HTTP请求,MsgTrans并不是HTTP框架的替代品。它面向的是持续连接、双向实时传输和可控生命周期。
如何开始
Beta 1发布后可使用:[dependencies] msgtrans = { version = "2.0.0-beta.1", features = ["tcp", "websocket", "quic"] } 启用压缩:msgtrans = { version = "2.0.0-beta.1", features = ["tcp", "websocket", "quic", "zstd"] } 对于现有1.x项目,建议采用滚动升级:先迁移公共API并保持原协议部署;在测试环境启用Strict策略;验证超时、重连、慢消费者与服务关闭场景;对移动网络优先试运行QUIC;生产环境先灰度单协议,再扩展到多协议入口。
结语
MsgTrans 1.x证明了统一TCP、WebSocket和QUIC是可行的。MsgTrans 2.0要证明的是另一件事:在弱网、拥塞、异常输入、频繁重连和服务退出时,网络库仍然可以给出精确、确定、可观察的行为。这不是一次简单升级,而是MsgTrans从多协议网络库迈向生产级实时传输基础设施的重要一步。