service mesh - 微服务通信进化之路

2021-02-22 17:11:03 浏览数 (1)

导语 | service mesh 致力于做微服务时代的 TCP,以 TCP 的方式解决微服务的通信问题。那么它解决的是微服务时代的什么问题?以及以何种方式解决这些问题呢?本文就来和大家一同探究这个话题,文章作者:吴芦峰,腾讯后台研发工程师。

一、什么是 service mesh

service mesh 致力于做微服务时代的 TCP,  它解决的是微服务架构时代的通信问题。管理和控制网络间通信问题,解放业务团队,提升整体研发效率。

1. 微服务时代的 TCP

TCP 是互联网的基石,首先来回顾下 TCP 对网络的作用,再来看看微服务时代下通信面临的问题以及 service mesh 该解决的问题,以及如何像 TCP 一样通用化的解决这些问题。从而成为作为微服务时代的 TCP。

(1)端到端时代的 TCP

互联网能发展至今,TCP 协议功不可没。它让计算机真正的能够互连互通。TCP 是提供了可靠的端到端的连接、数据传输方式。TCP  通过提供了握手协议、ACK 机制、超时重传、滑动窗口、拥塞控制算法、数据分片、数据校验等等,实现面向连接、可靠的端到端网络通信。

TCP 不仅解决了这些问题,它还成为所有应用程序互联的通用标准。互联网的应用几乎都使用 TCP 协议进行通信,可以说,没有 TCP 就没有今天的互联网。

TCP 协议由操作系统处理,绝大多数网络业务进程无需处理端到端通信,对网络协议的优化也无需更新各个应用程序的版本,只需要优化操作系统的协议即可,做到了标准化和解耦。极大的释放了应用程序的业务迭代能力,丰富的应用程序也进一步的促进了计算机操作系统进入千家万户。

(2)分布式微服务时代的 TCP ——  service mesh

在互联网迅速融入社会后,业务也越来越复杂。服务端需要处理的业务越来越多,几个大型服务器完全无法满足业务运营的需要, 业务开发团队也是动辄几百、上千人。后台的分布式架构、微服务架构开始流行,以适应复杂的业务,并围绕独立的业务构建团队。

随着业务的不断发展,微服务的数量越来越多,微服务间的通信网络也变得十分复杂,微服务间的通信拓扑可以构成一个复杂的网络。

在微服务架构中,一次请求往往经历了许多服务节点。在这个角度看,服务间通信已经不在是端到端的调用了,而是"多个节点访问多个节点"的关系了。在处理分布式微服务架构中"多个节点"的互相通信上,需要解决这些通用的问题:

  • 服务注册、服务发现;
  • 负载均衡;
  • 弹性能力(熔断、限流、降级、超时、重试等);
  • 安全(认证授权);
  • 可观测性(控制面板、拓扑图、链路追踪等)。

service mesh 要做微服务时代的 TCP,也就是在解决上述问题的基础上,还要做到通用化、标准化,解耦合业务进程与 mesh。让通信过程在微服务间变得简单、可靠。下图是 TCP 需要处理的问题以及 service mesh 需要处理的问题:

将这些能力与业务进程剥离,是 service mesh 和成为新一代 TCP 的理念。这样有利于通信过程的标准化、通用化,让业务开发无需关心通信过程,从而进一步解放业务的迭代效率。

2. 分布式微服务的通信发展史

service mesh 这个词汇在 2016 年出现。但是服务间通信的相关技术早在网格计算机系统时代就开始发展了。从计算机设备端到端通信的发展开始,经历过以下阶段:

  • 第一代网格计算机系统,应用程序的开发中需要处理网络通讯细节问题,如数据包顺序、流量控制等。这些处理网络的逻辑和业务逻辑混在一起。
  • 随之发展出了 TCP/IP 协议,处理网络的代码从应用程序中抽象出来,通用的协议成为操作系统的网络层的一部分,解放了应用程序的开发。
  • 微服务时代,随着应用程序功能的不断增加,新的微服务架构开始流行。第一代微服务架构中应用程序开发需要处理微服务面临的一些问题,包括负载均衡、熔断、重试等,对于微服务架构的应用开发人员有额外的要求。
  • 随着微服务架构的发展,Spring Cloud 、Dubbo 等微服务框架开始出现,框架层面处理了负载均衡、熔断、重试等,进一步的解放了应用程序的开发,以加快上层业务的迭代效率。Spring Cloud 等作为以类库方式存在的侵入式微服务框架,只是帮助业务程序减少了直接编写的冗余代码,但是依然需要框架与应用程序一起编译打包,功能与业务进程一同运行。Spring Cloud 等框架还是有如下缺点: 门槛高:由于框架组件多,对于业务开发人员,就需要掌握较多非业务的知识,增加了业务开发人员的挑战。 功能不全:框架所能提供的微服务治理功能是有限的,比如路由规则定义能力(Version Base Routing、Content Base Routing) 。 跨语言:跨语言是微服务的优势之一,它可以让不同语言编写的服务通过暴露接口服务调用的方式开放能力。而使用类库的微服务,将被类库支持的语言限制。 升级困难:框架也是需要不断的改进升级的,由于应用程序的编写使用的是框架,当框架升级更新时,就必须重新编译打包应用程序,按照发版流程升级所有使用框架的微服务。这样的流程将是十分复杂和耗时的。
  • Spring Cloud 等作为以类库方式存在的侵入式微服务框架,只是帮助业务程序减少了直接编写的冗余代码,但是依然需要框架与应用程序一起编译打包,功能与业务进程一同运行。Spring Cloud 等框架还是有如下缺点:
  • Proxy 模式。在微服务之前,为了避免客户端、服务端的耦合问题曾通过中间代理层如 Nginx、HAProxy、Apache 等反向代理完成转发功能,并由中间代理层实现负载均衡,从而解耦合服务端与客户端。Proxy 模式具备一些基础的微服务治理功能,同时它可以独立于应用服务,减少微服务治理与业务服务的耦合。
  • Sidecar 模式。Proxy 模式的功能较为简单,并不能完全代替侵入式的框架。sidecar 模式则在 Proxy 模式上进一步改进,它的实现往往是在 Proxy 的请求转发的基础上,利用框架类库进一步实现微服务框架具有的各种功能,如服务注册、熔断、重试等。sidecar 模式由于其解决的问题思路,一般是针对特定的基础架构设计的,它的通用性具有一些局限性。
  • 第一代 service mesh。2016 年 1 月,离开 twitter 的工程师William Morgan和 Oliver Gould 发布了 Linkerd ,成为第一个 Service Mesh 项目。2017 年 1 月来自 Lyft Envoy 诞生,它是业界第二个 service mesh 项目。service mesh 在 sidecar 的基础上,解决了通用性问题,不受限于原有的基础环境。在 Service Mesh 中,所有的请求都通过 Service Mesh 转发,不提供直连方式,它掌控所有的流量。
  • 第二代 service mesh。2017 年 5 月, Google、IBM、Lyft 联手发布了 Istio,它与第一代 Service Mesh 相比,增加了控制平面,它具备远超第一代的控制能力。通过集中式控制面板,加上所有流量均会通过 Service Mesh 转发,通过 Service Mesh 的控制面板,就可以控制所有整个系统。
(1)框架、库

以 Spring Cloud 、Dubbo 为代表的框架,与语言强相关相关,必须框架支持的语言,或提供各语言库函数,才可以进行微服务通信。它们需要和业务代码一起编译进入业务进程,在进行框架、库的更新时,将会十分痛苦,需要更新所有的相关业务服务。

(2)proxy 模式

在分布式服务器上,nginx 、HAProxy 等代理早就提供了终端访问服务器的负载均衡,它们同样也可以用于微服务间的通信,实现服务发现、负载均衡等相关功能。且 proxy 模式下,只需要接受网络报文即可,然后会将其转发到对应的服务上,与调用方、服务进程的编程语言无关,无需提供特定 API、SDK ,透明性更好。但传统的代理 nginx、HAProxy 等功能较简单,对于经常伸缩的微服务节点,使用也十分受到限制。

(3)sidecar

Proxy 模式的功能较为简单,并不能完全代替侵入式的框架。sidecar 模式则在 Proxy 模式上进一步改进,它的实现往往是在 Proxy 的请求转发的基础上,利用框架类库进一步实现微服务框架具有的各种功能,如服务注册、熔断、重试等。sidecar 模式由于其解决的问题思路,一般是针对特定的基础架构设计的,它的通用性具有一些局限性。但相比于传统的框架如 Spring Cloud,它是将对应的 SDK 运行于 sidecar 进程上,当对相关库进行更新时,只需要更新 sidecar 进程即可,不会影响到业务进程。

(4)service mesh

sidecar 模式的存在更多的是为了兼容已有的分布式系统,从而慢慢转向 service mesh 理念,将流量交给"微服务时代的 TCP"。service mesh 的通信流程大致如下:

可以看到,service mesh 相比于传统的 l5 以及当前的 polaris,业务服务调用流程上少了一步,只需要将请求转发给 service mesh 即可,它将直接转发到对应的业务服务。

在 service mesh 处理了这些请求、响应的转发之后,由于流量都经过 service mesh ,这就可以很方便的对这些流量进行统一管理,从而进一步提供限流、熔断、监控、全链路拓扑图生成等, 以及可以进一步针对 service mesh 层的流量进行分析处理,这些都将不需对应业务人员参与。就像 TCP 协议一样,统一处理了超时重传、可靠传输、流量控制、拥塞控制等,并可以不断的更新优化协议机制,而业务进程不需要再处理这些,不需要业务进程发版更新。业务进程只需构造 TCP 报文交给操作系统即可,端到端的优化则可以通过优化 TCP 处理。而 service mesh 也一样,对于分布式微服务之间的服务调用流量的进一步分析、管理功能的迭代,不需要更新业务服务、发版处理,解放业务开发人员,也解放微服务治理基础能力开发人员。

但目前 service mesh 也存在一定的问题,大规模的实践并不太多,腾讯内部的业务实践上也并不多。所有流量有 mesh 层统一处理,也带了了性能上的质疑, 不过这将被技术解决,它的优点和趋势是十分明显的。

(5)微服务通信治理

在微服务这样的分布式系统环境下,需要通过各种方式完成如下功能:

  • 服务注册: 节点启动后,对外注册提供服务,使得其它业务方可以调用节点的接口。
  • 服务发现: 当业务节点需要访问分布式的服务方时,可以通过服务发现功能获取目标节点的 IP,完成网络访问。
  • 负载均衡: 通过不同的负载均衡策略,可以将访问分发到分布式的各个节点上,增强服务方集群的容量。
  • 限流:  单体的节点的负载能力有限,限流可以保护服务方不至于流量过大,对节和集群加一层保护措施。
  • 熔断: 若服务方的响应时间过长或不可用调用过多,及时熔断的熔断可以提升整体的可用性。
  • 降级: 熔断后,业务方可以选择进行降级处理,进行不处理或简单处理,保证整体可用性。
  • 自动扩容: 根据访问量的增加,自动调整服务方集群节点数量,提高服务端的容量。
  • 自动故障隔离: 当系统内部组件出现故障后,故障隔离措施可以将故障范围控制在局部,防止故障范围扩大,增加对上层系统可用性带来的影响。
  • 自动业务恢复: 熔断、降级等处理后,可以及时根据系统情况恢复正常。
  • 监控: 对微服务、容器、机器、业务进行监控,了解系统的状况以便于进行相应调整。
  • 日志: 收集日志用于复盘分析。
  • 流量镜像等: 将线上的流量复制一份到特定的环境中,用于对访问内容进行分析。 service mesh 则在对流量透明转发的基础上,提供这些通用的能力。

3. 为什么需要 service mesh

kubernetes 技术将微服务的架构推向主流,让所有语言都可以以容器形式部署,提供微服务功能。而跨语言的微服务间通信将比 Spring Cloud 等语言相关的框架更加复杂,kubernetes 虽然提供了 service 代理层通信,提供了服务发现、服务注册、负载均衡的基础功能。但是认证授权、可观测性、链路追踪、熔断、降级、限流等业务发展不断庞大后都需要的微服务通信治理功能却依然不足。

若解决这些功能的代码开发工作放在业务工程内,编译进业务代码,那就不可避免的需要进行编译、发版甚至测试流程,对于通用能力的进一步迭代更新,比如流量分析,则需要更新发版所有业务进程。而且对于跨语言的微服务,通用的框架能力还需要提供多语言版本。而对于熔断、限流等的规则配置,则分散于不同的业务配置中,不利于统一管理。

这些通用的且业务相关性不大的微服务能力,能不能更加通用的进行维护、中台化?将所有的流量都交给 service mesh 这一透明代理层,对流量的管控不在需要业务进程处理,相应的微服务间访问的通用能力也交由 service mesh 层处理即可,包括认证授权、熔断、降级、限流、监控追踪等。对于流量的进一步分析、控制,也只要更新 service mesh 层,无需业务开发人员过多关注,交由相应的开发人员即可。比如利用 service mesh 层完成流量的灰度、管控特性分支、生成拓扑图、统计异常访问等,均可以做到业务进程无关。这样可以极大的解放业务开发人员。

二、腾讯服务间通信发展

1. L5 名字系统

L5 名字系统诞生较早,主要是在分布式架构下提供统一的服务发现、服务注册以及负载均衡功能,它诞生时,还没有 kubernetes,微服务还没有如今这样流行。它主要是在虚拟机时代通过 L5 Agent 进程协助业务进程进行服务注册与发现,从而让分布式系统能够向用户提供更好的服务端能力。L5 提供的名字系统能力主要流程如下图所示: 

L5 在流程上, 给业务进程提供的主要是服务发现、服务注册功能,让分布式的业务服务器能够找到指定服务的 IP,并通过 IP 的分发控制提供负载均衡功能。最终服务的调用是通过两个业务服务的 IP 进行访问的, 业务服务调用的网络报文不会经过 L5 Agent 及 L5 Server 。

这样,流量将直接由分布式的业务服务 A 与业务服务 B 直接建立连接。需要业务进程自行处理通信过程,涉及认证、请求、响应等。即使交给框架处理,跨语言的微服务间调用也需要跨语言的框架支持,而通用能力的更新,则需要更新业务进程发版处理,维护成本极高。并且,由于所有的流量是微服务间建立通信的,它们的调用链路也是不易于全局化的。

2. polaris 新一代名字系统

polaris 作为诞生在 kubernetes 分布式微服务架构广泛应用之后的云原生时代,在架构上首先兼容了老的 L5 名字服务,以兼容腾讯内部的老业务服务,同时提供了统一的微服务功能包括限流、熔断等能力。在未来规划上,也考虑了 sidecar、mesh 能力。在将公司内的所有老 L5 业务系统的能力兼容迁移到 polaris 上之后,相信后续的 mesh 能力的接入也可以更加平滑。

当前 polaris 的调用流程还是与 L5 类似,polaris server 将业务服务的 ip 返回,业务进程间建立连接。但是 polaris 提供了跨语言的统一 sdk,接入 polaris 的团队在后续的更新上,可以更加统一,若 polaris 支持 mesh 能力,老服务的迁移改造对业务的影响可能会更小。

L5/polaris/k8s service/service mesh 对比

L5、polaris、k8s service、service mesh 都提供了微服务之间的通信功能。以下是一些对比:

相比较而言,在后续的发展中, service mesh 在通信治理的功能上更易于扩展,能力将会更加强大,同时由于其透明代理的特性,与业务的耦合极低。在业务 service mesh 化后,业务进程只需通过传统的 tcp、http 进行通信即可,对于进一步的微服务的流量管控,都交给 service mesh 处理,而升级也将只影响 service mesh 代理层,业务进程可以无感知。

三、新一代微服务通信实战

第二代 service mesh 诞生在 kubernetes 之后,它的代表是 istio。下面将在腾讯 tke 平台上部署 istio 的 demo,让多个跨语言的服务进行通信。除了利用 kubernetes service 提供的服务发现、服务注册、负载均衡之外, istio 进一步通过流量的管控,生成了可视化的访问拓扑图,展示访问路径、访问的成功失败数。同时通过对 http header 中的 cookie 的分析,实现对特性分支的访问,以完成灰度功能。

目前腾讯内部的服务通信依然依赖于 L5,istio 目前并没有在腾讯大规模实战。polaris 作为新一代名字系统,虽然没有做到 mesh,但兼容了 L5,让 L5 业务无缝迁移到 polaris,并进一步实现了对微服务进行管控的功能,包括熔断、限流、访问统计等。同时,在 polaris 的规划上,也有 sidecar、mesh 的信息。兼容老的业务系统形式,也是 service mesh 应用上的一大问题。

1. 新一代 service mesh 之 tke istio 体验

(1)demo 部署

通过商城服务的 demo 演示,可以体验 istio 提供的流量管理功能。主要配置可以参考文档 Istio 服务 demo 演示【1】。

【1】:demo 地址

https://zhonghua.io/2019/06/26/tke-mesh-demo/?from=timeline&isappinstalled=0

demo 演示中提供的商城 demo 服务涉及数十个微服务,并包括 nodejs、go、java、python、ruby 等各种编程语言,如下所示:

这样的跨语言微服务之间的调用,若是基于框架完成微服务间的调用,则框架必须支持各个语言的版本,在更新框架时也必须更新各个语言版本,这给框架编写维护带来了极大的工作量。而框架的发展情况也将限制业务在功能上的开发。

基于商城微服务的 istio 部署,可以体验 istio 的在通用透明性、流量转发、流量控制、可观测性方面带来的优势功能。主要部署步骤如下:

  1. 选择支持 istio 功能的 tke 集群;
  2. 部署各个功能的 workload;
  3. 为每个 workload 建立 service ;
  4. 建立边缘代理网关作为流量入口,创建服务网关定义边缘代理网关的流量行为;
  5. 为 service 创建 destination rule 用于后续的分支版本控制;
  6. 创建 virtual rule 匹配到不同版本的后台服务,实现按条件进行的分支控制,将流量转到不同的微服务分支;
  7. 通过 virtual rule 基于流量控制实现权重路由和灰度发布。
(2)透明代理

istio 基于 k8s service 的透明代理可以让访问方对 service mesh 层是无感知的,客户端无需关心 service mesh 层处理的服务发现、服务注册、负载均衡等功能。只需将迭代工作放在业务上即可。demo 演示中,客户端直接通过 k8s service 提供的域名进行 基于 http 协议的访问,无需关系有多少服务方、服务方版本等问题。

(3)可观测性 - 拓扑图与访问统计

在页面上访问商城主页后,istio 通过流量的监控生成了网络拓扑图, 如下图所示:

istio 通过流量的管理,可以对访问的时间、成功失败率进行统计:

同时也可以精确的看出每个 pod 的具体访问数据,可以方便的看到用户的全局访问链路:

(4)流量级灰度控制

在开发测试过程中,不同需求开发在测试、发布阶段往往需要将特殊 pod 与基准服务 pod 进行联合调试,通过 virtual rule 和 destination rule 的配置规则,可以精确的将特性流量转到不同的微服务的指定特性 pod 上。通过 istio 可以快速构建下图所示的基准环境、分支特性环境的通信过程,适应业务的需要。

istio 支持配置根据流量内容转发,可以通过自定义截取 http 协议中如 cookie 内容,对流量进行灰度转发,控制分支特性。demo 示例部署了根据用户进行分支转发,将 user=jason 的用户的 recommend 转到 v2 分支上,其它基准环境不变,最终访问的拓扑图如下:

在正式环境中,可以通过不同版本的转发策略,实现流量级别的灰度升级,它的灰度粒度相比 tke 的 pod 级别的灰度,更加细致,同时灰度策略也可以更加灵活,可以定义包括 cookie、header、url 等各种方式的灰度策略。

2. polaris 体验

L5 作为腾讯内部的名字系统服务,目前已经被 polaris 兼容替换。sidecar、service mesh 的支持也在 polaris 的架构规划中。但目前业务还是以兼容 L5 的访问形式进行。对比 istio, polaris 诞生于腾讯内部, 内部业务未来通过 polaris 切换到 service mesh 比 istio  会更加容易。

(1)L5 兼容

L5 的服务端已经完全被无感知的替换到了 polaris,利用 polaris 的别名兼容 L5 的 modid:cmdid 的访问形式,使得业务侧可以没有太多的感知。业务团队也依然可以按照原来的方式进行后台的业务迭代。

(2)标准化 SDK

polaris 提供的标准化的 sdk ,支持了 go、cpp、java、python 等绝大多数语言。标准化的 sdk 维护相比各自团队的独立的框架、sdk,在微服务调用时,跨语言、跨平台的维护成本更低。

(3)微服务治理功能

目前的 polaris 虽然在底层通信方式上虽然依然和 L5 类似,除了支持基本的服务发现、服务注册与负载均衡, polaris 也提供统一面板管理微服务通信,支持了熔断、限流、健康监控等微服务治理的功能。

(4)未来规划

从 polaris 的规划看,sidecar、service mesh 都在 polaris 的支持中。相信在 polaris 支持 mesh 的过程中,对业务的改造工作量应该会更少、改造成本更低。

四、总结

互联网业务依旧在快速发展,越加融入日常生活,业务也更加复杂,业务量也更多。对于团队的迭代、架构也造成了影响。目前主流的服务端的微服务架构便是在业务复杂性、团队复杂性的基础上的新一代架构,适应团队随业务的快速拆分、迭代。微服务化也带来了新的通信问题。需要普遍处理服务注册、服务发现、负载均衡、熔断、限流、降级、可观测、认证授权、流量分析、监控统计等。而以 service mesh 通用化的形式处理微服务通带来的能力,集合了世界各大企业的智慧理念,已经成为了趋势所在。对于已经微服务化的服务架构团队,能否向 TCP 一样支持、处理微服务化带来的通信问题以及改造已有业务的成本是当前主要考虑因素。

polaris 目前更适应于腾讯内部业务,能够兼容业务的 L5 通信方式,也提供了基础的微服务治理功能,  在未来规划上支持 sidecar、mesh 能力。对于业务团队支持 mesh 上,预期迁移重构成本会更低。

istio 则是新一代开源 service mesh 产品的代表,它是目前 service mesh 的标杆产品,在功能支持上可以快速接入各种社区产品,但适应和改造已有业务的成本会更高,同时 istio 在性能、生产实践上也是待探索的。

参考文章:

[1] 技术往事:改变世界的TCP/IP协议:

https://cloud.tencent.com/developer/article/1194147

[2] Service Mesh技术对比:

https://hezhiqiang.gitbook.io/kubernetes-handbook/ling-yu-ying-yong/service-mesh/the-enterprise-path-to-service-mesh-architectures/comparing-service-mesh-technologies

[3] Service Mesh——后 Kubernetes 时代的微服务:

https://jimmysong.io/blog/service-mesh-the-microservices-in-post-kubernetes-era/

[4] Service Mesh:什么是Sidecar模式:

https://www.jianshu.com/p/626f9313e2bf

[5] Service Mesh架构解析:

https://www.servicemesher.com/blog/service-mesh-architectures/

[6] Sidecars and DaemonSets: Battle of containerization patterns:

https://wecode.wepay.com/posts/scds-battle-of-containerization

[7] Service Mesh演进历程:

https://skyao.io/learning-servicemesh/introduction/evolution.html

[8] 基于服务网格的测试环境路由治理方案:

https://zhonghua.io/2019/05/31/istio-protocol-extention/

[9] Service Mesh——后 Kubernetes 时代的微服务:

https://jimmysong.io/blog/service-mesh-the-microservices-in-post-kubernetes-era/

[10] 分布式架构发展史 Service Mesh:

http://www.soolco.com/post/44185_1_1.html

[11] 微服务的发展历程:

https://wewld.com/2018/07/09/微服务的发展历程/

[12] 架构演变之路:为何要搞微服务架构?

https://www.cnblogs.com/arthinking/p/12812786.html

0 人点赞