为什么要应用 gRPC?
在云原生的背景下,微服务大行其道。拆分的服务越来越细粒度,绝对于之前的单体架构设计,服务之间通信的品质成为影响整体服务质量的一个重要环节。
此外当初的研发体系,很少只存在一种语言,往往是多语言。此时,解决多语言交互也是一个必须解决的问题。
gRPC (gRPC Remote Procedure Calls) 是 Google 发动的一个开源近程过程调用 (Remote procedure call) 零碎。该零碎基于 HTTP/2 协定传输,应用 Protocol Buffers 作为接口描述语言。
其余性能:
- 认证(authentication)
- 双向流(bidirectional streaming)
- 流控制(flow control)
- 超时(timeouts)
最常见的利用场景是:
- 微服务框架下,多种语言服务之间的高效交互。
- 将手机服务、浏览器连贯至后盾
- 产生高效的客户端库
然而运行 gRPC 服务也带给咱们一些挑战,大多数是因为 HTTP/2 复用链接。
gRPC 带来的挑战
gRPC 只是一个 RPC 通信框架,并不是一个服务治理框架。尤其在云原生的环境下,比方 kubernetes 中,因为资源缓和被驱赶,或是弹性伸缩等起因,客户端如何能及时感知到新增的 server,以及剔除掉销毁的资源实例是一个挑战。因为 HTTP/2 复用链接,如何解决负载平衡的问题也是另外一个挑战。
gRPC 的负载平衡能够分为客户端负载平衡和代理负载平衡。
上面咱们讲下咱们理论应用过程中一些计划。
解决方案 1: 基于 envoy 的 ingress controller
该计划又可称为边缘 ingress。因为数据层 envoy 通过 daemonset 的形式部署到集群中,这样相当于每个 node 节点上部署了一个代理。边缘部署的形式,满足了高可用的要求。
如果 A 服务须要拜访 B 服务,那么创立 B 服务的 ingress,拜访域名为 http://b.service.com。
这种计划相当于代理的形式解决负载平衡。服务注册和发现利用了 k8s 原生的服务发现能力。
该计划的毛病是,一个 envoy 要解决 node 节点上所有的流量,可能会因为某个服务的流量问题,影响了其余的服务。
解决方案 2: gRPC client
拜访方须要集成对应语言的 gRPC client。
利用了 client 的客户端负载平衡的能力。不过这种计划,须要可能获取到 B 服务可用的 server 列表。
如何实现服务注册和发现那?
咱们能够为 B 服务,创立一个 Headless service,而后拜访 b.default.cluster.local,coredns 会返回可用的 Pod 列表。
此时,将 b.default.cluster.local 配置到 gRPC client,客户端主动会通过 dns,返回可用列表,用于客户端负载平衡。
该计划毛病是客户端引入了 sdk,减少服务的复杂性。
解决方案 3: 将 envoy 以 Sidecar 的模式部署
将 envoy 以 Sidercar 的模式部署,联合了前两种计划的劣势,客户端代码不必引入非业务逻辑的代码,每个 sidecar 只解决本 client 的流量逻辑。
论断
除了负载平衡和服务发现,咱们还须要实现优雅退出,因为不论是 dns 服务发现,还是 k8s 原生服务发现,均有肯定的提早。
此时咱们能够简略利用 Pod 生命周期的 pre-stop 钩子。
解决方案 1 和解决方案 3,除了解决了负载平衡的问题,还能通过 envoy 裸露进去的 metrics 和 access log,减少了服务的可察看性。
当然最终的解决方案,是一个残缺的 service mesh 计划。**