2016-02-29 11 views
9

Ho un server gRPC che ospita due servizi asincroni ("Master" e "Worker"), e vorrei implementare un arresto regolare per il server. Ogni servizio ha il proprio grpc::CompletionQueue.gRPC: Qual è il modo consigliato di arrestare un server asincrono in C++?

Sembrano esserci due metodi Shutdown() che potrebbero essere rilevanti: grpc::CompletionQueue::Shutdown() e grpc::Server::Shutdown(), ma non è chiaro dalla documentazione quali dovrebbero essere utilizzati.

Qual è un buon schema per lo spegnimento di un servizio asincrono?

risposta

8

TL; DR: Devi chiamare sia grpc::Server::Shutdown() e grpc::CompletionQueue::Shutdown() (per ogni coda di completamento utilizzati nel servizio) a chiudere in modo pulito.

  1. Se si chiama cq_->Shutdown(), l'unico effetto osservabile è che le chiamate successive a Service::AsyncService::RequestFoo() (metodo generato per il corrispondente Foo RPC) sicuro con un'affermazione. Dalla lettura della documentazione del metodo API C corrispondente (grpc_completion_queue_shutdown()), sembra che sia illegale aggiungere nuovi lavori alla coda — ovvero chiamando RequestFoo() — così ho aggiunto un membro is_shutdown_ alle mie classi wrapper del servizio (protetto da un mutex) in modo che non vengano effettuati tentativi di accodamento dopo la chiamata a cq_->Shutdown(). Tuttavia, dopo aver eseguito questa operazione, la coda di completamento si blocca indefinitamente in cq_->Next(). Nessuno dei tag enqueued è completo (con un errore o altro).

  2. Se invece si chiama server_->Shutdown(), tutti i tag accodati vengono completati immediatamente (con ok == false). Tuttavia, la coda di completamento continua a bloccare indefinitamente in cq_->Next().

Calling sia cq_->Shutdown() (per ogni coda di completamento definito) e server_->Shutdown() si traduce in un arresto pulito.

Un avvertimento: se si utilizza grpc::ServerContext::AsyncNotifyWhenDone() per registrare un tag per la cancellazione delle chiamate, questi saranno non essere restituiti dal cq_->Next() se il server si spegne prima che la richiesta iniziale è ricevuto per quella chiamata. Dovrai essere cauto con la gestione della memoria della struttura di tag corrispondente, se vuoi evitare perdite di memoria.

Problemi correlati