Mooncake 中的协程:从 coro_rpc 到同步接口桥接
Mooncake 确实使用了协程,但它并不是把整个系统改造成“全异步架构”。截至本文分析的主分支提交 3d1665a,协程主要出现在控制面 RPC、连接管理和阻塞任务卸载等 I/O 密集路径;对外接口仍大量保留同步调用形式。 这形成了一个很实用的分层:内部用 C++20 协程组织异步流程,边界处再按需要转换成同步返回值或回调。 技术栈 Mooncake 的协程代码主要建立在两层库之上: async_simple::coro::Lazy<T> 表示一个惰性异步任务; yalantinglibs 的 coro_rpc 和 coro_io 提供异步 RPC、网络连接与线程池调度。 典型代码形态如下: async_simple::coro::Lazy<Result> request() { auto response = co_await client.send_request(...); co_return response; } Lazy<T> 创建后通常不会立刻执行。它需要被另一个协程 co_await,通过 .start(...) 启动,或者由 syncAwait(...) 驱动至完成。 路径一:Mooncake Store 的 Master RPC mooncake-store/src/master_client.cpp 中的 MasterClient::invoke_rpc 是最清晰的例子。它的外部签名是同步的: tl::expected<ReturnType, ErrorCode> MasterClient::invoke_rpc(Args&&... args); 函数内部却先构造 Lazy,再连续等待两个异步阶段: return async_simple::coro::syncAwait( [&]() -> async_simple::coro::Lazy< tl::expected<ReturnType, ErrorCode>> { auto pending = co_await pool->send_request( [&](coro_io::client_reuse_hint, coro_rpc::coro_rpc_client& client) { return client.send_request<ServiceMethod>(...); }); if (!pending.has_value()) { co_return tl::make_unexpected(ErrorCode::RPC_FAIL); } auto result = co_await std::move(pending.value()); co_return result->result(); }()); 这里有两次 co_await: ...