在第一部分,我们学习了gRPC的基本调用过程,这样我们对全局层面有了一定了解。接下来,我们将结合官方文档,继续深入学习、探索下去。
示例很简单,客户端和服务端都大致分为两步:
creds
DialOption
传入信息认证方法的底层实现并不在我们今天的讨论范围内。这里值得一提的是,由于请求会存在大量的输入参数,这里提供的方法是 opts ...DialOption
,也就是可变长度的参数,这一点很值得我们思考和学习。
第一步:将认证信息放入连接中
grpc.WithTransportCredentials
中,将creds
保存到copts.TransportCredentials
Dial
,在内部用 opt.apply(&cc.dopts)
将认证信息传递到结构中credsClone = creds.Clone()
使用了一份复制,放到了Balancer中,估计是用于负载均衡的,暂时不用考虑第二步:将认证信息请求中发出
Invoke
函数,这里是发送请求的入口(对这一块有疑问的,查看上一篇)invoke
,调用了newClientStream
,一大段代码都没有用到copts.TransportCredentials
中的参数,大致猜测是在clientStream
中copts.TransportCredentials
很麻烦,建议第一次可以先通过反向查找,调用到这个参数的地方newHTTP2Client
=> NewClientTransport
=> createTransport
=> tryAllAddrs
=> resetTransport
=> connect
=> getReadyTransport
=>pick
=> getTransport
=>newAttemptLocked
=> newAttemptLocked
=> newClientStream
Transport
的,那下次正向查找时,会有一条比较明确的方向了第一步:将认证信息放入Server结构中
creds
包装成ServerOption
,传入NewServer
中opts.creds
里第二步:在连接中进行认证
handleRawConn
useTransportAuthenticator
creds
实现的ServerHandshake
实现了认证。到这里,认证已经完成,不过我们可以再看看,认证信息是怎么传递的newHTTP2Transport
,保存到结构体http2Server
中的authInfo
,最后返回了一个Interface ServerTransport
serveStreams
,然后调用了 http2Server
的HandleStreams
方法,这时,我们大致可以猜测,auth在这里被用到了operateHeaders
,在这里被赋值到 pr.AuthInfo
里,并被保存到s的Context中peer.FromContext
,然而并没有地方应用,那认证的分析,就告一段落了这一块我们暂不深入源码,先了解使用时的特性
代码逻辑很直观,即处理后返回
代码的关键在于两个函数inRange
和 stream.Send
用一个for循环进行多次发送,stream.Recv()
实现了从服务端获取数据,当EOF时,才调用stream.SendAndClose
结束发送
将 SendAndClose
变为 Send
,其余基本不变。从这里可以看到,正常的关闭都是由服务端发起的。
原文:https://www.cnblogs.com/cx2016/p/13817094.html