Windows端gRPC Channel WaitForConnection(deadline)失效问题排查
我正在开发基于gRPC的服务端与客户端,服务端运行于Linux系统,客户端运行于Windows系统。需要处理服务端未启动但客户端已启动的场景,编写了如下代码:
auto state = m_channel->GetState(true); while (state != GRPC_CHANNEL_READY || state != GRPC_CHANNEL_SHUTDOWN) { std::chrono::time_point deadline = std::chrono::system_clock::now() + std::chrono::seconds(30); if (m_channel->WaitForStateChange(state, deadline)) { std::cout << "new state is: " << static_cast<int>(state) << "\n"; state = m_channel->GetState(true); } }
运行时出现如下错误:
I0929 22:24:05.748000000 14812 subchannel.cc:905] subchannel 0123CF78 {address=ipv4:192.168.175.130:40051, args={grpc.client_channel_factory=0x121dd68, grpc.default_authority=192.168.175.130:40051, grpc.internal.channel_credentials=0x121dce8, grpc.internal.security_connector=0x1235f28, grpc.internal.subchannel_pool=0x1225db0, grpc.max_receive_message_length=-1, grpc.primary_user_agent=grpc-c++/1.49.0-dev, grpc.resource_quota=0x1225990, grpc.server_uri=dns:///192.168.175.130:40051}}: connect failed (UNAVAILABLE:WSA Error {syscall:"ConnectEx", os_error:"No connection could be made because the target machine actively refused it.\r\n", grpc_status:14, wsa_error:10061, created_time:"2022-09-29T20:24:05.748604482+00:00"}), backing off for -1057 ms
但在Linux端运行客户端时,程序可正常等待至服务端启动。请问Windows端是否需要特定防火墙设置?另外发现退避时间为负值,而Linux端为正值且符合退避策略递增规律。
1. 修正代码循环逻辑错误
你的循环条件state != GRPC_CHANNEL_READY || state != GRPC_CHANNEL_SHUTDOWN存在逻辑漏洞:任何gRPC通道状态都不可能同时等于GRPC_CHANNEL_READY和GRPC_CHANNEL_SHUTDOWN,因此这个循环会无限执行,无法正常退出。需要将逻辑或||改为逻辑与&&,这样当通道状态变为就绪或关闭时,循环才会终止:
auto state = m_channel->GetState(true); while (state != GRPC_CHANNEL_READY && state != GRPC_CHANNEL_SHUTDOWN) { std::chrono::time_point deadline = std::chrono::system_clock::now() + std::chrono::seconds(30); if (m_channel->WaitForStateChange(state, deadline)) { std::cout << "new state is: " << static_cast<int>(state) << "\n"; state = m_channel->GetState(true); } }
2. Windows防火墙配置
日志中的WSA错误10061表示目标主动拒绝连接,结合Linux客户端正常工作的情况,大概率是Windows防火墙拦截了客户端的出站请求。可以通过以下方式处理:
- 临时关闭Windows防火墙,测试是否能正常连接;
- 永久配置:在Windows防火墙中添加出站规则,允许你的客户端程序访问目标Linux机器的40051端口。
3. 退避时间负值问题
这是gRPC 1.49.x版本在Windows平台的已知bug,根源是Windows系统时间处理逻辑与Linux不一致,导致退避时间计算异常。该问题已在gRPC 1.50.0及以上的稳定版本中修复,建议你升级gRPC到最新稳定版本即可解决。
内容的提问来源于stack exchange,提问作者Trilokesh Pradhan

