这些自定义的扩展字段会破坏可移植性:如果你换一个组件,新组件肯定不认识这些字段,所以你得改代码。

2. 之所以出现这个问题,背后的根本原因是 Dapr API 的设计哲学。社区在设计 Dapr API 时,为了可移植性,设计出的 API 倾向于“功能交集”。比如在设计 API 时,会考察各种配置中心 A、B、C,如果 A、B、C 都有同一个功能,那么这个功能才会出现在 Dapr API 中:

启发式算法求解_启发式算法_启发式和算法式的区别

然而,在现实世界中,人们的需求可能是 A 和 B 的交集,B 和 C 的交集(如下图红色部分),而不是 A、B、C 的交集:

启发式算法_启发式算法求解_启发式和算法式的区别

或者更常见的是,用户的需求是“B 的所有功能”,其中必然包括一些 B 独有的功能,Dapr API 无法覆盖:

启发式算法_启发式算法求解_启发式和算法式的区别

3. Dapr API 有一定的侵入性

Dapr 提供“标准 API”、“语言 SDK”和“”,需要应用进行适配(这意味着老应用需要进行改造),侵入性比较大。

因此 Dapr 更适合新应用开发(所谓 Green Field),对于现有的老应用(所谓 Brown Field)则需要付出较高的改造代价。但在付出这些代价之后,Dapr 就可以提供跨云跨平台的可移植性,这是 Dapr 的核心价值之一。

这些听起来是解决不了的问题。那怎么办?

2.2 跨云部署时,你真的需要从 Redis 换成 吗?

在设计 API 时,常常出现类似的讨论:

A:嘿,这个功能只有 Redis 和 xxx 有,但是 和其他存储系统没有。我们该怎么办,要不要把这个功能纳入 API 规范里?

B:如果我们把这个功能纳入 API 里,会有什么问题?

A:那样的话,使用我们 API 的用户就没法从 Redis 迁移到 了,这破坏了可移植性!

等一等……你真的需要从 Redis 换成 吗?

你真的需要这种“可移植性”吗?

不需要吧!如果你的应用是面向 Redis 编程的,那它天生就能部署到不同的云上,因为每个云环境都有托管 Redis 服务。如果没有这种服务,你可以自己部署一个 Redis,让它有。

而且不止是 Redis,其他开源产品也可以类似操作。

舔狗定理

曾经听过一个很有意思的观点(不是我说的):商业公司们就像舔狗,哪个开源产品有商业机会,商业公司很快就会去跟进,那个产品就会在各种云上出现托管服务。话虽糙,但揭示了一个道理:开源产品的协议天生具有可移植性。

2.3 标准化 API 的价值是限制私有协议

为了让讨论更具体,让我们把应用依赖的基础设施协议划分成两类:可信协议与私有协议。

可信协议

指在某个领域影响力比较大的协议,衡量标准是:有托管服务的云环境 >=k(k 是某个让你有安全感的数字,比如 3,5)

比如 Redis 的协议,基本可以认为是和 SQL 一样的事实标准了,各个云厂商都提供了 Redis 托管服务;再比如 MySQL 协议,各个云厂商都会提供兼容 MySQL 协议的数据库托管服务。

启发式算法_启发式和算法式的区别_启发式算法求解

观点 1. 可信协议天生具有可移植性。

没必要担心“万一我以后想换云部署时,没法从 Redis 切换到 怎么办”。因为每个云上都有兼容 Redis 的托管服务。

担心要从 Redis 换成别的缓存产品,就像是担心“假如我今天引入了 ,如果以后 架构不流行了,我要去掉 怎么办”,或者“假如我今天引入了 Cloud,以后其他框架火了,我要换成别的框架怎么办”。那一天当然会出现,但是大部分业务都活不到那一天,如果能,恭喜你,到那时你会有足够的资源做重构。

私有协议

比如闭源产品的协议,或者影响力小的开源产品的协议,衡量标准是:有托管服务的云环境

举个例子,蚂蚁内部的 MQ 是自建 MQ,使用私有协议,业务代码依赖了这种私有协议就不好部署到别的云环境了,所以适合用标准化 API 包一层。

再比如,你在调研接入某个阿里云提供的 MQ,但是发现这个 MQ 的 API 是阿里云独有的,别的云厂商不提供这种服务,如果你害怕被阿里云绑定,最好用标准化 API 把这个私有 MQ API 包一层。

读到这,你应该明白我想说的了:

观点 2. Dapr 标准化 API 的价值是限制私有协议。

题外话:Sky

2021 年,UC 发了篇论文,预言云计算的未来是 Sky ,大意是说:回看互联网的历史,互联网连接了各种异构网络,对用户暴露出一个统一的网络,用户面向这个网络编程不需要关心具体每个异构网络的细节;今天不同云厂商的环境有差异,像极了互联网出现之前“各立山头”的状态,为了让用户更方便,我们可以设计一个“互联云”,连接各种异构云环境,屏蔽差异,只对用户暴露统一的抽象。连接不同云,可以叫“空计算”。

那怎么实现呢?作者提出了 3 层概念模型,最基础的第一层是“兼容层”,负责抽象不同云服务,让应用能够不改代码部署在不同云上。作者认为,开源软件在各个云上都有托管服务,所以可以把不同开源软件整合成一个平台,形成“兼容层”,并且现在已经有项目在这么做了,比如 Cloud 。

在“兼容层”之上,作者认为应该还有“ 层”和“ 层”,感兴趣的可以阅读原文。

2.4 我们需要什么样的“可移植性”

题外话:聪明的计算机科学家

计算机科学中有一种思想:如果一个问题太难了解决不了,那就放宽假设,弱化需求。用大白话讲就是:如果一个问题太难了解决不了,那就先解决一些更简单的问题。这样的例子很多:

比如实现数据库事务的“隔离性”会导致性能很差,只能在实验室环境使用,无法用在现实世界,于是人们提出“弱隔离性”,罗列出“读提交”,“可重复读”之类的“弱隔离级别”,越弱的问题越好解决;

比如在现实世界中,求解 NP-Hard 问题的最优解太慢了,不可行,于是人们提出,放弃追求最优解,只要能保证算法给出的结果在“可以承受的范围内”就行,于是有了“近似算法”;如果这也太难了,那就用玄学算法——“启发式算法”;

比如想实现“对业务透明”的分布式事务比较难,要付出很多代价,于是人们就提出放弃“对业务透明”,于是就有了 TCC 和 Saga;……

既然“可移植性”这个问题太难了,那就让我们弱化一下需求,先解决一些更简单的问题:“弱移植性”。

可移植性分级

“可移植性”这个需求太模糊了,我们先明确下需求。我们可以把可移植性分成多个等级:

level 0:业务系统换云平台部署时,需要改业务代码(比如换一套基础设施 sdk,然后重构业务代码)。

这是常见状态:比如某公司内部有一套自研消息队列系统“XX MQ”,有一个“xx-mq-java-sdk”供业务系统引入。当业务系统想要上云 / 换云部署时,由于云上没有“XX MQ”,需要换一个 MQ(比如换成 ),业务系统需要做重构。

level 1:换云平台部署时,业务代码不用改,但是需要换一套 sdk,重新编译。

社区有一些通过 sdk 做跨平台的方案,属于这个级别。比如携程开源的 Capa 项目,比如腾讯开源的 Femas 项目。

level 2:换云平台部署时,业务系统不需要改代码,不需要重新编译,但是 要改代码。

level 3:换云平台部署时,业务系统和 都不需要改代码,不需要重新编译,只需要改配置。

level 4:换依赖的开源产品时(比如原先使用 Redis,现在要换成别的分布式缓存),业务系统和 都不需要改代码。

社区的最终目标是 level 4,但是上文已述,现在还没法完美实现,存在种种问题。对于需要快速落地,解决业务问题的商业公司,现在能实现的目标是:追求 level 2 的可移植性,部分场景可以达到 level 3。这就足够解决业务问题了。

比如分布式缓存场景,蚂蚁在 MOSN 里自建了一套分布式缓存中间件支持 Redis 协议访问,如果你相信 Redis 协议是具有可移植性的,那么应用通过 Redis 协议和 MOSN 通信即可,没必要强行迁移到 Dapr 的“State API”上。在这种情况下,标准化 API 只是作为补充。

启发式算法求解_启发式和算法式的区别_启发式算法

题外话:Sky 的“兼容层”需要哪种可移植性?

按照这种分级方式,Sky 提出的“兼容层”需要 level 3 及以上的可移植性。

如何实现 level 3 可移植

如果我们把目标定为 level 3,那么 对外暴露的“兼容层”协议应该是多种多样的,包括各种领域的可信协议(比如 Redis 协议、MySQL 协议、AWS S3 协议等),以及 Dapr 风格的标准化 API。

启发式和算法式的区别_启发式算法求解_启发式算法

由此,我们可以得出两个观点:

观点 3. 拥抱可信协议:Dapr 标准化 API 的定位应该是作为可信协议的补充,而不是试图让用户放弃可信协议,迁移到 Dapr API 上。

观点 4. 设计 Dapr 标准化 API 时,要专注于那些还没有形成可信协议的领域,为这些领域设计标准化 API,而不是花精力设计“ SQL”,或者纠结“如何从 Redis 迁移到 ”。

比如,不同云厂商的配置中心提高的 API 不一样,还没形成事实标准,那么设计一套跨平台的 API 就能填补这个空缺。

演进路线

现在我们回答最开始提出的问题:

现在的 Dapr API 有很多问题,比如自定义扩展字段太多,破坏可移植性,比如面向“交集”做设计,功能太弱难以演进,比如侵入性强等等,该怎么办?

答案是:逐渐演进,先考虑从 level 2 演进到 level 3。

启发式和算法式的区别_启发式算法_启发式算法求解

为了实现 level 3,我们需要:

而为了实现最终的 level 4,我们需要:

启发式算法_启发式算法求解_启发式和算法式的区别

本文不再展开。

3. 架构带来的价值

除了标准化 API,实践中 架构更大的价值在于以下几个方面:

3.1 可能是最重要的价值:让“下沉”合理化

一个有趣的观察是:以前 Mesh 的概念强调“代理”,因此一些基础设施产品想把自己的代码逻辑也“下沉”进 时可能会遭到 Mesh 团队的拒绝,或者能“下沉”进去,但是实现的比较 hack,并不规范;而有了 的概念后,各种产品把代码逻辑挪到 行为就合理化了。

这里说的“下沉”,是指“把应用依赖的公共组件从应用里挪到 里”,分离核心业务逻辑和技术部分。好处就太多了,比如:

多语言复用中间件

Mesh 宣传的好处之一是让多语言应用复用流量治理类的中间件,现在 强调把更多的中间件放进 ,意味着有更多的中间件能够被多语言应用复用。比如,以前的中间件都是为 Java 开发的,C++ 用不了,现在可以让 Node.js//C++ 语言的应用通过 gRPC 调 ,复用中间件。

微服务启动加速、FaaS 冷启加速

原先微服务应用的框架比较重,比如有和配置中心建连、初始化、缓存预热之类的逻辑,现在这些启动逻辑都挪到 里。当应用或者函数需要扩容时,可以复用原有 ,不需要再做一遍类似的建连预热动作,从而达到启动加速的效果。

启发式算法求解_启发式和算法式的区别_启发式算法

不用推动用户升级 sdk 了

这个就是 Mesh 一直讲的好处:有了 后,不需要天天催促各个业务方升级 sdk,提高了基础设施的迭代效率。

让业务逻辑也能下沉

除了基础设施,一些业务逻辑也有放进 的诉求,例如处理用户信息等逻辑。

让业务逻辑放进 需要保证隔离性,去年尝试了用 来做,但是不太成熟,不敢在生产中使用,今年会尝试其他方案。

3.2 让“下沉”规范化:约束“私有协议”,保证能实现 level 2 可移植

在“下沉”的过程中,标准化 API 更多的是起到约束“私有协议”的作用,比如:

3.3 RPC 协议转换、微服务互通

Dapr 的 (用来做 RPC 调用的 API)设计的比较简单,也有一些不足,在实际 RPC 场景中, 调整了它的定位,作为 Mesh 的辅助:

已有的 Java 微服务的 RPC 流量还是通过 Mesh(MOSN)进行转发,而对于其他语言的微服务,或者其他协议栈的微服务,可以通过 gRPC 调用 ,由 帮忙做协议转换,然后把流量接入已有服务体系。

比如很多语言没有 库,可以通过 gRPC 调 , 帮忙做 序列化,然后将流量接入 MOSN。

启发式和算法式的区别_启发式算法求解_启发式算法

(业界也有一些做多语言微服务打通的项目,比如 -pixiu 项目,区别是通过网关的形式部署)

4. 如何划分 Mesh,Event Mesh 和 Multi- 的边界?

Mesh 和 Event Mesh 的区别是什么?网上的说法是 Event Mesh 处理异步调用的流量, Mesh 处理同步调用。

Mesh 和 Dapr 的区别是什么?网上的说法是 Mesh 是代理,Dapr 是运行时,要抽象 API,做协议转换。

但是,随着落地演进,我们渐渐发现这些技术概念的边界变得很模糊。

如下图, 这个 支持了各种协议,好像已经“非驴非马”了:不只是 Dapr 式的对外暴露标准化 http/gRPC API,抽象分布式能力,也包括 Mesh 式的流量拦截、代理转发,能处理同步调用、异步调用,能处理 Redis 等开源协议的请求,好像把 Event Mesh 的事情也做了,已经变成了一种混合模式的 :

启发式算法求解_启发式算法_启发式和算法式的区别

所以,如何划分 Mesh,Event Mesh 和 Multi- 的边界?

个人观点是,可以把 Dapr 的“标准化 API”看做“ 增强”。比如“ API”可以看成“ Mesh 增强”,“ API”可以看成是“Event Mesh 增强”,“State API”可以看成“数据中间件增强”,这里说的数据中间件包括缓存流量转发和 DB Mesh。从这种角度看, 更像是 里的“API 网关”。

启发式算法_启发式算法求解_启发式和算法式的区别

5. 部署形态之争

5.1 目前的架构有什么问题?

目前的架构存在一个问题: 是个巨石应用。

不管是 Dapr 还是 ,都倾向于承载所有和业务无关的功能。

如果你把 类比成操作系统的内核,那么 API 这层就是系统调用,负责抽象基础设施,简化编程,而不同的组件类似于驱动,负责把系统调用翻译成不同基础设施的协议。 把所有组件都放在一个进程里,类似于“宏内核”的操作系统把所有子模块都塞在一起,变成了巨石应用。

巨石应用有什么问题?模块间互相耦合,隔离性不好,稳定性降低。比如之前就有研究指出 Linux 中大部分的代码是驱动,而且很多驱动是“业余玩家”写的,稳定性不好,驱动写的有问题是 崩溃的主要原因。同样的,如果 Dapr 或者 的一个组件出现 bug,会影响整个 。

怎么解决巨石应用的问题呢?拆!一个思路是把 按模块拆分,每个模块是一个 ,整个 以 的形式部署:

启发式算法求解_启发式和算法式的区别_启发式算法

这种方案就像操作系统的“微内核”,不同子模块之间有一定的隔离性,但相互通信的性能损耗会高一些。比如 Event Mesh 容器想要读取配置中心的配置时,就需要通过网络调用 容器;如果调用频率过高,就要考虑在 Event Mesh 容器里做一些配置缓存,可能最后每个容器都要做一套缓存。

那么应该选择单容器 还是多容器 呢?这就像操作系统选择“宏内核”还是“微内核”架构,全看取舍。巨石应用的好处是子模块之间互相通信性能好,缺点是紧耦合,隔离性不好;如果把 拆成多个 则刚好相反。

目前,Dapr 和 都是单容器 。

一个可能的拆分方案是:将 按能力“垂直拆分”成多个容器,比如一个容器负责状态存储,一个容器负责异步通信等等,容器间通信通过 eBPF 做优化。不过目前还没看到这样做的项目。

5.2 目前的架构还可以做哪些优化?

直觉上想,如果能让新启动的应用(或函数)复用已有的 ,就能省掉一些初始化动作,加速启动。

每个 Pod 都有一个 容器,假如一个节点有 20 个 Pod,就得有 20 个 ,在大规模集群里光是 就要占用很多内存。

启发式算法求解_启发式和算法式的区别_启发式算法

能否减少 的资源占用?

直觉上想,如果能让多个容器共享同一个代理(而不是每个容器独享一个代理),就能减少资源占用。

上述两点看起来都可以通过“让多个容器共享同一个代理”来做优化。但事情真有那么简单吗?

Mesh 社区关于“共享代理”的讨论

其实 Mesh 社区有过很多关于数据面部署形态的争论,大致有以下几种方案:

启发式算法求解_启发式算法_启发式和算法式的区别

(图片来自)

启发式算法求解_启发式算法_启发式和算法式的区别

(图片来自)

很优雅,但功能有限,满足不了所有需求。

启发式算法求解_启发式和算法式的区别_启发式算法

(图片来自)

启发式算法_启发式算法求解_启发式和算法式的区别

(图片来自)

社区还需要共享代理吗?

上面几种方案看起来都行,只是取舍问题,但是到了 这里,情况就变了!

情况 1:集群里有各种各样的中间件,各种各样的基础设施

如果集群里有各种各样的中间件,各种各样的基础设施,那还是别用“节点上所有 Pod 共享同一个代理”的模型了。

举个例子,某集群里有各种各样的 MQ,如果节点上所有 Pod 共享同一个 , 事先不知道 Pod 会用什么 MQ,所以它必须在编译时带上所有 MQ 组件。每次新建一个 Pod 时,这个 Pod 要动态把配置传给 ,告诉 它要用哪个 MQ,然后 再根据配置去和相应的 MQ 建立连接。

比如下图,某个节点上,Pod 1、Pod 2、Pod 3 分别使用 、Kafka、,这时新启动了一个 Pod 4,Pod 4 告诉 它很有个性,它要用 !于是 就得去和 建连,做一些初始化动作。所以,Pod 4 启动并没有“加速”,因为它没能复用之前已有的连接。

启发式和算法式的区别_启发式算法_启发式算法求解

这种情况下,共享 并不能帮助应用启动加速,无法复用和后端服务器的连接数,虽然能省一些内存,但带来了一些缺点:增加了复杂度,降低了隔离性等等。

如果强行把 模型的 改成共享代理,有用,但投入产出比不高。

情况 2:集群里基础设施的技术栈比较统一

在这种情况下,共享代理模型可能有一定价值。

比如,某集群只用一种 MQ,。假如使用共享代理模型,某个节点上 Pod 1、Pod 2、Pod 3 已启动,这时新启动一个 Pod 4 也要用 ,此时就可以复用已有的一些元数据,甚至有可能复用和 MQ 服务器的连接。

启发式算法_启发式算法求解_启发式和算法式的区别

这种情况下,共享代理模型的好处有:

不过,所谓“启动加速”也是要看情况的,比如通过优化让 启动快了 2 秒,但是应用启动却要 2 分钟,那么优化 2 秒其实并没有多大用处。尤其是有很多 Java 应用的集群,大部分 Java 应用启动不快,这点优化价值有限。所以,启动加速在 FaaS 场景会比较有用。如果函数本身启动、加载速度较快,优化几秒还是很有价值的。

6. 总结

本文讨论了 落地之后,关于 Multi- 架构“可移植性”、落地价值以及部署形态等方面的思考。且本文的讨论不限定于某个具体项目。

作者简介:

周群力,目前在蚂蚁中间件团队负责 项目的开发,以及 和 开源社区的建设。Dapr 贡献者,Dapr sig-api 的 Co-chair。个人 :

参考链接:

Multi- :

———END———
限 时 特 惠: 本站每日持续更新海量各大内部创业教程,永久会员只需109元,全站资源免费下载 点击查看详情
站 长 微 信: nanadh666