Dapr:我不是Service Mesh!我只是长得很像
引言
Dapr:“许多人都说我是Service Mesh,但我不是!我是Service Mesh下一代的发展方向”。
Service Mesh
(一)什么是Service Mesh
说到Service Mesh就不得不提一下微服务架构。随着具有分布式能力的微服务技术越来越火热,许多公司都已经完成了架构的技术转型。
但是这些框架技术多数都是以lib库依赖的形式集成在SDK中,并与业务代码部署在一起。SDK中lib库的升级无法对业务系统做到完全透明:业务系统会因为和业务无关的lib库升级而不得不进行升级。
分布式架构技术的火热,使得一些额外的分布式能力比如:如负载均衡、熔断限流、链路监控等也开始集成到SDK中。带来的好处是屏蔽了底层的实现细节,但是却使得应用程序的依赖变得越来越臃肿且难以维护。并且一些主流的微服务框架通常都与某种特定开发语言进行绑定,这就很难做到语言无关。
Service Mesh的出现使得上面提到的问题迎刃而解。优秀的架构设计使得Service Mesh天生就具有业务隔离和多语言支持的特点。如图1所示。

Mesh,即网格的意思。Service Mesh就是将服务像网格一样穿在一起,而真正进行网络通信的是网格内与应用程序(图2中绿色的部分)一起部署的Sidecar(图2中蓝色的部分)。

在Service Mesh中,Sidecar与应用程序部署在不同的进程中,不管Sidecar进行何种变化,应用程序对此都是是无感知的。
Service Mesh将原来集成到SDK中的服务发现、负载均衡等分布式能力下沉到Sidecar中,通过Sidecar的流量劫持转发应用程序的请求,所有的服务都通过自己的Sidecar进行相互通信。
所有的Sidecar集合到一起,就组成了Service Mesh的数据平面(图3中的所有的浅蓝色方块)。数据平面中的Sidecar则统一由控制平面进行管理(图3中的深蓝色方块)。

(二)Mesh技术的蓬勃发展
1.istio
Istio是由Google、IBM和Lyft共同开发的一款开源Service Mesh,通过Istio可以轻松的为已经部署的服务创建一个服务网格,而服务的代码只需要很少更改甚至无需更改。Istio也是一个与k8s紧密结合的适用于云原生场景的Service Mesh产品,通过Istio平台可以更方便的进行服务治理。
Istio具有的强大特性提供了一种统一的、更有效的方式来保护、连接和监视服务。Istio只需要进行简单的配置就可实现服务的负载均衡、服务到服务的身份验证等分布式功能。Isito的控制平面非常强大,它可以对Istio进行配置和管理,包括:
使用TLS加密、强身份认证和授权的集群内服务到服务的安全通信
自动负载均衡的HTTP、gRPC、WebSocket和TCP流量
通过丰富的路由规则、重试、故障转移和故障注入对流量行为进行细粒度控制
一个可插入的策略层和配置API,支持访问控制、速率限制和配额
对集群内的所有流量(包括集群入口和出口)进行自动度量、日志和跟踪

2.Linkerd
Linkerd是运行在Kubernetes上的Service Mesh,它提供了运行时服务调式、服务可观察性、可靠性和安全性的能力,并且服务的所有代码都无需进行修改。
Linkerd的工作原理是在每个服务实例所在的环境中部署一组超轻的透明代理,并且这些代理会自动处理所有来往于服务的流量。这些代理相对应用程序来说是透明的,他们可以高效的直接向控制平面发送遥测数据并接收控制信号,而不会被应用程序所感知。这种设计允许Linkerd在不引入过多延迟的情况下测量和操纵进出服务的流量。

3.云原生技术实践者层出不穷
在云原生技术蓬勃发展的今天,通过相关权威机构如CNCF的管理,国内外很多优秀的开源云原生技术都已面世。如Conduit、Consul、Envoy、华为的ServiceMesher、新浪微博MotanMesh、Mosn等等。
国内的大型互联网厂商如Alibaba、字节跳动,以及一些优秀的公司如中原银行、中移在线等,都在不遗余力的拥抱云原生,拥抱下一代Mesh化的微服务架构。
(三)Dapr:下一代Service Mesh的发展方向
当Mesh化技术在如火如荼的进行实践落地的时候,业界内又逐渐喊出了“将Mesh进行到底”的口号。
现在已经面世的几款优秀的Servcie Mesh产品主流定位大多是通讯层的透明代理,在网络层面解决问题,“将Mesh进行到底”却不仅仅局限于此。随着Dapr 1.0版本的发布,新一代Service Mesh架构的发展方向逐渐开始走进大家的视野。
Dapr
(一)Multi-Runtime(运行时)软件架构
Multi-Runtime(运行时)架构是一种未来架构趋势,Dapr便是基于此架构,从需求出发,分布式应用的主要需求包括以下四大类:
生命周期:主要是弹性伸缩和异常快速恢复的诉求
网络:可靠的网络、可靠的路由的需求
状态:对于服务编排、服务调度、状态管理等需求
绑定:与外部系统、中间件的通讯的需求

在此需求基础上,Service Mesh架构将网络层抽出为独立的边车进程,而参考Service Mesh架构,Multi-Runtime架构则是把各种边车提供的能力统一抽象成若干个Runtime,这样应用从面向基础组件开发就演变成了面向各种分布式能力开发。

(二)什么是Dapr
Dapr(Distributed Application Runtime,分布式运行时),是微软内部团队的一个开源项目。Dapr同样使用Sidecar架构,以独立进程的形式与应用程序同时运行,同时兼具Service Mesh中Sidecar/proxy的优点和高度可扩展的特性。
Service Mesh的发展为我们指明了一个发展方向:将SDK中的分布式能力外移到独立的Sidecar中。但是我们可以想象一下,在未来是否可以将我们现在集成的中间件能力也外移到独立的Sidecar中呢?比如说将数据库Mesh化、将消息中间件Mesh化、将缓存Mesh化,将除了业务代码程序之外的全部SDK都Mesh化。
在蚂蚁金服,已经有团队开始将Mesh化推广到中间件领域,如图8所示的在Mesh层出现的DB Mesh、Cache Mesh、Msg Mesh等Mesh化形态的模块。

我们可以将这些独立出来的Mesh化模块统称为提供不同功能的“运行时”组件。
过多的“运行时”组件出现之后,应用程序在运行时就会依赖一个或多个这样的Mesh化模块。虽然做到了将SDK移出了应用程序,但是这种多依赖的结果显然不是我们所期望的形式。
Dapr的出现将这些提供不同分布式能力以及中间件能力的“运行时”模块进行了整合,开发人员可以按照自己的需求,通过yaml文件的方式,将提供不同功能的组件整合到Dapr的构建块(Building Block)中。应用程序可以通过Dapr提供的标准API,访问构建块来获得并使用这些能力。

以图9为例,在k8s环境中,应用程序代码和Dapr的Sidecar分别运行在两个不同的容器中。应用程序代码可以通过标准的HTTP/gRPC协议使用Dapr提供的各种分布式能力,而Dapr中提供能力的构建块(Building Block)又是可以根据开发人员的需求进行可插拔和高度扩展的。
Dapr的这种模式极大的提升了Service Mesh体系中Sidecar的灵活性,并对各种不同的Mesh进行了统一的整合。可以说Dapr的这种模式是未来Service Mesh未来发展的一种新方向。
(三)Dapr的功能和架构
Dapr虽然也使用Sidecar架构,但是却提供了更多的能力和使用场景。
除了提供和Service Mesh一样的服务间远程调用(Service-to-service invocation)能力外,还提供了状态管理(State management)的能力来帮助开发人员构建出弹性的、有/无状态的应用程序,并且提供了发布订阅(Publish and subscribe)、资源绑定(Resource bindings)等额外的能力。
Dapr中所有功能都是通过使用Dapr中的构建块(Building Block)来进行提供。图10中蓝色方框中的内容,都是Dapr目前已经提供给应用开发人员使用的构建块。

在Dapr的架构中,有三个主要的组成部分:Dapr API、构建块(Building Block)和组件(Component),他们之间的关系如图11所示。

应用程序可以通过标准的Dapr API与构建块进行通信,构建块作为Dapr对外提供分布式能力的基本单元,将各种分布式能力进行了抽象,并将自己内部整合的分布式能力提供给应用程序。
组件(Component)是构建块的具体实现,每个构建块都是由一个或多个组件组成,并且所有的组件都是可插拔和高度扩展的。Dapr内部有自己的一套SPI扩展机制,任何开源的或者商业化的产品都可以很方便的集成到一个组件中。
例如想要将一个Redis集成到Dapr中,只需要将Redis集成到一个State的组件中就可以很方便的在应用程序中通过HTTP/gRPC协议使用Redis的功能,而不需要在应用程序中依赖操作Redis的SDK。
Dapr的主要架构可以总结为以下三点:
应用开发者只需要基于Dapr多语言的SDK,并且面向能力的方式对Dapr进行编程,而底层的具体实现方式由Dapr以yaml文件的方式进行激活。应用无需感知到自己使用的分布式能力是由哪种方式实现的。Dapr整体的功能图如图12所示。

(四)Dapr的特性
Dapr主要有两大特性:一个是跨语言、多运行环境支持(Any language,anywhere),一个是组件的可插拔、可替换。
应用开发者可以基于Dapr多语言的SDK面向Dapr的分布式能力进行编程,通过集成Dapr的SDK,可以使用任何语言、任何框架构建自己的微服务应用,并将应用运行在任何有Dapr的环境中。如图13所示。

同时Dapr也可以部署在任何环境里面,包括自己本地的环境、边缘计算的场景、拥有k8s的环境或者是任何的商业化云产品开发厂商的环境中。
在非k8s的环境中,Dapr和应用程序分别单独运行在自己的进程中,应用程序可以通过Dapr API与之进行通信,Dapr自己则以一个代理的身份为应用程序提供各种分布式能力。

在k8s的环境中,Dapr和应用程序运行在同一个Pod里,但是在不同的容器中。Dapr的构建块则分布在其他的Pod中,通过yaml文件的方式进行激活并让Dapr感知到。

在构建微服务应用时,每个组件都是独立的。开发人员可以采用其中一个或多个或全部来构建应用,并且组件的更新对应用来说是无感知的,应用程序不会感知到底层组件的升级。这也就是Dapr的第二个特性:组件的可插拔、可替换特性。
Dapr通过把一些构建微服务应用所需的最佳实践内置到开放、独立的构建块(building block)中,让开发人员只需专注于业务逻辑代码的编写,即可开发出功能强大的微服务应用,截至现在,Dapr社区中已经有70多个组件可供开发人员进行使用。
Dapr与Service Mesh
虽然Dapr和Service Mesh在架构上都是使用的Sidecar模式,并且在功能上也存在一些重叠部分,但是不能将Dapr简单的定义为Service Mesh。
图16展示了Dapr和Service Mesh提供的重叠功能和独特功能。

(一)不同点
通过上面的讲解,我们可以明白,Service Mesh主要专注于服务调用和网络问题,而Dapr是为了给应用服务提供更多的分布式能力而诞生的,两者的关注点在本质上就不一样。
Service Mesh主要以基础设施为中心:
与Service Mesh不同,Dapr是以开发人员为中心:
(二)相同点
如图17红框中所示,Dapr与服务网格都有的一些常见功能包括:
基于mTLS加密的服务到服务安全通信
服务到服务的度量指标收集
服务到服务分布式跟踪
故障重试恢复能力

Dapr与Service Mesh虽然有异同点,具体选择哪种技术还是要取决于具体的需求。可以只选择两者中的某一种,也可以两者全部使用,同时使用它们是没有任何限制的。
前景展望
Dapr为开发者提供了标准的API,这种API带来了支持多语言的、面向能力的、统一的编程体验。
Dapr目前仍处于不断迭代升级的状态,虽然社区的关注度很高,但是在将面向能力的API标准化并能持续发展的方向上Dapr还需要继续努力,在我们的调研实践中,我们总结了以下几个方面的期望和诉求:
(一)易用性
控制平面的建设,在目前的Dapr社区发展上来看,Dapr仅支持在每个Dapr实例上进行配置,维护成本较高,参考业界Istio、Linkerd等开源框架建设控制平面,对所有配置进行统一纳管,统一下发。
异地多活的解决方案,目前Dapr仅支持k8s集群或虚拟机部署,暂时不能感知多集群、多机房环境,异地多活的解决方案目前处于缺失状态。我们期望Dapr社区能提出解决方案,这也是Dapr成熟落地不可或缺的一步。
(二)可靠性
逃生模式,其实对于所有Service Mesh架构的组件都有类似的需求,当Dapr处于异常情况下,如何尽快恢复业务应该也是落地Dapr必须考虑的问题之一。
(三)可扩展性
目前Dapr已经对接业界大多数开源中间件和支持常见的Rpc协议,但很多公司都存在自研Rpc协议或自研中间件的情况。我们期望Dapr能提供一套成熟的插件式开发框架,满足各类用户的个性化需求。
在如今这个云原生技术蓬勃发展的时代,以Service Mesh和Dapr为代表的将分布式能力持续下沉的技术还将会继续向前演进。k8s、Serverless等云原生技术的发展,相信也会带动越来越多的公司进行云原生技术的转型,也会有更多的优秀产品在生产上进行落地。
拥抱云原生,我们需要一同努力探索。
本文转载自原银科技
参考文档
Dapr官方文档:
Isio官方文档:
Linkerd官方文档:
2021阿里巴巴研发效能峰会直播-Dapr在阿里云云原生的实践
Alibaba云原生技术专栏:
Conduit和Linkerd的创建者威廉·摩根(William Morgan)的文章:
ServiceMesher社区文章:
InfoQ社区文章: