grpc的dial正常执行流程

来源:互联网 发布:青岛淘宝供应商 编辑:程序博客网 时间:2024/04/28 17:16

请先阅读  grpc源码注解(golang)

以下基于默认配置情况下(还有其它没有提到的配置都取默认值):

  1. 设置了balancer(etcd等)
  2. 没有设置WithBlock,即dialOptions.block = false
  3. 没有设置FailOnNonTempDialError,即dialOptions.copts.FailOnNonTempDialError = false

grpc.Dial 正常的执行流程,第一次进入的时候的有些逻辑是走不到或者不太重要的都舍去不表

A. grpc.Dial()  返回一个*ClientConn

  1. 从balancer(etcd等)返回一批地址,但是这批地址暂时还是不能用的,需要等待A225

  2. A2,对于每一个地址依次建立连接,循环调用cc.resetAddrConn, 即
  3. A3,单独goroutine监控balancer(etcd等)的变化(cc.lbWatcher())实时更新服务集群地址,即
  4. 单独goroutine监控监控ServiceConfig的变化(cc.scWatcher),可以在服务启动后动态更新调用服务的配置

A2cc.resetAddrConn针对一个地址建立连接,创建一个addrConn加入到ClientConn.conns中去,主流程分为:

  1.  如果这个地址已经存在连接了,先关闭掉ac.teardown
  2. A22,ac.resetTransport,建立一个底层连接(http2),这一步默认是goroutine出去的,不会阻塞,除非调用WithBlock;
  3. A23,单独goroutine监控底层连接的状态变化(ac.transportMonitor),进行重连或者放弃

A22, ac.resetTransport里面是一个大循环,重试建立连接直到成功,除非某些条件下返回(默认情况下只有被ac.teardown了,即在balance中删除),每个循环里面:

  1. 如果ac.state == Shutdown ,直接返回
  2. 将状态改为正在连接中~~  ac.state == Connecting

  3. 计算sleepTime,这里是根据重试的超时策略,返回两次重试的间隔时间;即如果这次重连还是失败,会等待sleepTime才会进入下一次循环
  4. A224,建立一个底层的http2连接(transport.NewClientTransport);如果是临时错误, 将状态改为短暂的失败,ac.state = TransientFailure,等待sleepTime;如果是非临时错误,直接返回,默认情况下可以认为都是临时错误;
  5. 将状态改为readyac.state = Ready ,通知balancer(etcd等)这个地址连接ok了(up);这样下次就能从balancer 中读取到这个地址了

A224, 建立一个底层的http2连接(newHTTP2Client)

  1. dial一个tcp连接,失败的话,默认返回一个临时错误
  2. 单独goroutine,循环的读取所有的帧,并且分发到相应的流中去,如果有错误了,会有通知到A233
  3. 初始化http2 相关的操作(发送setting帧等)

A23,transportMonitor 是一个单独的goroutine,里面是一个循环,会监控这个连接以下几种情况:

  1. 如果这个连接被ac.teardown了,直接退出,不需要维护了
  2. 如果收到http2的goaway帧,再重新cc.resetAddrConn,即A2,然后当前直接退出;相当于用一个新的连接来替换
  3. 如果这个连接出错了,置为临时失败ac.state = TransientFailure ,暂时不让用,然后重试连接ac.resetTransport,即A22

A3,cc.lbWatcher监控balancer(etcd等)的变化 , 实时更新集群服务地址

  1.  balancer.Notify() 是一个channel,每当有更新的时候,从这里读取到所有的地址(全量而非增量)
  2. 判断有哪些地址是新增的,哪些地址是删除掉的

  3. 对于新增的地址执行cc.resetAddrConn,即A2

  4. 对于删掉的地址直接ac.tearDown,通知balancer(etcd等)这个地址down了, 这样可能会影响到A231A221

 

对于ac.tearDown,里面会关闭底层的连接,修改状态为ac.state == Shutdown,然后通知balancer(etcd等)这个地址down了,在下次轮询的时候,就不会有这个地址了;

如果这个balancer(etcd等)收到这个地址的UP的通知,表示这个地址又OK了

 

0 0