Design Goals
rs-netty 的设计目标不是把 Java Netty 原样搬到 Rust,而是把 pipeline/handler/channel 这套建模方式换成 Rust-native 的形式。
Keep The Useful Shape
保留的概念:
- codec 位于 pipeline 边界,负责 bytes/datagrams 和 typed message 之间的转换。
- inbound stage 处理解码后的入站消息。
- final handler 处理应用语义,并写出应用层响应。
- outbound stage 把 handler 写出的应用类型转换成 codec 可编码类型。
- channel handle 可以从当前 handler 外部写入、flush 或关闭连接。
- lifecycle hook 可以观察 server、connection 和 UDP socket 的启动/关闭。
Use Rust Types Instead Of Dynamic Pipeline Mutation
Java Netty 的动态 pipeline 很灵活,但错误通常在运行时出现:handler 顺序不对、上游消息类型与下游不匹配、TCP pipeline 被误用于 UDP 等。rs-netty 把这些约束编码在 builder 类型里:
codec -> inbound* -> business* -> handler -> outbound*
只有当前状态允许的方法才存在。比如在 .codec(...) 之前没有 .handler(...),在 .handler(...) 之后没有 .inbound(...),并且最终 outbound 类型必须被 codec 的 encoder 支持。
仓库里的 trybuild 用例覆盖了这些失败场景,例如:
fail_stream_handler_before_codec.rsfail_stream_outbound_before_handler.rsfail_stream_type_mismatch_inbound_to_handler.rsfail_stream_final_encoder_mismatch.rsfail_udp_with_stream_pipeline.rsfail_tcp_with_datagram_pipeline.rs
Separate TCP And UDP Builders
TCP 使用 pipeline(),要求 codec 实现 Decoder 和 Encoder<T>。UDP 使用 datagram_pipeline(),要求 codec 实现 DatagramDecoder 和 DatagramEncoder<T>。
这不是命名偏好,而是类型边界。TcpServer::pipeline 只接受 IntoStreamPipeline,UdpServer::pipeline 只接受 IntoDatagramPipeline。因此 TCP/UDP pipeline 混用不会通过编译。
Prefer Owned Messages
框架没有暴露 Java Netty 风格的 reference-counted ByteBuf。codec 和 handler 在公开 API 中使用 String、bytes::Bytes、用户自定义 struct 等 owned 类型。这样更贴近 Rust 的所有权模型,也减少了 refCnt 误用带来的生命周期风险。
Bounded Queues And Explicit Flush
Channel 和 DatagramChannel 背后使用 bounded Tokio mpsc。outbound_queue_size 控制外部写入命令队列大小;队列满时写调用等待容量,而不是无限制堆积。
写入和 flush 明确分离:
write只排队或暂存。flush推送已暂存数据到 socket。write_and_flush写入并建立一个 flush 边界。
这个模型让高吞吐场景可以 batch,也让低延迟场景可以显式 flush。
Zero Unsafe
crate 根使用 #![deny(unsafe_code)],rs-netty-macros 也启用了同样的约束。当前主库和宏库都不依赖 unsafe 作为实现主路径。