web-dev-qa-db-ja.com

gRPC:C ++で非同期サーバーをシャットダウンするための推奨される方法は何ですか?

2つの非同期サービス(「マスター」と「ワーカー」)をホストするgRPCサーバーがあり、サーバーの正常なシャットダウンを実装したいと思います。各サービスには独自の_grpc::CompletionQueue_があります。

関連する可能性のある2つのShutdown()メソッドがあるようです: grpc::CompletionQueue::Shutdown()grpc::Server::Shutdown() ですが、どれを使用すべきかがドキュメントから明確ではありません。

非同期サービスをシャットダウンするための良いパターンは何ですか?

14
mrry

TL; DR:grpc::Server::Shutdown()grpc::CompletionQueue::Shutdown()の両方を呼び出す必要があります (サービスで使用される完了キューごとに)クリーンにシャットダウンします。

  1. cq_->Shutdown() を呼び出す場合、観察可能な唯一の影響は、Service::AsyncService::RequestFoo()(対応するFoo RPCに対して生成されたメソッド)への後続の呼び出しが失敗することです。アサーション。対応するCAPIメソッド( grpc_completion_queue_shutdown() )のドキュメントを読むと、キューに新しい作業を追加することは違法であるように見えます。 RequestFoo()を呼び出すことにより、cq_->Shutdown()が呼び出された後にエンキューが試行されないように、サービスラッパークラス(ミューテックスで保護)にis_shutdown_メンバーを追加しました。ただし、これを行った後、完了キューは cq_->Next() で無期限にブロックされます。エンキューされたタグはどれも完了していません(エラーまたはその他の理由で)。

  2. 代わりに server_->Shutdown() を呼び出すと、キューに入れられたすべてのタグがすぐに完了します(ok == falseを使用)。ただし、完了キューはcq_->Next()で無期限にブロックされ続けます。

cq_->Shutdown()(定義された完了キューごとに)とserver_->Shutdown()の両方を呼び出すと、クリーンシャットダウンが実行されます。

注意点:grpc::ServerContext::AsyncNotifyWhenDone()を使用して通話キャンセルのタグを登録した場合、サーバーが以前にシャットダウンした場合、これらはcq_->Next()によって返されませんその呼び出しの最初の要求が受信されます。メモリリークを回避したい場合は、対応するタグ構造のメモリ管理に注意する必要があります。

14
mrry