[英]gRPC: What is the recommended way to shut down an asynchronous server in C++?
I have a gRPC server that hosts two asynchronous services ("Master" and "Worker"), and I would like to implement graceful shutdown for the server. 我有一个gRPC服务器,它承载两个异步服务(“Master”和“Worker”),我想为服务器实现正常关闭。 Each service has its own
grpc::CompletionQueue
. 每个服务都有自己的
grpc::CompletionQueue
。
There appear to be two Shutdown()
methods that might be relevant: grpc::CompletionQueue::Shutdown()
and grpc::Server::Shutdown()
, but it's not clear from the documentation which ones should be used. 似乎有两个可能相关的
Shutdown()
方法: grpc::CompletionQueue::Shutdown()
和grpc::Server::Shutdown()
,但是从文档中不清楚应该使用哪些方法。
What is a good pattern for shutting down an asynchronous service? 关闭异步服务有什么好的模式?
TL;DR: You must call both grpc::Server::Shutdown()
and grpc::CompletionQueue::Shutdown()
(for each completion queue used in the service) to shut down cleanly. TL; DR:你必须同时调用
grpc::Server::Shutdown()
和grpc::CompletionQueue::Shutdown()
(对于服务中使用的每个完成队列)来干净地关闭。
If you call cq_->Shutdown()
, the only observable effect is that subsequent calls to Service::AsyncService::RequestFoo()
(the generated method for the corresponding Foo
RPC) fail with an assertion. 如果你调用
cq_->Shutdown()
,唯一可观察的效果是后续调用Service::AsyncService::RequestFoo()
(相应的Foo
RPC的生成方法)失败并带有断言。 From reading the documentation of the corresponding C API method ( grpc_completion_queue_shutdown()
), it appears that it is illegal to add new work to the queue—ie by calling RequestFoo()
—so I added an is_shutdown_
member to my service wrapper classes (protected by a mutex) so that no enqueue attempts are made after cq_->Shutdown()
is called. 通过阅读相应的C API方法(
grpc_completion_queue_shutdown()
)的文档,似乎将新工作添加到队列是非法的 - 即通过调用RequestFoo()
我将is_shutdown_
成员添加到我的服务包装类(protected)通过互斥锁),以便在调用cq_->Shutdown()
之后不会进行入队尝试。 However, after doing this, the completion queue blocks indefinitely in cq_->Next()
. 但是,执行此操作后,完成队列将无限期地阻塞在
cq_->Next()
。 None of the enqueued tags complete (with an error or otherwise). 没有排队的标签完成(有错误或其他)。
If instead you call server_->Shutdown()
, all of the enqueued tags complete immediately (with ok == false
). 如果您调用
server_->Shutdown()
,则所有排队的标签立即完成(使用ok == false
)。 However, the completion queue continues to block indefinitely in cq_->Next()
. 但是,完成队列继续在
cq_->Next()
无限期地阻塞。
Calling both cq_->Shutdown()
(for each defined completion queue) and server_->Shutdown()
results in a clean shutdown. 同时调用
cq_->Shutdown()
(对于每个已定义的完成队列)和server_->Shutdown()
导致干净关闭。
One caveat: if you use grpc::ServerContext::AsyncNotifyWhenDone()
to register a tag for call cancellation, these will not be returned by cq_->Next()
if the server shuts down before the initial request is received for that call. 需要注意的是:如果使用
grpc::ServerContext::AsyncNotifyWhenDone()
来注册呼叫取消标签,那么如果服务器在收到该呼叫的初始请求之前关闭,则cq_->Next()
将不会返回这些标签。 You will need to be cautious with the memory management of the corresponding tag structure, if you want to avoid memory leaks. 如果要避免内存泄漏,则需要对相应标记结构的内存管理保持谨慎。
Warning The server must be either shutting down or some other thread must call Shutdown for this function to ever return. 警告服务器必须要么关闭,要么其他线程必须调用Shutdown才能返回此功能。
http://static.grumpycoder.net/pixel/ref/c++/html/classgrpc_1_1_server.html http://static.grumpycoder.net/pixel/ref/c++/html/classgrpc_1_1_server.html
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.