跨机器部署gRPC服务遇连接失败问题求助
gRPC跨局域网连接失败问题排查与解决
问题现象
同一机器上运行gRPC服务端和客户端正常,但跨局域网不同机器连接时出现StatusCode.UNAVAILABLE错误,具体分两种情况:
- 初始服务端绑定
localhost时,客户端报错:
Traceback (most recent call last): File "client.py", line 29, in <module> run() File "client.py", line 25, in run add_reply = stub.Add(add_request) File "/home/caio/dev/laboratorio/mygrpc/.env/lib/python3.8/site-packages/grpc/_channel.py", line 946, in __call__ return _end_unary_response_blocking(state, call, False, None) File "/home/caio/dev/laboratorio/mygrpc/.env/lib/python3.8/site-packages/grpc/_channel.py", line 849, in _end_unary_response_blocking raise _InactiveRpcError(state) grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with: status = StatusCode.UNAVAILABLE details = "failed to connect to all addresses; last error: UNKNOWN: ipv4:192.168.100.9:50051: tcp handshaker shutdown" debug_error_string = "UNKNOWN:failed to connect to all addresses; last error: UNKNOWN: ipv4:192.168.100.9:50051: tcp handshaker shutdown {grpc_status:14, created_time:"2022-12-10T15:21:32.619696358-03:00"}" >
- 服务端改为绑定
0.0.0.0后:- 以太网连接时报错
No route to host - WiFi连接时仍报错
tcp handshaker shutdown
- 以太网连接时报错
现有代码
服务端代码
from os import system system('clear') from concurrent import futures import time import grpc from grpc import _server import sum_pb2 import sum_pb2_grpc PORT = 50051 HOST = "localhost" class Servicer(sum_pb2_grpc.SumNumbersServicer): def Add(self, request, context): print(request) add_reply = sum_pb2.AddReply() add_reply.r = request.a + request.b # return super().Add(request, context) return add_reply def serve(): server:_server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) sum_pb2_grpc.add_SumNumbersServicer_to_server(Servicer(), server) # serve._add_insecure_port(f"localhost:{PORT}") server.add_insecure_port(f"{HOST}:{PORT}") server.start() print(f"Listenning on port {PORT}") try: server.wait_for_termination() except KeyboardInterrupt: server.stop(0) if __name__ == "__main__": serve()
客户端代码
from os import system system('clear') from concurrent import futures import time from random import randint import grpc from grpc import _server import sum_pb2 import sum_pb2_grpc PORT = 50051 HOST = "localhost" HOST = "192.168.100.9" min = 0 max = 100 def run(): with grpc.insecure_channel(f"{HOST}:{PORT}") as channel: stub = sum_pb2_grpc.SumNumbersStub(channel) a = randint(min, max) b = randint(min, max) add_request = sum_pb2.AddRequest(a= a, b= b) add_reply = stub.Add(add_request) print(f"{a} + {b} = {add_reply}") if __name__ == "__main__": run()
排查与解决步骤
1. 服务端绑定地址修正
服务端初始绑定localhost时,仅能接收来自本机的连接,必须改为绑定0.0.0.0,让服务监听所有可用网络接口:
HOST = "0.0.0.0" # 替换原来的"localhost"
2. 防火墙端口放行
跨机器连接失败最常见原因是防火墙拦截了50051端口,执行以下命令放行:
- Linux(ufw防火墙):
sudo ufw allow 50051/tcp sudo ufw reload - Linux(iptables):
sudo iptables -A INPUT -p tcp --dport 50051 -j ACCEPT sudo service iptables save - Windows:
在“Windows Defender防火墙”中添加入站规则,允许TCP 50051端口的连接。
3. WSL环境特殊处理
如果服务端运行在WSL中,需要注意:
- WSL2的网络是NAT模式,默认无法直接被局域网其他机器访问,需要做端口转发:
- 查看WSL2的内部IP:
hostname -I - 在Windows命令提示符(管理员权限)中执行端口转发:
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=50051 connectaddress=<WSL内部IP> connectport=50051 - 同时放行Windows防火墙的50051端口。
- 查看WSL2的内部IP:
- 若使用WSL1,网络与Windows共享,只需确保Windows防火墙放行端口即可。
4. 网络连通性测试
在客户端机器上先测试基础网络连通性,排除路由问题:
- ping服务端机器的局域网IP:
ping 192.168.100.9 - 用telnet或nc测试端口是否开放:
telnet 192.168.100.9 50051 # 或 nc -zv 192.168.100.9 50051
如果ping不通,检查两台机器是否在同一局域网,是否有路由器隔离;如果端口不通,回到防火墙和端口转发步骤排查。
5. 客户端地址确认
确保客户端代码中的HOST是服务端机器的正确局域网IP,避免IP地址错误(比如服务端切换WiFi/以太网后IP变化)。
内容的提问来源于stack exchange,提问作者Caio m. silva
相关产品推荐
相关产品推荐

