C++ gRPC异步服务端执行关机流程时永久卡住如何解决?
gRPC 1.40.x Windows 平台异步服务端强制关机方案
核心优化逻辑
1. 调整AsyncNext循环的退出条件
你已为AsyncNext配置了16ms超时,可新增全局原子关机标记,每次超时后检查标记状态,触发关机时直接跳出循环,不再继续调用AsyncNext接收新RPC:
// 全局/类成员原子关机标记,触发关机前首先置为true std::atomic<bool> g_shutdown_flag = false; // 工作线程内的AsyncNext循环 void WorkThreadFunc(CompletionQueue* cq) { while (!g_shutdown_flag.load()) { void* tag = nullptr; bool ok = false; auto next_status = cq->AsyncNext(&tag, &ok, gpr_time_from_millis(16, GPR_CLOCK_REALTIME)); if (next_status == CompletionQueue::SHUTDOWN) { break; } if (next_status == CompletionQueue::TIMEOUT) { // 超时后二次检查关机标记,直接退出 if (g_shutdown_flag.load()) { break; } continue; } // 原有正常RPC处理逻辑 ProcessRpc(tag, ok); } }
2. 带超时兜底的关机流程
官方基础关机流程新增超时判断,超过预设等待时间后直接强制终止工作线程,避免进程挂起:
void ShutdownServer(std::unique_ptr<Server>& server, CompletionQueue* cq, std::thread& work_thread) { // 第一步:先置关机标记,通知AsyncNext循环停止 g_shutdown_flag.store(true); // 第二步:调用带超时的Server Shutdown,3s后主动断开所有客户端连接 server->Shutdown(gpr_time_from_seconds(3, GPR_CLOCK_REALTIME)); // 第三步:关闭CompletionQueue cq->Shutdown(); // 第四步:等待工作线程正常退出,最多等待2s if (work_thread.joinable()) { if (work_thread.join_for(std::chrono::seconds(2)) == false) { // 超时未退出,Windows平台下强制终止线程(进程即将退出,可忽略少量资源泄漏) TerminateThread(work_thread.native_handle(), 0); } } // 第五步:排空队列剩余事件,此时已无活跃工作线程不会阻塞 DrainQue(cq); }
3. 适配gRPC 1.40.x Windows平台已知问题
该版本Windows IOCP底层实现存在CompletionQueue已调用Shutdown后仍持续返回超时事件的bug,触发关机后可直接丢弃所有AsyncNext返回结果,不处理任何新RPC请求,避免队列持续被新事件填满导致死循环。
内容的提问来源于stack exchange,提问作者Jan Mrázek
相关产品推荐
相关产品推荐

