• 解决grpc连接问题Dial成功但状态变为TransientFailure


    如有帮助,欢迎留下足迹哦!

    详情如下


    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;
        
      这两状态是什么意思呢?看下源码:

    1.     const (
    2.     // Idle indicates the ClientConn is idle. Idle 表示 ClientConn 处于空闲状态。
    3.     Idle State = iota
    4.     // Connecting indicates the ClientConn is connecting.  Connecting 表示 ClientConn 正在连接。
    5.     Connecting
    6.     // Ready indicates the ClientConn is ready for work. Ready 表示 ClientConn 已准备好工作。
    7.     Ready
    8.     // TransientFailure indicates the ClientConn has seen a failure but expects to recover.  TransientFailure 表示 ClientConn 已经看到失败但希望恢复。
    9.     TransientFailure
    10.     // Shutdown indicates the ClientConn has started shutting down.  Shutdown 表示 ClientConn 已经开始关闭。
    11.     Shutdown
    12. )


    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))

    以下几种写法均可:

    1. net.Listen("tcp", fmt.Sprintf(":%s", 9001))
    2. net.Listen("tcp", fmt.Sprintf("%s:%s", "本机IP", 9001))
    3. net.Listen("tcp", fmt.Sprintf("%s:%s", "0.0.0.0", 9001))


    皆可成功!

    其中第一、三个启动后打印出来的服务地址是[::]:9001
    第二种是192.168.31.33: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为妥。

  • 相关阅读:
    Java学习----习题总结
    VMware网络设置 桥接模式 NAT VMNET0 1 8
    GPT引发智能AI时代潮流
    Python二级题:MOOC学校名单|关键词提取和查找
    IO模型原理
    NLP Bi-Encoder和Re-ranker
    分析负数取模与取余的规则
    面试算法55:二叉搜索树迭代器
    web前端期末大作业——基于Bootstrap响应式汽车经销商4S店官网21页
    Vue中的路由嵌套
  • 原文地址:https://blog.csdn.net/HYZX_9987/article/details/125615197