gRPC-go源码(1):连接管理 (2)

gRPC提供的是插件式的Resolver功能,他会根据用户传入的aaa:///bbb-project/ccc-srv,选择一个能够解析aaa的Resolver,并进行解析,得到ip:port列表。

3.3 Balancer

Balancer称为负载均衡器,负责在Resolver解析出的一串地址中,选择其中的一个建立连接。

至于如何选择,也是由用户自己编写LB的逻辑。

也就是说,gRPC实现了基础的逻辑,但是也提供了很强大的插件式编程的能力,将很多操作都留给开发人员自己去做选择。

不过,很大的灵活度对应的是很复杂的代码结构,直接去看源码可能会让人摸不着头脑。所以在这一篇的文章中我们先来介绍整体的一个设计逻辑,在下一篇文章中我们再来聊具体的细节。

3.4 Wrapper

我们在上面聊到,gRPC的Resolver和Balancer都是支持自定义的。我们可以自己定义各种不同的Resolver和Balancer,来应对不同场景的需求。

这么做虽然增加了代码复杂度,但是却能够让gRPC变得更灵活,能够对各种复杂情景提供支持。

那么,要怎么才能够实现插件式的编程呢?

答案是使用装饰器模式

装饰模式(Decorator)也叫包装器模式(Wrapper)。GOF在《设计模式》一书中给出的定义为:动态地给一个对象添加一些额外的职责

装饰器模式是指动态地给一个对象添加一些额外的职责,就增加功能来说装饰模式比生成子类更为灵活。它通过创建一个包装对象,也就是装饰来包裹真实的对象。

这么说可能有点抽象,我们直接上图:

首先创建一个resolver接口,并设计一些具体的resolver实现类:

gRPC-go源码(1):连接管理

然后我们还需要一个resolver的包装器,里面包含了真正的resolver。

当我们的gRPC需要调用ResolverNow方法的时候,他只需要调用resolverWrapper中的Resolve()方法,在这个方法中来调用真正的resoleNow()逻辑:

gRPC-go源码(1):连接管理

只要理解了这个设计模式,gRPC Client端建立连接的代码,你就能看懂一大半了。

至此,gRPC对连接的管理就结束了。

4 总结

最后我们再梳理一遍gRPC是如何管理连接的。

在第一次建立连接时,gRPC会调用服务端地址相对应的Resolver,来解析出所有能够提供服务的服务端地址。随后,经过指定的Balancer,选择其中的一个地址,建立连接。

如果是已经建立过连接,在Resolver中存在一个协程,监听了服务的状态,当存在新上线或下线的服务,会重新进行地址解析,来获取新的服务端地址集合,随后通过Balancer来选择一个地址,建立连接。

在这篇文章的铺垫下,阅读具体的实现代码可能就会比较容易了。对于这部分的代码,我们会在下一篇文章中进行分析。

而对于连接的建立,逻辑也比较复杂,我们在后面的文章中继续分析。

写在最后

首先,谢谢你能看到这里!

这篇文章带有了比较强的主观判断,因为作者才疏学浅,对于gRPC的设计思路可能存在了误会。如果你觉得有哪里是我说的不对的,还请不吝赐教,谢谢你!

在下一篇文章中,我也会尽可能的把代码也梳理的比较简单一些,敬请期待。

最后,如果有任何问题,都可以留言或者在公众号“红鸡菌”中找到我。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpyzwg.html