写给Go开发者的gRPC教程-服务发现与负载均衡

对于一个客户端创建请求的过程,gRPC官方提供了基本的服务发现和负载均衡逻辑,并提供了接口供扩展用于开发自定义的服务发现与负载均衡,用通俗易懂的方式来解释下什么是服务发现。通常情况下客户端需要知道服务端的IP+端口号才能建立连接,但服务端的IP和端口号并不是那么容易记忆。还有更重要的,在云部署的环境中,服务端的IP和端口可能随时会发生变化。,所以我们可以给某一个服务起一个名字,客户端通过名字创建与服务端的连接,客户端底层使用服务发现系统,解析这个名字来获取真正的IP和端口,并在服务端的IP和端口发生变化时,重新建立连接。这样的系统通常也会被叫做name-system(名字服务),gRPC 中的默认name-system是 DNS,同时在客户端以插件形式提供了自定义name-system的机制。,gRPC采用的名字格式遵循的RFC 3986中定义的URI语法,例如,URI示例URI示例,gRPC关注其中两部分,大部分gRPC实现默认支持以下的URI schemes,如果gRPC服务端的地址是静态的,可以在客户端服务发现时直接解析为静态的地址,如果gRPC服务端的地址是动态的,可以有两种选择,关于服务注册这里不在做更多介绍了,自定义服务发现需要在客户端启动前,注册一个服务解析器(Resolve),Golang中使用google.golang.org/grpc/resolver.Register(resolver.Builder)注册,这个函数不是直接接收一个解析器,而是使用工厂模式接收一个解析器的构造器, Scheme()需要返回的就是名字格式中提到的URI scheme, Build(…)需要返回一个服务发现解析器google.golang.org/grpc/resolver.Resolver,cc ClientConn代表客户端与服务端的连接,其拥有的cc.UpdateState(State) error可以让我们更新链接的状态,解析器需要有能力从注册中心获取解析结果,并更新客户端中连接(cc ClientConn)的信息。还可以持续watch一个名字的解析结果,实时的更新客户端中连接的信息, 在 init() 阶段时, 客户端启动时通过自定义Dail()方法构造grpc.ClientConn单例,name-reslover原理name-reslover原理,同样来通俗易懂的解释下什么负载均衡。为了提高系统的负载能力和稳定性,我们的服务端往往具有多台服务器,负载均衡的目的就是希望请求能分散到不同的服务器,从服务器列表中选择一台服务器的算法就是负载均衡的策略,常见的轮循、加权轮询等,负载均衡器要在多台服务器之间选择,所以通常情况下负载均衡器是具备服务发现的能力的,根据负载均衡实现所在的位置不同,通常可分为以下三种解决方案:,在客户端和服务端之间有一个独立的LB,通常是专门的硬件设备如 F5,或者基于软件如 LVS,HAproxy,Nginx等实现。LB使用负载均衡策略将请求转发到目标服务,因为所有服务调用流量都经过LB,当服务数量和调用量大的时候,LB容易成为瓶颈;一旦LB发生故障影响整个系统;客户端、服务端之间增加了一级,有一定性能开销,图片集中式负载均衡,客户端负载将LB的功能集成到客户端进程里,然后使用负载均衡策略选择一个目标服务地址,向目标服务发起请求。LB能力被分散到每一个服务消费者的进程内部,同时服务消费方和服务提供方之间是直接调用,没有额外开销,性能比较好。,但如果有多种不同的语言栈,就要配合开发多种不同的客户端,有一定的研发和维护成本;后续如果要对客户库进行升级,势必要求服务调用方修改代码并重新发布,升级较复杂。,图片客户端负载均衡,将LB从进程内移出来,变成主机上的一个独立进程。主机上的一个或者多个服务要访问目标服务时,他们都通过同一主机上的独立LB进程做负载均衡,此方案有两种模式,第一种是直接由LB进行转发请求,被称为sidecar方案,第二种是从LB获取到IP后依旧由客户端发起请求,gRPC曾经支持过此方案叫lookaside方案,目前已废弃,该方案也是一种分布式方案没有单点问题,一个LB进程挂了只影响该主机上的客户端;客户端和LB之间是本地调用调用性能好;同时该方案还简化了客户端,不需要为不同语言开发客户库,LB的升级不需要服务调用方改代码。该方案主要问题:部署较复杂,环节多,出错调试排查问题不方便,独立负载均衡进程独立负载均衡进程,
,上文介绍的三种负载均衡方式,集中式负载均衡和gRPC无关,属于外部的基础设施,因此我们不再介绍,gRPC中的负载平衡是以每次调用为基础,而不是以每个连接为基础。换句话说,即使所有的请求都来自一个客户端,它仍能在所有的服务器上实现负载平衡,gRPC目前内置四种策略, pick_first:默认策略,选择第一个, round_robin:轮询,使用默认的负载均衡器很简单,只需要在建立连接的时候指定负载均衡策略即可。,️ 注意,旧版本gRPC使用 grpc.WithBalancerName(“round_robin”),已经被废弃,使用grpc.WithDefaultServiceConfig。,grpc.WithDefaultServiceConfig可以被上文服务发现中提到的cc.UpdateState(State) error覆盖配置, grpclb:已废弃,它属于上文介绍的负载均衡中独立负载均衡进程第二种。不必直接在客户端中添加新的LB策略,而只实现诸如round-robin之类的简单算法,任何更复杂的算法都将由lookaside负载平衡器提供,gRPC的grpclb方案gRPC的grpclb方案, xDS,如果接触过servicemesh那么对xDS并不会陌生,xDS 本身是Envoy中的概念,现在已经发展为用于配置各种数据平面软件的标准,最新版本的gRPC已经支持xDS。不同于单纯的负载均衡策略,xDS在gRPC包含了服务发现和负载均衡的概念,这里简单的理解下xDS,本质上xDS就是一个标准的协议,它规定了xDS客户端和xDS服务端的交互流程,即API调用的顺序,我们在xDS 服务端实现服务发现,配置负载均衡策略等等,支持xDS的客户端连接到xDS 服务端并通过xDS api来获取各种需要的数据和配置,xDS主要应用于servicemesh中,在mesh中由sidecar连接到xDS server进行数据交互,同时由sidecar来控制流量的分发。也就是上文提到的独立负载均衡进程的第一种模式,servicemesh的负载均衡servicemesh的负载均衡,gRPC使用xDS是一种无proxy的客户端负载均衡方案。对比Mesh方案,性能更好。我们把servicemesh的负载均衡和grpc的xds负载均衡放在一起感受下区别,gRPC的xDS的方案, 这意味着,grpclb废弃后,gRPC内置的pick_first、round_robin、xDS三种模式都属于客户端的负载均衡模式。pick_first、round_robin是单纯的负载均衡策略;xDS包含了服务发现等一系列能力,并且还在不断拓展中,而我们控制gRPC的行为也被转移到了xDS server上了。,xDS内容较多,又比较新,单独开个章节介绍下xDS的使用,gRPC xDS架构中出现了三个服务,我们可以使用 Envoy go-control-plane库来实现xDS server,这部分的开发类似于servicemesh,就不介绍太多了,如果位于k8s平台内可以参考下istio中控制面的实现,gRPC server需要自注册或者托管到k8s平台,如果托管到k8s则可以继续参考istio中控制面的实现,因为xDS也包含了服务发现的部分,因此对于client来说第一步需要先开发自定义的服务发现和负载均衡配置。幸运的是gRPC官方已经为我们开发了对应实现,只需要引入包即可,在init阶段会注册xDS的解析器和负载均衡器,随后只需要把gRPC client连接到xDs server即可,这部分与非xDS并无不同。只是目标服务的地址的URI scheme为xds,完整代码可以参考:https://github.com/grpc/grpc-go/tree/master/examples/features/xds,自定义负载均衡器需要使用google.golang.org/grpc/balancer.Register提前注册,此函数和服务发现一样接受工厂函数, Name()是负载均衡策略的名字, Build(…)需要返回负载均衡器, cc ClientConn代表客户端与服务端的连接,其拥有一系列函数可以让我们更新链接的状态,负载均衡器需要实现一系列的函数用于gRPC在不同场景下调用,类RR算法负载均衡器,如果要实现一个类round_robin的负载均衡策略,gRPC官方实现提供了一个baseBuilder,它已经实现了大部Balancer接口,可以大幅简化了我们创建RR策略的逻辑。使用google.golang.org/grpc/balancer/base.NewBalancerBuilder创建负载均衡的工厂,于是借助base.NewBalancerBuilder我们仅需要实现Picker一个函数即可实现类RR的负载均衡策略了,利用Picker接口来实现一个随机选择策略,[1]URI语法: https://zh.wikipedia.org/wiki/%E7%BB%9F%E4%B8%80%E8%B5%84%E6%BA%90%E6%A0%87%E5%BF%97%E7%AC%A6,[2]go-control-plane: https://github.com/envoyproxy/go-control-plane,[3]gRPC Name Resolution: https://github.com/grpc/grpc/blob/master/doc/naming.md,[4]Load Balancing in gRPC: https://github.com/grpc/grpc/blob/master/doc/load-balancing.md,[5]https://github.com/grpc/grpc-go: https://github.com/grpc/grpc-go,[6]gRPC Go 服务发现与负载均衡: https://blog.cong.moe/post/2021-03-06-grpc-go-discovery-lb/,[7][转]gRPC服务发现&负载均衡: https://colobu.com/2017/03/25/grpc-naming-and-load-balance/,[8]浅淡 xDS 协议在 gRPC 中的应用: http://limeng.org/2020/03/08/xds-in-grpc.html

文章版权声明

 1 原创文章作者:cmcc,如若转载,请注明出处: https://www.52hwl.com/28345.html

 2 温馨提示:软件侵权请联系469472785#qq.com(三天内删除相关链接)资源失效请留言反馈

 3 下载提示:如遇蓝奏云无法访问,请修改lanzous(把s修改成x)

 免责声明:本站为个人博客,所有软件信息均来自网络 修改版软件,加群广告提示为修改者自留,非本站信息,注意鉴别

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023年6月23日
下一篇 2023年7月15日