2つの非同期サービス(「マスター」と「ワーカー」)をホストするgRPCサーバーがあり、サーバーの正常なシャットダウンを実装したいと思います。各サービスには独自の_grpc::CompletionQueue
_があります。
関連する可能性のある2つのShutdown()
メソッドがあるようです: grpc::CompletionQueue::Shutdown()
と grpc::Server::Shutdown()
ですが、どれを使用すべきかがドキュメントから明確ではありません。
非同期サービスをシャットダウンするための良いパターンは何ですか?
TL; DR:grpc::Server::Shutdown()
と grpc::CompletionQueue::Shutdown()
の両方を呼び出す必要があります (サービスで使用される完了キューごとに)クリーンにシャットダウンします。
cq_->Shutdown()
を呼び出す場合、観察可能な唯一の影響は、Service::AsyncService::RequestFoo()
(対応するFoo
RPCに対して生成されたメソッド)への後続の呼び出しが失敗することです。アサーション。対応するCAPIメソッド( grpc_completion_queue_shutdown()
)のドキュメントを読むと、キューに新しい作業を追加することは違法であるように見えます。 RequestFoo()
を呼び出すことにより、cq_->Shutdown()
が呼び出された後にエンキューが試行されないように、サービスラッパークラス(ミューテックスで保護)にis_shutdown_
メンバーを追加しました。ただし、これを行った後、完了キューは cq_->Next()
で無期限にブロックされます。エンキューされたタグはどれも完了していません(エラーまたはその他の理由で)。
代わりに server_->Shutdown()
を呼び出すと、キューに入れられたすべてのタグがすぐに完了します(ok == false
を使用)。ただし、完了キューはcq_->Next()
で無期限にブロックされ続けます。
cq_->Shutdown()
(定義された完了キューごとに)とserver_->Shutdown()
の両方を呼び出すと、クリーンシャットダウンが実行されます。
注意点:grpc::ServerContext::AsyncNotifyWhenDone()
を使用して通話キャンセルのタグを登録した場合、サーバーが以前にシャットダウンした場合、これらはcq_->Next()
によって返されませんその呼び出しの最初の要求が受信されます。メモリリークを回避したい場合は、対応するタグ構造のメモリ管理に注意する必要があります。