gRPC服务器反应器Callback API中OnCancel方法的正确使用
gRPC C++ 流式服务器反应器OnCancel()的正确处理方案
背景
我们使用gRPC官方的RouteGuide回调服务器示例代码,其中包含ServerWriteReactor、ServerReadReactor、ServerBidiReactor三类流式反应器。示例中,当服务器主动关闭连接时触发的OnDone()回调里,子类通过delete this直接删除实例:
class Lister : public grpc::ServerWriteReactor<Feature> { public: ... void OnDone() override { delete this; } .... }
但基类还有OnCancel()虚拟回调——当客户端主动断开连接时触发。如果直接在OnCancel()中写delete this,会导致后续调用grpc::Server::ShutDown()无法返回,数据流频繁时还会触发gRPC内部异常,因此这种写法不安全。
问题解答
1. 如何正确处理流式服务器反应器中的OnCancel()方法?
正确的处理逻辑是:
- 在
OnCancel()中先通知gRPC完成取消流程,不要立即删除实例 - 保留
OnDone()中的delete this逻辑,统一在OnDone()中处理实例销毁
具体实现代码示例:
class Lister : public grpc::ServerWriteReactor<Feature> { public: // 原有成员和方法... void OnDone() override { delete this; } void OnCancel() override { // 通知gRPC确认取消请求,触发后续的OnDone回调 Finish(grpc::Status::CANCELLED); // 若有自定义异步资源(如定时器、业务回调),在此处先清理 // 例如:CancelCustomTimer(); } };
关键在于调用Finish(grpc::Status::CANCELLED),这会让gRPC完成该反应器的内部资源清理,最终触发OnDone(),确保生命周期管理的一致性。
2. 触发OnCancel()后,何时才是安全删除服务器反应器实例的时机?
必须等待OnDone()回调被触发后,才是安全删除实例的时机。
OnCancel()仅代表客户端发起了取消请求,但gRPC内部仍可能存在未完成的异步操作、资源释放流程。只有当OnDone()被调用时,才意味着该反应器的所有生命周期流程已彻底结束,此时删除实例不会干扰gRPC的内部逻辑,也不会导致ShutDown()卡住或触发异常。
内容的提问来源于stack exchange,提问作者Dmitry Gorelov
相关产品推荐
相关产品推荐

