HTTP 长连接与高效文件传输
t-io 将 HTTP 连接复用、明文文件零拷贝和异步发送队列结合起来,使普通接口、文件下载和 TLS 通信共享一致的发送流程。一次响应完成后,框架释放本次资源、通知发送结果,并根据连接策略继续处理后续请求。
连接复用,减少重复握手
| 请求 | 响应完成后的连接行为 |
|---|---|
| HTTP/1.1,未声明关闭 | 保留连接,允许继续请求 |
HTTP/1.1,Connection: close | 完整发送本次响应后关闭 |
HTTP/1.0,Connection: keep-alive | 保留连接 |
| HTTP/1.0,未要求 keep-alive | 完整发送本次响应后关闭 |
同一连接可以连续接收文件响应和普通响应。HTTPS 同样支持复用已建立的连接,有助于降低连续请求的握手开销。业务可通过响应的 keepConnection 控制发送后的连接行为。
启用 bizExecutor 后,同一连接按解码顺序执行业务处理。同步 HTTP 处理器与发送队列配合,保持流水线请求的响应顺序。处理器自行启动异步任务或使用 SSE 等持续输出时,由业务协调后续响应的发送时机。
明文文件的零拷贝路径
增强异步通道上的明文文件正文通过 FileChannel.transferTo() 发送,减少文件内容经过用户态缓冲区的复制。具体内核零拷贝优化取决于操作系统和通道实现。
底层异步接口如下,常规 HTTP 文件响应由框架调用该接口完成发送:
public <A> void transfer(FileChannel file, long position, long count,
A attachment, CompletionHandler<Long, ? super A> handler)
每次成功完成最多推进 1 MiB。调用者按实际完成字节数更新偏移,并继续提交剩余部分。文件句柄在操作完成前保持打开;该接口与普通异步写共用 pending 状态,同一通道依次提交写操作。
根据网络状态推进发送
transferTo() 或 socket 写入返回零时,框架保存传输进度并注册 OP_WRITE,在网络恢复可写后继续发送。等待期间释放调用线程,适应不同客户端的接收速度。
普通异步通道若内联完成零字节写入,发送器采用延迟重试。普通正文与文件正文都通过同一队列推进机制处理,便于在同一连接上组合不同响应。
磁盘读取仍可能占用当前线程;应用应结合文件大小、连接数量及业务要求规划发送容量和超时策略。当前发送队列没有内置容量上限,发送路径也不提供默认写超时,可在应用层设置相应资源预算与截止时间。
TLS 文件分片发送
TLS 文件响应按 64 KiB 分片读取,完成加密后提交异步写入。普通 JDK 异步通道也采用文件分片路径。
响应头与明文分片通过 EncodedBuffer 接入 VirtualBuffer 响应池。TLS 加密产生独立密文后即可归还明文分片,密文输出继续保留到写入完成;普通通道上的分片在写入完成后归还。明文增强通道继续使用 transferTo()。具体用法见缓冲区复用。
分片方式控制单次读取的数据量,适合与 TLS 加密流程配合。加密前的缓冲区切分支持直接缓冲区及非零 position,按实际剩余数据生成分片。
一致的完成通知与资源管理
文件响应和普通响应共用以下流程:
- 编码响应,并检查文件范围等发送条件。
- 依次发送响应头和正文,记录实际完成进度。
- 完成本次发送后通知结果,释放缓冲区及文件句柄。
- 根据连接策略处理队列中的下一项,或结束连接。
连接关闭时,等待中的读写操作获得对应的完成结果。正在异步写入的缓冲区在回调到达后再回收,使资源生命周期与 IO 完成状态保持一致。
请求格式与静态文件使用
调用方使用可确定长度的正文,并通过 Content-Length 表达正文长度。解码器接收合法半包,按字节检查请求行及请求头上限,并校验长度、重复的消息边界头和头名称格式。
当前请求解码器不接受 Transfer-Encoding(包括 chunked 请求正文),收到后关闭连接。发送端应选择带 Content-Length 的请求;请求格式校验与业务参数校验分别处理。
静态文件允许访问根目录之外、当前进程有权限读取的文件,便于接入已有文件目录。应用可根据部署需要配置操作系统文件权限。
典型使用组合
| 使用场景 | 可组合的能力 |
|---|---|
| 连续接口调用 | HTTP keep-alive、连接内有序业务处理 |
| 明文文件下载 | transferTo()、可写事件调度、发送完成通知 |
| HTTPS 下载 | TLS 连接复用、有界文件分片、异步写入 |
| 文件与接口混合请求 | 统一发送队列、完整响应后的连接策略 |
