如有帮助,欢迎留下足迹哦!
详情如下
code = Unavailable desc = connection error: desc = "transport: Error while dialing dial tcp 192.168.31.33:9001:
connectex: No connection could be made because the target machine actively refused it."
此时连接状态为 TransientFailure
目录
背景
现象汇总
分析与解决
总结与附录
GRPC客户端与服务端建立连接时我们都知道需要先Dial,报该错时实际上Dial操作是成功的,此时err为nil,但调用rpc接口时失败,报了该错。
1, 将客户端与服务端均放在本机,且地址写本机地址时也报改错,Dial成功,调用rpc接口失败;
Dial成功时的连接状态为Connecting,调用rpc接口失败前的连接状态变为TransientFailure;
这两状态是什么意思呢?看下源码:
const (
// Idle indicates the ClientConn is idle. Idle 表示 ClientConn 处于空闲状态。
Idle State = iota
// Connecting indicates the ClientConn is connecting. Connecting 表示 ClientConn 正在连接。
Connecting
// Ready indicates the ClientConn is ready for work. Ready 表示 ClientConn 已准备好工作。
Ready
// TransientFailure indicates the ClientConn has seen a failure but expects to recover. TransientFailure 表示 ClientConn 已经看到失败但希望恢复。
TransientFailure
// Shutdown indicates the ClientConn has started shutting down. Shutdown 表示 ClientConn 已经开始关闭。
Shutdown
)
2, 将客户端与服务端均放在本机,且地址写127.0.0.1时成功,调用rpc接口也成功,一切正常;
3,将客户端与服务端均放在不同主机,且启动服务地址写127.0.0.1、客户端连接地址写服务端ip时失败也报改错,Dial成功,调用rpc接口失败;
不禁让人纳闷,到底是哪的问题?
以上现象出现时,服务端所在主机已开放了端口号为9001的tcp端口,因此排除端口开放问题;
另外,客户端与服务端均在本机时可成功,而在不同主机不成功,就说明了大概率还是网络不通方面的问题;
与此同时进行抓包,发现有从客户端流向服务端主机的包且端口正确,但来回都是R.和S的标记交替着,服务端给客户端一直回复R. 表明连接异常一直在被重置,同时这样的回复实际也和服务端未启动服务时的情形一致;
根据以上现象,基本确定是客户端没有识别到服务端的启动(实际上服务端启动着)
最终一步步摸排得知,启动服务时监听地址写的是:
net.Listen("tcp", fmt.Sprintf("%s:%s", "127.0.0.1", 9001))
以下几种写法均正常:
net.Listen("tcp", fmt.Sprintf(":%s", 9001))
net.Listen("tcp", fmt.Sprintf("%s:%s", "本机IP", 9001))
net.Listen("tcp", fmt.Sprintf("%s:%s", "0.0.0.0", 9001))
其中第一、三个启动后打印出来的服务地址是[::]:9001
第二种是 ip:9001
那么总结一下原因,实际上就是127.0.0.1启动时仅本机可连接成功,只作用在本机,因为它是本机回环地址,
正常的网络包从3层进入2层,然后发出去,而发向回环地址的包,直接在IP层短路了,也就是发到IP层时直接被IP层接收、不再向下发送;
也就是说对于本机单机测试时可以直接用127.0.0.1。
1、如果监听地址是127.0.0.1:port,表示仅监听环回接口的数据,即本机发送给本机port端口的数据,其他主机发送过来的数据无法接收到。
2、如果监听地址是0.0.0.0:port,表示监听所有网络接口的数据,包括回环接口和其他网络接口,所有本机和其他主机发送的数据都可以接收到。
3、如果监听地址是本机ip:port,表示仅监听本机ip对应的网络接口。仅接收目的地址是本机ip的数据。(对本机发送给本机这种情况,如果目的主机地址是127.0.0.1则,收不到,仅当目的主机地址是本机ip时能够收到)。
实际上0.0.0.0风险较大,建议使用本机IP为妥。