![](/img/trans.png)
[英]gRPC: How can RPC handlers properly detect if `Server` has been `Shutdown()`
[英]How to shutdown gRPC server from Client (using RPC function)
我将gRPC用于C ++ App(gRPC服务器)和Java App(gRPC客户端)之间的进程间通信。 一切都在一台机器上运行。 我想为客户提供关闭服务器的可能性。 我的想法是将RPC函数添加到服务中,以实现此目的。
C ++实现为:
class Service : public grpcGeneratedService
{
public:
......
private:
grpc::Server* m_pServer;
};
grpc::Status Service::ShutDown(grpc::ServerContext* pContext, const ShutDownRequest* pRequest, ShutDownResponse* pResponse)
{
if (m_pServer)
m_pServer->Shutdown();
return grpc::Status(grpc::StatusCode::OK, "");
}
但是ShutDown会阻塞,直到处理完所有RPC调用为止,这意味着死锁。 有什么优雅的方法可以实现它吗?
我使用的std :: promise几乎与您的方法完全一样。
// Somewhere in the global scope :/
std::promise<void> exit_requested;
// My method looks nearly identical to yours
Status CoreServiceImpl::shutdown(ServerContext *context, const SystemRequest *request, Empty*)
{
LOG(INFO) << context->peer() << " - Shutdown request acknowledged.";
exit_requested.set_value();
return Status::OK;
}
为了使此工作正常进行,我在第二个线程中调用server->Wait()
,并在将来等待exit_requested
诺言来阻止关闭调用:
auto serveFn = [&]() {
server->Wait();
};
std::thread serving_thread(serveFn);
auto f = exit_requested.get_future();
f.wait();
server->Shutdown();
serving_thread.join();
一旦有了这个,我还可以通过信号处理程序支持干净关闭:
auto handler = [](int s) {
exit_requested.set_value();
};
std::signal(SIGINT, handler);
std::signal(SIGTERM, handler);
std::signal(SIGQUIT, handler);
到目前为止,我对这种方法很满意,它使我始终处于gRPC和标准c ++库的范围之内。 与其使用某些全局范围的promise(我必须在服务实现源中将其声明为外部的promise),不如考虑更优雅的方法。
这里要注意的一件事是,多次设置promise的值将引发异常。 如果您以某种方式发送关闭消息并同时发送pkill -2 my_awesome_service
,则可能会发生这种情况。 当我的持久层中存在一个死锁阻止关闭完成时,当我尝试再次发送SIGINT时,我实际上遇到了这个问题,而是服务被中止了! 对于我的需求,这仍然是可以接受的解决方案,但是我很想听听能解决或解决这个小问题的替代方案。
您可以从ShutDown()处理程序创建std :: function,然后在单独的线程(或线程池)中运行该函数。 这将允许将RPC处理与关闭逻辑的执行脱钩,并消除死锁。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.