我有一个gRPC服务器,它承载两个异步服务(“Master”和“Worker”),我想为服务器实现正常关闭。每项服务都有自己的grpc::CompletionQueue
。
似乎有两种可能相关的Shutdown()
方法:grpc::CompletionQueue::Shutdown()
和grpc::Server::Shutdown()
,但从文档中不清楚应该使用哪些方法。
关闭异步服务有什么好的模式?
TL; DR:你必须同时调用grpc::Server::Shutdown()
和grpc::CompletionQueue::Shutdown()
(对于服务中使用的每个完成队列)来干净地关闭。
cq_->Shutdown()
,唯一可观察到的效果是后续调用Service::AsyncService::RequestFoo()
(相应的Foo
RPC的生成方法)失败并带有断言。通过阅读相应的C API方法(grpc_completion_queue_shutdown()
)的文档,似乎将新工作添加到队列中是非法的 - 即。通过调用RequestFoo()
-所以我在我的服务包装类中添加了一个is_shutdown_
成员(受互斥锁保护),这样在调用cq_->Shutdown()
之后就不会进行入队尝试。但是,执行此操作后,完成队列将无限期地阻塞在cq_->Next()
中。没有排队的标签完成(有错误或其他)。server_->Shutdown()
,所有排队的标签立即完成(使用ok == false
)。但是,完成队列继续在cq_->Next()
中无限期阻塞。调用cq_->Shutdown()
(对于每个已定义的完成队列)和server_->Shutdown()
都会导致干净关闭。
需要注意的一点是:如果您使用grpc::ServerContext::AsyncNotifyWhenDone()
为呼叫取消注册标记,那么如果服务器在收到该呼叫的初始请求之前关闭,cq_->Next()
将不会返回这些标记。如果要避免内存泄漏,则需要对相应标记结构的内存管理保持谨慎。
警告服务器必须要么关闭,要么其他线程必须调用Shutdown才能返回此功能。
http://static.grumpycoder.net/pixel/ref/c++/html/classgrpc_1_1_server.html