【Ceph RADOS】OSD 与 Messenger:daemon 结构、msgr2 协议与 Op 入队路径

💡 原文中文,约10400字,阅读约需25分钟。
📝

内容提要

本文介绍Ceph OSD通信层架构:msgr2协议负责连接建立与帧传输,AsyncMessenger用epoll多路复用处理I/O,ShardedOpWQ按PG哈希分片调度操作。重点分析Op从TCP帧进入OSD队列的路径、心跳机制独立性,以及mClock调度器如何管理优先级,帮助定位通信层故障。

🔎

延伸解读

排障定位:区分“I/O 慢”与“排队慢”

文章指出,通信层故障有两种典型表现:连接建立失败(如 connection refused)和连接成功但消息处理延迟高。后者常因 ShardedOpWQ 的某个 shard 积压导致,即使 CPU 空闲,其他 shard 也无法分担。理解 Messenger 与 ShardedOpWQ 的边界,是判断“I/O 路径慢”还是“排队慢”的关键。若客户端超时而 ceph -s 仍 HEALTH_OK,应优先检查目标 PG 所在 shard 是否被恢复类 Op 占满,以及 client_messenger 与 cluste

心跳独立性:避免“忙”被误判为“宕机”

OSD 心跳使用独立的 cluster_messenger,与处理客户端 Op 的 client_messenger 分离。即使 client_messenger 因 ShardedOpWQ 积压而响应迟缓,心跳仍能正常发送,确保 MON 不会因高 I/O 压力误判 OSD 宕机。这种设计防止了“OSD 忙但未宕机”被误判为“OSD 宕机”,是理解高负载下集群稳定性的重要细节。

peering 期间的 EAGAIN:队列上限而非网络问题

PG 处于 peering 状态时,客户端 Op 会暂存在 PG::waiting_for_active 队列,等待 peering 完成后重放,因此客户端写操作表现为“阻塞而不报错”。但该队列有上限(osd_max_waiting_ops,默认 512),超过后新 Op 会被拒绝并返回 EAGAIN,客户端刷新 map 后重试。理解这个上限,可以避免将 peering 期间的零散 EAGAIN 误诊为网络问题。

Q&A

Ceph OSD 的通信层主要由哪些组件构成?

Ceph OSD 的通信层主要由 AsyncMessenger 和 ShardedOpWQ 构成。AsyncMessenger 负责 I/O 多路复用和连接管理,基于 epoll;ShardedOpWQ 是主工作队列,按 PG 哈希分片调度操作。OSD 还有 client_messenger 和 cluster_messenger 两个独立的 messenger,分别处理客户端和集群内部消息。

msgr2 协议相比 msgr1 有哪些改进?

msgr2 相比 msgr1 增加了连接层加密(AES-GCM)、标准化的握手过程,以及多路复用框架(预留但未全面启用)。msgr2 的帧结构分为 Preamble、Segments 和 Epilogue,便于调试和版本兼容。

Ceph OSD 中 Op 请求从网络进入到 ShardedOpWQ 的路径是怎样的?

Op 请求从网络进入 OSD 的路径为:epoll 事件触发 AsyncConnection::process(),然后 ProtocolV2 读取并解析帧,接着通过 Messenger::ms_deliver_dispatch() 调用 OSD::ms_dispatch2(),根据消息类型分发到 handle_op(),再调用 enqueue_op() 将 Op 放入 ShardedOpWQ 的队列中。

ShardedOpWQ 是如何保证同一 PG 内操作顺序的?

ShardedOpWQ 通过将 Op 按 PG 的哈希值分配到固定的 shard,同一 PG 的 Op 总是在同一个 shard 中按序处理,从而保证 PG 内的操作顺序。

Ceph OSD 的心跳机制是如何工作的?为什么心跳使用独立的 messenger?

OSD 之间通过 peer 心跳(MOSDPing)互相检测存活,若一个 OSD 在 osd_heartbeat_grace(默认 20 秒)内未收到另一个 OSD 的心跳,会向 MON 报告。MON 在收到足够多报告后才标记 OSD down。心跳使用独立的 cluster_messenger,与处理客户端 Op 的 client_messenger 分离,这样即使 client_messenger 因队列积压而响应迟缓,心跳也不受影响,避免 OSD 忙但未宕机被误判为宕机。

mClock 调度器在 Ceph OSD 中是如何工作的?

mClock 调度器是 Ceph Squid 版本默认的 Op 调度器,基于 reservation、weight、limit 三类参数对共享队列进行 QoS 控制。它将客户端 Op、恢复、scrub 等分成不同服务类,显式保证前台最低份额,同时给后台上限,避免恢复操作打满磁盘。

在 Ceph 排障中,如何判断 Op 卡在通信层还是 I/O 路径?

如果连接建立失败(如 connection refused),通常是防火墙或 OSD 进程未启动;如果连接建立成功但消息处理延迟高,可能是 ShardedOpWQ 的 shard 积压。需要检查该 PG 所在 shard 是否被恢复类 Op 占满,以及 client_messenger 与 cluster_messenger 是否出现不对称延迟。不要一上来就调整 osd_op_num_threads,除非已证明队列深度与 CPU 绑定关系。

🏷️

标签

➡️

继续阅读