Ответ 1
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()
, если сервер выключится до того, как будет получен первоначальный запрос для этого вызова. Вам нужно быть осторожным с управлением памятью соответствующей структуры тегов, если вы хотите избежать утечек памяти.