我正在使用gRPC进行C++ App(gRPC Server)和Java App(gRPC Client)之间的进程间通信.一切都在一台机器上运行.我想提供客户端关闭服务器的可能性.我的想法是在proto中添加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, "");
}
Run Code Online (Sandbox Code Playgroud)
但是,ShutDown会阻塞,直到所有RPC调用都被处理,这意味着死锁.有没有优雅的方法如何实现它?
小智 8
我正在使用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;
}
Run Code Online (Sandbox Code Playgroud)
为了使这项工作,我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();
Run Code Online (Sandbox Code Playgroud)
一旦我有了这个,我也能够通过信号处理程序支持干净关闭:
auto handler = [](int s) {
exit_requested.set_value();
};
std::signal(SIGINT, handler);
std::signal(SIGTERM, handler);
std::signal(SIGQUIT, handler);
Run Code Online (Sandbox Code Playgroud)
到目前为止,我对这种方法感到满意,它使我保持在gRPC和标准c ++库的范围内.而不是使用一些全局范围的承诺(我必须在服务实现源中将其声明为外部)我应该想到更优雅的东西.
这里需要注意的一点是,多次设置promise的值会引发异常.如果您以某种方式同时发送关闭消息,则可能会发生这种情况pkill -2 my_awesome_service.当我的持久层中出现死锁以防止关闭完成时,我实际上遇到了这种情况,当我尝试再次发送SIGINT时,服务中止了!对于我的需求,这仍然是一个可接受的解决方案,但我很想知道解决这个小问题的替代方案.