请先阅读 grpc的dial正常执行流程和 grpc服务异常情况的执行流程
默认配置情况下(还有其它没有提到的配置都取默认值):
- 设置了balancer(etcd等)
- 没有设置WithBlock,即dialOptions.block = false
- 没有设置FailOnNonTempDialError,即dialOptions.copts.FailOnNonTempDialError = false
调用grpc.Dial之后,这时client和服务端的连接已经建立起来了
这个时候我们发起一次请求,即调用protobuf生成的*.pb.go文件里面的对应方法,本质上还是调用的grpc.Invoke
B. Invoke发起一起请求:
- 先调用拦截器unaryInt,
- 然后在1里面调用invoke处理真正的一次请求过程
B2. invoke里面是一次请求过程,主要分为:
- 先cc.getTransport,获取一个连接,出错后默认直接返回
-
发送请求,sendRequest,生成一个stream对象
-
接受响应数据 recvResponse,里面是阻塞等待的,根据2中的stream.id 来区别这个响应是哪一个请求的
B21. cc.getTransport,获取一个连接
- 从balancer中获取一个地址(轮询),会优先选择正常的地址,如果都不ok了,则返回上回用的地址,不保证这个地址一定是有效的
-
ac.wait()等待一个连接,默认情况下,这里是保证连接ok,如果不ok会返回错误
代码中有大量逻辑对于两种错误进行了特殊处理,这里说明一下
// errConnClosing indicates that the connection is closing. // 这个表示连接被关闭了,一般是balancer中去掉之后,被teardown了 errConnClosing = errors.New("grpc: the connection is closing") // errConnUnavailable indicates that the connection is unavailable. //这个表示连接是无效的,一般是服务有问题,但是没有从balancer中去掉,这个时候会一直重试连接 errConnUnavailable = errors.New("grpc: the connection is unavailable")