2016-02-29 8 views
9

Ich habe einen gRPC-Server, der zwei asynchrone Dienste hostet ("Master" und "Worker"), und ich würde gerne ein ordnungsgemäßes Herunterfahren für den Server implementieren. Jeder Dienst hat seine eigene grpc::CompletionQueue.gRPC: Was ist die empfohlene Methode zum Herunterfahren eines asynchronen Servers in C++?

Es scheint zwei Shutdown() Methoden zu geben, die relevant sein könnten: grpc::CompletionQueue::Shutdown() und grpc::Server::Shutdown(), aber aus der Dokumentation ist nicht klar, welche verwendet werden sollten.

Was ist ein gutes Muster zum Herunterfahren eines asynchronen Dienstes?

Antwort

8

TL; DR: Sie müssen beide rufen grpc::Server::Shutdown() und grpc::CompletionQueue::Shutdown() (für jeden in den Dienst verwendet Abschluss-Warteschlange) sauber herunterzufahren.

  1. Wenn Sie cq_->Shutdown() nennen, die einzige beobachtbare Effekt ist, dass nachfolgende Aufrufe Service::AsyncService::RequestFoo() (die erzeugte Methode für die entsprechende Foo RPC) mit einer Behauptung fehlschlagen. Nach dem Lesen der Dokumentation der entsprechenden C-API-Methode (grpc_completion_queue_shutdown()) scheint es illegal zu sein, neue Arbeit in die Warteschlange — hinzuzufügen, dh RequestFoo() —, so fügte ich ein is_shutdown_ Mitglied meiner Service Wrapper-Klassen (durch einen Mutex geschützt) damit keine Enqueue-Versuche unternommen werden, nachdem cq_->Shutdown() aufgerufen wird. Nachdem Sie dies getan haben, blockiert die Abschlusswarteschlange jedoch unbegrenzt in cq_->Next(). Keines der eingereihten Tags wird abgeschlossen (mit einem Fehler oder auf andere Weise). Wenn Sie stattdessen server_->Shutdown() aufrufen, werden alle eingereihten Tags sofort (mit ok == false) abgeschlossen. Die Beendigungswarteschlange wird jedoch weiterhin unbegrenzt in cq_->Next() blockiert.

Aufruf sowohl cq_->Shutdown() (für jede Abschluss-Warteschlange definiert ist) und server_->Shutdown() Ergebnisse in einem sauberen Abschaltung.

Eine Warnung: Wenn Sie grpc::ServerContext::AsyncNotifyWhenDone() verwenden, um einen Tag für Rufabstellung zu registrieren, wird diese nicht von cq_->Next() zurückgegeben werden, wenn der Server heruntergefahren, bevor die ursprüngliche Anforderung für diesen Anruf empfangen wird. Sie müssen mit der Speicherverwaltung der entsprechenden Tag-Struktur vorsichtig sein, wenn Sie Speicherlecks vermeiden wollen.

Verwandte Themen