perf: add hybrid S3 writes and shared lease keepalive - #50
Merged
Conversation
ActivePeter
temporarily deployed
to
OPENAI_API_KEY
July 28, 2026 05:31 — with
GitHub Actions
Inactive
ActivePeter
temporarily deployed
to
OPENAI_API_KEY
July 31, 2026 14:24 — with
GitHub Actions
Inactive
ActivePeter
temporarily deployed
to
OPENAI_API_KEY
July 31, 2026 18:30 — with
GitHub Actions
Inactive
ActivePeter
requested changes
Aug 3, 2026
ActivePeter
left a comment
Collaborator
There was a problem hiding this comment.
发现 3 个需要在合并前修复的生命周期与资源回收问题,详见行内评论。
ActivePeter
temporarily deployed
to
OPENAI_API_KEY
August 4, 2026 10:14 — with
GitHub Actions
Inactive
ActivePeter
temporarily deployed
to
OPENAI_API_KEY
August 4, 2026 11:21 — with
GitHub Actions
Inactive
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR #50 Overview / PR #50 概述
perf: add hybrid S3 writes and shared lease keepaliveperf/s3-hybrid-kv-writes→main+12,657 / -1,267English
Summary
PR #50 upgrades FluxonFS S3 object I/O from a mostly sequential, chunk-by-chunk RPC path to a size-aware bounded pipeline. Small objects are completed with one RPC, while large objects use write sessions with bounded buffering, concurrent batch delivery, backpressure, and an explicit finalize barrier. Large payload batches use Fluxon KV by reference regardless of whether the Controller and target Agent share an Owner: KV uses shared memory locally and its Transfer Engine across Owners or machines. Raw data RPC remains an operational fallback.
The PR also strengthens the lifecycle around temporary KV keys, lease keepalive, background tasks, and FS-before-KV shutdown. On the read side, it adds bounded concurrent piece reads, holder-backed extraction of cached bytes, and
TCP_NODELAYfor small HTTP responses.Motivation
The previous S3 write path performed parent-directory checks and creation, then sent object data through repeated write RPCs before truncating the destination to its final size. Fixed RPC overhead dominated small-object writes, while large-object writes paid for many sequential data calls and additional payload copies.
Large write sessions introduce a second requirement: temporary KV references and holder-backed frames must remain valid until all consumers finish, and KV memory must not be unmapped before FluxonFS releases every holder. This PR treats data flow, temporary-key cleanup, lease keepalive, and shutdown ordering as one end-to-end lifecycle.
Main changes
1. Hybrid S3 write path
4 MiBremain buffered in the Gateway and are committed through one typedput_small_objectRPC. The Agent validates permissions, creates missing parent directories, truncates the destination, and writes the full payload in that RPC.4 MiBor above, the writer opens a long-lived write session. The threshold is evaluated while streaming, so the request does not need to declare its final size in advance.PutObject, eachUploadPart, and the final assembly performed byCompleteMultipartUploaduse the hybrid writer.32 MiBsubmissions, frames of at most8 MiB, batches of up to four frames, a default128 MiBController inflight window, a32 MiBAgent queue, and four sender tasks per target Agent.finalize(expected_frames, final_size)is the barrier that waits for all writes and sets the final file length.2. KV-backed payload path with raw-RPC fallback
KV-ref is the reference-based payload path used by a write session. Instead of carrying the batch payload in the Agent RPC, the Controller stores the batch under a temporary Fluxon KV key, then sends only the key, offset, frame boundaries, source-node generation, and sequence metadata. The Agent resolves that reference with ordinary
kv_getand keeps the returned payload owner alive until the corresponding frames have been written.4 MiBuseput_small_object; objects at or above4 MiBenter a write session whose batches first use KV-ref. FS does not select a different transport for cross-Owner placement.kv_getinvokes KV's internal Transfer Engine and returns payload accessible to the Agent. FluxonFS does not expose or directly select the Transfer API.PreferredSubClusteris only an optional source-local placement hint. If no eligible local preference exists, KV chooses placement; FluxonFS still uses KV-ref.kv_put, reference-RPC,kv_get, or reference-validation failure permanently downgrades that session to raw RPC. The retry uses the same sequence and offset, allowing the Agent to deduplicate a batch whose success ACK was lost.NodeNotFound.3. Temporary-key cleanup and shared lease keepalive
kv_put, making it the single final cleanup owner even when the put result is unknown or deletion fails.180slease. Later sessions and batches reuse the same lease and generation, keeping lease and periodic keepalive overheadO(1)with respect to the number of sessions.LeaseKeepaliveActorimplementation, but they do not share one runtime actor or one lease. Generation checks prevent an old inflight keepalive from reviving an unregistered lease.4. S3 read-path improvements
GetObjectmaintains a sliding window of bounded concurrent piece reads while preserving offset order in the HTTP body.FlatDict, locates the requested bytes field, and creates a holder-backed slice instead of materializing the full dictionary and copying the field into an intermediate buffer.TCP_NODELAY, reducing Nagle/delayed-ACK latency for small objects and small Range responses.5. Retryable shutdown and ownership barriers
close(), repeated close attempts, andDropfallback, avoiding competing cleanup paths.Data-path summary
< 4 MiBput_small_objectRPC>= 4 MiBfinalizewaits for every expected frame and applies the final lengthCompatibility and explicit boundaries
put_start/put_commitAPI or second FluxonFS-specific keepalive subsystem is introduced.Vec<u8>.finalizewaits forwrite_allcompletion and sets the final length; it does not callfsyncorsyncfs.abortreleases session resources but does not roll back bytes already written to restore an older object version.Performance and validation
The documentation added by this PR includes a single-node
rclone v1.60.1comparison between FluxonFS S3 and Alluxio S3 Proxy. Both systems were run three times across2,000 × 4 KiB,256 × 1 MiB, and32 × 256 MiBobjects at concurrency1,8, and32, for 162 validated cases in total.36%–726%for persisted PUT and7%–661%for cold reads.8%–43%; medium and large sequential-throughput results were generally close, except for a larger 1 MiB gain at concurrency 8.The user-facing validation covers bucket checks, listing, upload, download, delete, Range GET, and Multipart Upload through
rclone. At the snapshot date, the latest PR check rollup is green for wheel packaging, two-virtual-node CI, large-scale MQ CI, and documentation image construction. The PR remains open and is awaiting review approval.Documentation included
中文
概述
PR #50 将 FluxonFS S3 对象 I/O 从以顺序分块 RPC 为主的链路,升级为按对象大小选择的有界流水线。小对象通过一次 RPC 完成,大对象进入带有界缓存、并发 batch 发送、背压和明确 finalize 屏障的 write-session。大 payload 无论同 Owner 还是跨 Owner 都通过 Fluxon KV 引用传递:KV 在本地复用共享内存,跨 Owner 或跨机时使用内部 Transfer Engine;Raw RPC 只作为运行失败兜底。
本 PR 同时强化了临时 KV key、lease keepalive、后台任务以及 FS-before-KV 关闭顺序的生命周期。在读取侧,新增有界并发 piece 读取、holder-backed 缓存数据提取,以及面向小型 HTTP 响应的
TCP_NODELAY优化。背景与目标
原 S3 写入路径会逐级检查和创建父目录,再通过多次 write RPC 发送对象数据,最后将目标文件截断到最终长度。对小对象来说,固定 RPC 开销占比很高;对大对象来说,顺序数据调用和额外 payload 复制限制了吞吐。
大对象 write-session 还带来另一项要求:临时 KV 引用和 holder-backed frame 必须存活到所有消费者完成,FluxonFS 释放全部 holder 之前,KV 共享内存不能被卸载。因此,本 PR 将数据流、临时 key 回收、lease keepalive 和关闭顺序作为同一个端到端生命周期处理。
核心改动
1. S3 混合写入链路
4 MiB的对象保留在 Gateway 内存中,通过一次 typedput_small_objectRPC 提交。Agent 在同一个操作内校验权限、创建缺失父目录、截断目标文件并写入完整 payload。4 MiB时,writer 打开长生命周期 write-session。阈值在流式接收过程中判断,不要求请求预先声明最终大小。PutObject、每个UploadPart,以及CompleteMultipartUpload的最终对象组装都接入混合写入器。32 MiBsubmit、不超过8 MiB的 frame、每 batch 最多 4 个 frame、Controller 默认128 MiBsession 在途窗口、Agent32 MiB队列,以及每个目标 Agent 4 个 sender task。finalize(expected_frames, final_size)才是等待全部写入完成并设置最终文件长度的屏障。2. KV-backed payload 路径与 Raw RPC 降级
KV-ref 是 write-session 使用的引用式 payload 路径。Controller 不把 batch payload 直接放进 Agent RPC,而是先以临时 key 将 batch 写入 Fluxon KV,再通过 RPC 发送 key、offset、frame 边界、source node generation 和 sequence 等元数据。Agent 使用普通
kv_get解析该引用,并让返回的 payload owner 一直存活到对应 frame 写入完成。4 MiB使用put_small_object;达到或超过4 MiB后进入 write-session,每个 batch 先走 KV-ref。FS 不因跨 Owner 改选其他传输方式。kv_get由 KV 内部 Transfer Engine 搬运并返回 Agent 可访问的 payload。FluxonFS 不暴露或直接选择 Transfer API。PreferredSubCluster只作为可选的 source-local 放置提示;没有合适的本地提示时由 KV 自行选址,仍然使用 KV-ref。kv_put、引用 RPC、kv_get或引用校验失败时,session 会永久降级到 Raw RPC。重试沿用相同 sequence 和 offset,因此 Agent 可以去重“数据已接纳但成功 ACK 丢失”的 batch。NodeNotFound时,才访问中央 FS Master registry 刷新快照。3. 临时 key 回收与共享 lease keepalive
kv_put开始前记录临时 key,即使 put 结果不确定或 delete 失败,它仍然是唯一最终回收者。180slease;后续 session 和 batch 复用同一 lease 与 generation,使 lease 和周期 keepalive 开销相对 session 数保持O(1)。LeaseKeepaliveActor实现,但不共享同一个运行时 actor 或 lease。generation 校验可阻止旧的在途 keepalive 复活已注销 lease。4. S3 读取链路优化
GetObject使用有界并发 piece 滑动窗口,同时保证 HTTP Body 仍按对象 offset 顺序输出。FlatDict、定位目标 bytes 字段,并创建 holder-backed slice,不再先物化完整字典并把字段复制到中间缓冲区。TCP_NODELAY,降低小对象和小 Range 响应受到 Nagle/delayed-ACK 交互影响时的额外延迟。5. 可重试关闭与资源所有权屏障
close()、失败后的再次 close 和Dropfallback 使用同一个后台 shutdown owner,避免多条清理路径相互竞争。数据路径摘要
< 4 MiBput_small_objectRPC>= 4 MiBfinalize等待所有预期 frame,并设置最终长度兼容性与明确边界
put_start/put_commitAPI,也不引入第二套 FluxonFS 专用 keepalive 子系统。Vec<u8>。finalize等待write_all完成并设置最终长度,但不调用fsync或syncfs。abort只释放 session 资源,不会回滚已经写入的字节并恢复旧对象版本。性能与验证
本 PR 新增文档包含 FluxonFS S3 与 Alluxio S3 Proxy 的单机
rclone v1.60.1对比。两套服务分别重复运行 3 次,覆盖2,000 × 4 KiB、256 × 1 MiB、32 × 256 MiB三种规模和并发1、8、32,共完成 162 个通过内容与磁盘 I/O 校验的案例。36%–726%,冷读为7%–661%。8%–43%;除 1 MiB、并发 8 的较明显优势外,中大文件顺序吞吐整体接近。面向用户的验证通过
rclone覆盖 bucket 检查、列举、上传、下载、删除、Range GET 和 Multipart Upload。截至快照日期,PR 最新检查汇总中 wheel 打包、双虚拟节点 CI、大规模 MQ CI 和文档镜像构建均为绿色。PR 当前仍处于开放状态,等待审阅批准。随 PR 提供的文档