gRPC 客户端如何用 wait-for-ready 让 RPC 等待 channel 就绪而不立即失败?
gRPC 客户端如何用 wait-for-ready 让 RPC 等待 channel 就绪而不立即失败【免费下载链接】grpcC based gRPC (C, Python, Ruby, Objective-C, PHP, C#)项目地址: https://gitcode.com/GitHub_Trending/gr/grpc服务器还没启动、或网络抖动导致 channel 处于TRANSIENT_FAILURE时C 客户端发出的 RPC 默认会立即失败fail fast。如果你的任务需要服务端没就绪就先等着不要直接报错返回gRPC 提供了 per-RPC 的 wait-for-ready 选项RPC 会被排队直到 channel 进入READY再发出。本文基于 gRPC 仓库中的规范文档 doc/wait-for-ready.md、C 客户端 API include/grpcpp/client_context.h 和可运行示例 examples/cpp/wait_for_ready/给出设置方式和完整验证路径。先弄清语义哪些状态会 fail fastwait-for-ready 改变什么doc/wait-for-ready.md 给出的规范是当 channel 处于TRANSIENT_FAILURE或SHUTDOWN状态时RPC 无法立即发送gRPC 实现应当SHOULD立即失败这就是 fail fast该名称是历史用法。channel 处于CONNECTING、READY或IDLE状态时RPC 不应因此失败。实现**可以MAY**提供 per-RPC 选项让 RPC 不因TRANSIENT_FAILURE而失败而是排队直到 channel 变为READY这就是 wait for ready。即使设置了 wait-for-readyRPC 在READY之前仍可能因不相关的原因失败例如 channel 进入SHUTDOWN或 RPC 的 deadline 到期。也就是说这个选项不保证 RPC 一定成功它只把因 channel 未就绪而立即失败替换为等待 channel 就绪deadline 和 SHUTDOWN 仍然会让 RPC 失败。在 C 客户端上设置 wait-for-ready设置入口是grpc::ClientContext的set_wait_for_ready(bool)定义在 include/grpcpp/client_context.h/// Trigger wait-for-ready or not on this request. /// See https://github.com/grpc/grpc/blob/master/doc/wait-for-ready.md. /// If set, if an RPC is made when a channels connectivity state is /// TRANSIENT_FAILURE or CONNECTING, the call will not fail fast, /// and the channel will wait until the channel is READY before making the /// call. void set_wait_for_ready(bool wait_for_ready) { wait_for_ready_ wait_for_ready; wait_for_ready_explicitly_set_ true; } /// DEPRECATED: Use set_wait_for_ready() instead. void set_fail_fast(bool fail_fast) { set_wait_for_ready(!fail_fast); }两个要点这是per-RPC选项每次调用都要在当次调用的ClientContext上设置对同一个 stub/channel 的其他调用不生效。旧代码中的set_fail_fast(bool fail_fast)已被标记 DEPRECATED内部实现就是set_wait_for_ready(!fail_fast)。如果你在维护旧代码迁移方式就是把set_fail_fast(false)换成set_wait_for_ready(true)。最小使用形态在发起异步或同步调用前ClientContext context; context.set_wait_for_ready(true); // 该次 RPC 等待 channel READY而不是 fail fast运行仓库中的 wait_for_ready 示例仓库自带一个对照示例 examples/cpp/wait_for_ready/greeter_callback_client.cc它基于 helloworld Greeter 服务先发送一个不带wait-for-ready 的 RPC再发送一个带wait-for-ready 的 RPC让你直接对比两种行为。客户端用grpc::InsecureChannelCredentials()创建 channel服务器地址由命令行 flag--target控制默认值为localhost:50051需要连别的地址时追加--targethost:port。前置条件能在仓库根目录运行tools/bazel示例通过 bazel 目标运行依赖 examples/protos 中的 helloworld proto 目标//examples/protos:helloworld_cc_grpc见 BUILD。步骤如下注意顺序是先客户端、后服务端在仓库根目录先启动客户端tools/bazel run examples/cpp/wait_for_ready:greeter_callback_client此时服务端还没启动。按 examples/cpp/wait_for_ready/README.md 的描述你会看到未设置 WAIT_FOR_READY 的那批 RPC 因 Connection refused 失败——这就是 fail fast 的直接体现随后设置了 WAIT_FOR_READY 的 RPC 不会立刻返回失败而是停在等待 channel ready 的状态。在另一个终端启动服务端示例复用的是 helloworld 的回调式服务端tools/bazel run examples/cpp/helloworld:greeter_callback_server客户端 channel 应能连上服务端之前等待中的 RPC 应成功返回。示例 README 描述现象时写的是10 个 RPC 失败、随后 10 个带 WAIT_FOR_READY 的 RPC 等待而当前仓库中该示例的main()实际是每类各发送 1 个 RPC源码见 greeter_callback_client.cc。两者描述的是同一组对照行为运行时看到的输出以当前源码为准。结果判断怎么确认 wait-for-ready 生效对照示例的源码逻辑greeter_callback_client.cc每个 RPC 的结果分两种输出成功打印Greeter received: 服务器返回的消息失败打印error_code: error_message函数返回RPC failed。据此可以核对未设置 wait-for-ready 的 RPC服务端未运行时立即打印失败信息文档示例为 Connection refused 错误。设置了 wait-for-ready 的 RPC不会立刻打印失败源码注释写明即使服务端一直没启动该 RPC 也会一直等到 deadline 到期才失败。示例代码没有为它设置 deadline所以它表现为持续等待。启动服务端后该 RPC 变为成功打印Greeter received: ...。如果在第 2 步客户端立刻返回失败而不是等待先检查两点该次调用是否真的在ClientContext上调用了set_wait_for_ready(true)选项是 per-RPC 的作用不到别的调用上以及失败原因是否为SHUTDOWN——规范明确 wait-for-ready 不能覆盖 channel 已关闭这种情况。在自己的代码中套用把示例的模式迁移到自己的 C 客户端时结构是固定的// channel 的创建方式不变例如 std::shared_ptrChannel channel grpc::CreateChannel(target, grpc::InsecureChannelCredentials()); Greeter::Stub stub(channel); // 需要等待就绪的那次调用 ClientContext context; context.set_wait_for_ready(true); // 如需控制最长等待时间给 context 设置 deadline // context.set_deadline(std::chrono::system_clock::now() std::chrono::seconds(30)); // 然后照常发起同步或异步调用两点边界来自规范文档直接决定行为设置了 deadline 时channel 迟迟不就绪会在 deadline 到期时失败wait-for-ready 只会把立即失败推迟到 deadlinechannel 进入SHUTDOWN时 RPC 仍会失败无法靠该选项挽救。关于适用面doc/wait-for-ready.md 使用的是 MAY/SHOULD 措辞wait-for-ready 是规范允许提供的选项仓库内 C API 已实现set_wait_for_ready()如果你使用其他语言的 gRPC 实现该选项是否可用需以对应语言 SDK 的文档为准本文不展开。【免费下载链接】grpcC based gRPC (C, Python, Ruby, Objective-C, PHP, C#)项目地址: https://gitcode.com/GitHub_Trending/gr/grpc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考