GRPC: Каков рекомендуемый способ отключения асинхронного сервера на С++?

У меня есть сервер gRPC, на котором размещаются две асинхронные службы ( "Мастер" и "Рабочий" ), и я хотел бы реализовать изящное завершение работы сервера. Каждая служба имеет свой собственный grpc::CompletionQueue.

Кажется, существуют два метода Shutdown(), которые могут быть релевантными: grpc::CompletionQueue::Shutdown() и grpc::Server::Shutdown(), но из документации не видно, какие из них следует использовать.

Что такое хороший шаблон для отключения асинхронной службы?

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

Ответ 2

  • Wait() void grpc :: Server :: Wait()
    Блокировать overridevirtual, пока сервер не выключится.

Предупреждение Сервер должен либо выключиться, либо какой-либо другой поток должен вызвать Shutdown, чтобы эта функция когда-либо возвращалась.

  • grpc :: Завершение работы сервера()

http://static.grumpycoder.net/pixel/ref/c++/html/classgrpc_1_1_server.html