分布式缓存的 IORPC 协议
从 JuiceFS 企业版 5.2 开始,IORPC 为缓存组节点间数据传输提供了一套 RPC 框架。TCP Pool 是默认通信模式,适用于绝大多数场景。IORPC 仅在连接数过多导致性能衰退时考虑使用,其连接多路复用可以降低 goroutine 调度带来的 CPU 开销。IORPC 默认关闭,启用前请联系 Juicedata 技术支持评估可行性。
IORPC 与 TCP Pool 对比
JuiceFS 分布式缓存系统支持两种节点间数据传输的网络通信模式:
| 特性 | IORPC | TCP Pool |
|---|---|---|
| 多路复用 | 一个连接可并发处理多个请求 | 每个连接同一时刻只能处理一个请求 |
| I/O 路径(默认) | Direct I/O 读盘 + write 发送(两次用户态拷贝) | sendfile(内核内零拷贝) |
| 连接数 | 高并发下所需连接数较少 | 高并发下需要维护大量连接 |
| 传输方式 | TCP(默认)或 RDMA | 仅 TCP |
| 缓存读取模式 | dio(默认)、pagecache、splice | sendfile(默认)或 dio(需配合 --cache-try-dio) |
| 适用场景 | 连接过多导致性能衰退时 | 绝大多数场景 |
TCP Pool 是早期版本一直使用的传统模式,也是所有版本的默认模式。默认使用 sendfile 实现缓存盘到网络的零拷贝传输。
IORPC 支持多路复用,单个连接可以并发处理多个请求,显著减少高并发场景下的连接数量。此外,IORPC 还可以配合 RDMA 传输,获得更高的吞吐和更低的 CPU 占用。
启用 IORPC
IORPC 分为服务端和客户端两个独立的部分。只有当两部分同时开启时,系统才会使用 IORPC 模式进行数据传输。
服务端
IORPC 服务端运行在缓存组成员节点上(即未使用 --no-sharing 的挂载点)。从 5.2 版本开始,服务端默认开启。
如需关闭某个节点的 IORPC 服务端,使用 --iorpc-mode=disable。
客户端
IORPC 客户端默认关闭。如需在任意 JuiceFS 客户端(包括 --no-sharing 节点)上启用,使用 --use-iorpc。
指定 --rdma-network 后,IORPC 会在服务端和客户端自动启用并以 RDMA 方式传输数据,无需单独设置 --use-iorpc。详见分布式缓存 RDMA 加速。
IORPC 缓存读取模式
--iorpc-mode 参数控制 IORPC 服务端从磁盘读取缓存数据的方式。该设置仅对缓存组成员节点生效。
| 模式 | 说明 |
|---|---|
dio(默认) | Direct I/O,绕过内核 page cache,减少内存拷贝和系统内存占用。 |
pagecache | Buffer 读,经过内核 page cache,使用标准文件系统读路径。 |
splice | 零拷贝模式,利用内核管道(splice/vmsplice)在磁盘和网络之间直接传输数据,无需用户态拷贝。要求系统管道最大值 ≥ 8 MiB。RDMA 启用时自动回退为 dio。 |
disable | 禁用本节点的 IORPC 服务端,缓存请求改由 TCP Pool 处理。 |
配置 splice 模式
使用 splice 模式时,设置 --iorpc-mode=splice。
启用 splice 前,需将系统管道最大值调至 8 MiB 以上:
echo 8388608 > /proc/sys/fs/pipe-max-size
查看当前管道最大值:
sysctl fs.pipe-max-size
如果管道大小不足 8 MiB 或已启用 RDMA,服务端会自动回退为 dio 模式并在日志中输出警告。
连接管理
IORPC 会根据带宽和 QPS 自动调整连接数,增加连接每秒评估一次,减少连接每分钟评估一次。TCP 连接在带宽超过 300 MiB/s 或 QPS 超过 1000 时增加,在带宽和 QPS 同时分别低于 100 MiB/s 和 500 时减少。RDMA 连接的增长和减少阈值更高(增加阈值为 1 GiB/s 或 5000 QPS,减少阈值为 512 MiB/s 且 2000 QPS) 。连接数始终至少保留一个。
验证 IORPC 是否生效
服务端
查看缓存组成员节点的 JuiceFS 客户端日志,日志行会显示当前 IORPC 模式和 TCP Pool 模式:
max pipe size: 8388608, iorpc: dio, tcp pool: sendfile
其中 iorpc 字段的可能值:
dio:Direct I/O(默认)pagecache:Buffer 读splice:零拷贝模式disable:IORPC 服务端未启用
tcp pool 字段的可能值:
sendfile:默认零拷贝方式dio: 已启用 Direct I/O(通过--cache-try-dio)
客户端
当客户端与缓存服务端成功建立 IORPC 通信后,客户端日志中会显示:
iorpc client started, server address X.X.X.X:X
其中 X.X.X.X:X 为已连接的缓存服务端 IP 地址和端口号。
监控
关键日志
| 日志 | 来源 | 说明 |
|---|---|---|
max pipe size: ..., iorpc: dio, tcp pool: sendfile | 服务端启动 | 显示当前 IORPC 模式和 TCP Pool 读盘方式。各字段值详见服务端验证。 |
iorpc client started, server X.X.X.X:X | 客户端 | IORPC 连接成功建立。 |
get iorpc address from ... failed: rpc disabled | 客户端 | 对端不支持 IORPC(旧版本),回退到 TCP Pool。 |
splice iorpc is disabled since max pipe size is ... or RDMA is enabled, use dio instead | 服务端 | splice 条件不满足,自动回退为 dio。 |
iorpc-mode should be one of ..., but got ..., set to dio | 服务端 | 配置了无效的 --iorpc-mode 值,回退为默认 dio。 |
Prometheus 指标
以下为 IORPC 核心指标,前缀为 mount_。各延迟指标同时提供 _tp50 / _tp90 / _tp99 分位数及 _max。
| 指标 | 说明 |
|---|---|
mount_iorpc_processRespDur | 服务端处理 IORPC 请求的耗时(从收到请求到响应序列化)。 |
mount_iorpc_writeBodyDur | 将响应体写入网络连接的耗时。排查网络拥塞时可关注此指标。 |
mount_iorpc_decodeBodyDur | 解码请求/响应体的耗时。 |
mount_iorpc_inflight | 当前正在被服务端并发处理的 IORPC 请求数。达到默认并发上限 2048 后,新请求会排队等待,直到有空闲 slot 释放,可能导致延迟上升和客户端超时。若该指标持续 接近 2048,需考虑扩容缓存组。 |
juicefs stats 实时输出
使用 juicefs stats 配合 r 字符和 -l 1 可实时查看 IORPC 内部各阶段耗时:
juicefs stats --schema=ufmcro -l 1 /jfs
在 remotecache 区域中,会额外显示三列:
db_c/lat:解码请求/响应体的操作次数和平均延迟。pr_c/lat:服务端处理 RPC 请求的操作次数和平均延迟。wb_c/lat:将响应体写入网络的操作次数和平均延迟。
不使用 -l 1 时,r 仅显示业务层 remotecache 指标。这些 IORPC 列在 -l 1 下始终显示,但仅在 IORPC 启用时才有实际数值。
调优建议
什么时候使用 IORPC
启用 IORPC 前请联系 Juicedata 技术支持评估可行性。
当连接数过多导致性能衰退时,可考虑启用 IORPC。典型判断依据包括:
- 缓存服务端进程 goroutine 数量达数千级(用
cat /jfs/.stats | grep goroutines查看),但juicefs stats显示的 remotecache 吞吐并未随并发增加同步增长 ,表明 TCP Pool 每个连接一个 goroutine 的模型消耗了 CPU 却未能提升吞吐 juicefs stats显示 CPU 占用高,但 remotecache 吞吐远低于网卡额定带宽,表明 CPU 被 goroutine 调度而非有效数据传输所消耗- 客户端到缓存组节点存在大量 TCP 连接(用
ss -tan | wc -l查看,该命令统计ESTABLISHED和TIME_WAIT连接总量,TIME_WAIT数量高直接反映连接频繁创建和关闭,是 TCP Pool 的典型特征),配合上述 CPU 或吞吐异常,可进一步确认瓶颈来自 TCP Pool 的连接模型
IORPC 通过多路复用解决该问题:单个连接通过消息 ID 匹配同时承载多个并发请求,一个 goroutine 即可服务多个请求,连接数从成千上万降至数十个,goroutine 随之大幅减少,Go 调度器因大量 goroutine 上下文切换产生的开销大幅减少。CPU 从连接管理中释放出来,回归缓存盘 I/O 和网络数据传输。
如果启用 IORPC 后仍无法充分利用带宽,可以进一步尝试 splice 模式。
什么时候使用 Direct I/O(dio)
默认的 dio 模式适用于大多数场景。尤其当使用 top 观察到 kswapd 进程占用较多 CPU 时,说明内存碎片化导致 page cache 分配缓慢,此时 Direct I/O 绕开内核 page cache 可避免该问题。但 Direct I/O 性能受磁盘性能限制。
什么时候使用 splice
如果 dio 模式下吞吐仍不理想,可以切换为 splice 模式,通过内核管道实现零拷贝传输。该模式希望在最大化吞吐的同时降低 CPU 开销,在内核版本低于 5.12(缺少 TCP 协议栈优化)的环境中收益尤为明显。
启用 splice 前请务必调高管道最大值至 8 MiB 以上。
IORPC 与 RDMA 的关系
使用 RDMA 加速 时,--iorpc-mode 仍然控制服务端的磁盘读取方式。不过 splice 模式在 RDMA 启用时会自动回退为 dio。RDMA 如何自动启用 IORPC 详见上文的说明,完整配置指南见分布式缓存 RDMA 加速。


