那么,你要如何屏蔽服务化架构中服务治理的细节,或者说,如何让服务治理的策略在多语言之间复用呢?
有没有考虑过这个问题?我们实现的一整套服务治理的组件 熔断、限流、认证、负载均衡器、分布式日志追踪怎么来平滑的使用到跨语言的应用中呢?
可以考虑将服务治理的细节,从 RPC 客户端中拆分出来,形成一个代理层单独部署。这个代理层可以使用单一的语言实现,所有的流量都经过代理层来使用其中的服务治理策略。这是一种“关注点分离”的实现方式,也是 Service Mesh 的核心思想。
Service Mesh 是如何工作的
1. 什么是 Service Mesh
Service Mesh 主要处理服务之间的通信,它的主要实现形式就是在应用程序同主机上部署一个代理程序。一般来讲,我们将这个代理程序称为“Sidecar(边车)”,服务之间的通信也从之前的客户端和服务端直连,变成了下面这种形式:

在这种形式下,RPC 客户端将数据包先发送给与自身同主机部署的 Sidecar,在 Sidecar 中经过服务发现、负载均衡、服务路由、流量控制之后,再将数据发往指定服务节点的 Sidecar,在服务节点的 Sidecar 中,经过记录访问日志、记录分布式追踪日志、限流之后,再将数据发送给 RPC 服务端。
这种方式可以把业务代码和服务治理的策略隔离开,将服务治理策略下沉,让它成为独立的基础模块。这样一来,不仅可以实现跨语言服务治理策略的复用,还能对这些 Sidecar 做统一的管理。
目前,业界提及最多的 Service Mesh 方案当属Istio, 它的玩法是这样的:

它将组件分为数据平面和控制平面,数据平面就是我提到的 Sidecar(Istio 使用Envoy作为 Sidecar 的实现)。控制平面主要负责服务治理策略的执行,在 Istio 中,主要分为 Mixer、Pilot 和 Istio-auth 三部分。
你可以先不了解每一部分的作用,只知道它们共同构成了服务治理体系就可以了。
然而,在 Istio 中,每次请求都需要经过控制平面,也就是说,每次请求都需要跨网络地调用 Mixer,这会极大地影响性能。因此,国内大厂开源出来的 Service Mesh 方案中,一般只借鉴 Istio 的数据平面和控制平面的思路,然后将服务治理策略做到了 Sidecar 中,控制平面只负责策略的下发,这样就不需要每次请求都经过控制平面,性能上会改善很多。
-
如何将流量转发到 Sidecar 中
Iptables 方式的优势在于对业务完全透明,业务甚至不知道有 Sidecar 存在,这样会减少业务接入的时间。不过它也有缺陷,那就是它是在高并发下,性能上会有损耗,因此国内大厂采用了另外一种方式:轻量级客户端。
请求被发送到服务端的 Sidecar 上后,然后在服务端记录访问日志和分布式追踪日志,再把请求转发到真正的服务节点上。当然,服务节点在启动时,会委托服务端 Sidecar 向注册中心注册节点,Sidecar 也就知道了真正服务节点部署的端口是多少。整个请求过程如图所示:

与此同时,我也建议你了解目前业界一些开源的 Service Mesh 框架,这样在选择方案时可以多一些选择。目前在开源领域比较成熟的 Service Mesh 框架有下面几个,你可以通过阅读它们的文档来深入了解,作为本节课的引申阅读。
Istio 这个框架在业界最为著名,它提出了数据平面和控制平面的概念,是 Service Mesh 的先驱,缺陷就是刚才提到的 Mixer 的性能问题。
Linkerd 是第一代的 Service Mesh,使用 Scala 语言编写,其劣势就是内存的占用。
SOFAMesh 是蚂蚁金服开源的 Service Mesh 组件,在蚂蚁金服已经有大规模落地的经验。
网友评论