应用技术架构 —— 分布式应用多运行时架构

2023-03-22 09:55:56 浏览数 (4)

本文作者:何文强 — CODING 高级解决方案架构师 具有一线互联网、物联网独角兽、全国股份制银行、新型智慧交通等跨行业从业经历,历任 Java 开发高级工程师、DevOps 技术专家、高级研发经理等职,对微服务、敏捷、DevOps、容器技术有深刻的理解和丰富的实践。

多运行时微服务背景

在分布式系统中,应用通常包含业务逻辑、非功能性需求(NFR)和中间件依赖(三方依赖)。在应用程序中,只有业务逻辑才承载具体的业务价值,NFR 和三方依赖是必要的非增值活动,不直接产生业务价值,但是非增值活动耗费开发人员大量的时间和精力,导致业务交付速度慢。

在微服务架构中,主流的微服务框架解决了部分 NFR 和三方依赖的能力,提升了业务价值专注度,但是所有的能力都耦合在应用程序中,导致其扩展性和复用性说到严重挑战。

在服务网格中,将 NFR 能力从业务逻辑中抽离出来,下沉到单独的组件中,实现 NFR 与业务逻辑的沉底解耦,进一步将开发人员从非增值活动中解放出来,更加专注于业务价值交付。服务网格解决了大部分的 NFR 的能力(如可观测性、熔断、限流、灰度、路由、负载均衡等),但是三方依赖(如 Mysql、Redis、MQ 等)等依赖于业务逻辑耦合,仍然需要开发人员通过 lib 库或 SDK 的方式在业务代码中进行集成,不能让开发纯粹的专注于业务逻辑开发和业务价值交付。

三方依赖(分布式能力)是否也可以以 sidecar 的方式独立于业务逻辑,并且提供统一的能力抽象,屏蔽底层的组件差异,成为技术架构演进的新方向。以 Dapr 为代表的分布式应用多运行时肩负着使命和重任闪亮登场。

多运行时微服务简介

多运行时微服务架构由 Bilgin Ibryam 提出,围绕“微服务”架构和“云原生 12 要素应用程序”的最佳实践,提出了交付生命周期、网络、状态管理以及绑定外部依赖四个方面的多运行时微服务架构。

在多运行时微服务架构中,将非功能性需求(NFR)和三方库能力彻底与业务逻辑解耦,并以独立的 sidecar(进程)提供这些能力。开发人员无需关注必要的非增值活动,最大限度的管制业务逻辑实现和业务价值交付。同时多运行时微服务建立完整的应用模型,将各种非功能性需求和分布式能力进行分类和抽象,业务逻辑与 sidecar 通过标准的协议进行通信,实现跨平台跨语言的服务治理。

非功能性需求(NFR)

分布式能力与主流实现

分布式应用需求

现代分布式应用需求主要分为四种类型:生命周期、网络、状态、绑定。

图为传统中间见平台与云原生平台概述

生命周期(Liftcycle)
  • 打包(Packaging)
  • 健康检查(Healthcheck)
  • 部署(Deployment)
  • 缩扩容(Scaling)
  • 配置(Configuration)

传统中间件局限:

在传统的中间件中,通常只有一个受支持的语言运行时(例如 Java),它规定了软件的打包方式,可用的库,需要修补的频率等。业务服务必须使用这些库。使其与以相同语言编写的平台紧密结合。实际上,这导致服务和平台升级被关联起来,从而阻止了独立和常规的服务和平台发布。

解决方案:

容器和 Kubernetes 将打包,分发和部署应用的方式发展为与语言无关的格式。对于 Kubernetes,要管理的最小原语是容器,它专注于在容器级别和流程模型上交付分布式原语。这意味着它在管理应用的生命周期,健康检查,恢复,部署和扩展方面做得很出色,但是在容器内的分布式应用的其他方面却没有做得很好,例如灵活的网络,状态管理和绑定。

网络(Networking)
  • 服务发现(Service discovery)
  • A/B 测试,金丝雀、回滚(A/B testing,canary rollouts)
  • 重试、超时、熔断(Retry,timeout,circuit breaker)
  • 安全、可观察性(Point-to-point,pub/sub)

传统中间件局限:

尽管传统中间件也具有围绕与其他内部和外部服务交互的高级功能集,但它有一些主要缺点。网络功能集中于一种主要语言及其相关技术。对于 Java 语言,即 JMS,JDBC,JTA 等。更重要的是,网络问题和语义也深深地刻在业务服务中。有一些具有抽象的库来处理网络问题(例如曾经很受欢迎的 Hystrix 项目),但是该库的抽象也“泄漏”到了服务的编程模型,交换模式和错误处理语义以及库本身中。虽然可以方便地在一个位置编写和读取与网络方面混合的整个业务逻辑,但是这将两个问题紧密地耦合到实现中,最终形成了共同的演进路径。

解决方案:

通过服务网格,将与网络相关的问题从包含业务逻辑的服务中移出,放到单独的运行时(sidecar 或节点代理)。在不改动服务的情况下,完成对更高级的发布策略,管理安全性,指标,跟踪,从错误中恢复,模拟错误等等方面的需求。

状态(State)
  • 工作流管理(Workfow mgmt)
  • 幂等性(Idempotency)
  • 时间调度(Temporal scheduling)
  • 缓存(Caching)
  • 应用状态(Application state)

传统中间件局限:

为了进行可靠的服务编排,业务流程管理以及实现模式(例如 Saga 模式和其他运行缓慢的流程),平台需要在幕后持久化状态。同样,临时动作(例如触发计时器和 cron 作业)建立在状态之上,并且需要在分布式环境中对数据库进行集群和恢复。这里的主要约束是以下事实:与状态交互的库和接口没有完全抽象出来,也没有与服务运行时解耦。通常,这些库必须配置有数据库详细信息,并且它们存在于服务中,从而将语义和依赖关系泄漏到应用域中。

解决方案:

将所有状态功能抽象到一个单独的运行时中。这意味着工作流管理,单例,幂等,事务管理,cron 作业触发器和有状态错误处理都可靠地发生在 Sidecar(或主机级代理)中,而不是存在于服务中。业务逻辑不需要在应用中包含此类依赖关系和语义,并且可以从绑定环境中声明性地请求此类行为。

绑定(Binding)
  • 链接(Connectors)
  • 协议转换(Protocol conversion)
  • 消息投递(Message transformation)
  • 消息路由(Message routing)
  • 事务性(Transactionality)

传统中间件局限:

使用集成中间件的主要驱动力之一是能够使用不同的协议,数据格式和消息交换模式连接到其他各种系统。但是,这些连接器必须与应用程序一起使用,这意味着必须将依赖关系与业务逻辑一起更新和修补。这意味着必须在服务中来回转换数据类型和数据格式。这意味着必须根据消息交换模式来构造代码并设计流程。即使是抽象的端点也会影响传统中间件中的服务实现,有很多这方面的例子。

解决方案:

连接器,协议转换,消息转换,错误处理和安全中介都可以移出服务运行时。将所有这些职责移出应用运行时将导致更小,更专注于业务逻辑的代码。这样的代码将在运行时中运行,运行时独立于分布式系统需求,而分布式系统需求可以作为预先打包好的功能使用。

多运行时微服务架构

图为多运行时微服务

  • Kubernetes 和容器在多语言应用程序的生命周期管理中取得了巨大的飞跃,并为未来的创新奠定了基础。
  • 服务网格技术在 Kubernetes 之上利用高级的网络功能进一步进行了改善,并开始涉足应用程序方面。
  • 尽管 Knative 凭借其快速扩展主要专注于 serverless 类型的工作负载,但是,它也满足了服务编排和事件驱动的绑定需求。
  • Dapr 建立在 Kubernetes、Knative 和服务网格的思想之上,并深入应用程序运行时以解决状态化工作负载、绑定和集成的需求,充当现代分布式中间件。
概述

这是一个有两个组件的模型,其中每个组件都是独立的运行时。这两个组件都位于同一个主机中,并且在它们之间有可靠的网络。组件之一称为微逻辑(Micrologic),它包含了几乎所有从分布式系统关注点中剥离出来的最小业务逻辑。另一个组件叫 Mecha,提供了所有分布式系统功能(生命周期除外,它是平台的功能)。

图为多运行时(进程外)微服务架构

Mecha 特征:

  • Mecha 是一个通用的、高度可配置的、可重用的组件,提供分布式原语作为现成的功能。
  • Mecha 的每个实例必须配置成与一个微逻辑组件(边车模型)一起工作,或者配置成与一些组件共享。
  • Mecha 不对微逻辑运行时做任何假设。它与利用开放协议和格式(如 HTTP/gRPC、JSON、Protobuf、CloudEvents)的多语言微服务或甚至单体系统一起工作。
  • Mecha 用简单文本格式(如 YAML、JSON)进行声明式配置,这些格式规定了要启用什么功能以及如何把它们绑定到微逻辑端点上。对于特定的 API 交互操作,可以为 Mecha 附加规范,如 OpenAPI、AsyncAPI、ANSI-SQL 等。对于由多个步骤构成的状态化工作流,可以使用如亚马逊状态编程语言(Amazon State Language)的规范。对无状态集成,可以用类似 Camel-K YAML DSL 的方法使用企业集成模式(Enterprise Integration Patterns,简称 EIPs)。所有这些都是简单的、基于文本的、声明式的、多语言定义的,Mecha 可以不需要编码就能实现。Mecha 是应用程序级别的分布式原语抽象层。
  • 与其依赖于用于不同目的(如网络代理、缓存代理、绑定代理)的多个代理,不如有一个提供所有这些功能的 Mecha。某些能力的实现(如存储、消息持久性、缓存等)将会有其他的云或自建的服务插入并支持。
  • 关于生命周期管理的一些分布式系统问题由管理平台(比如,Kubernetes 或其他云服务)而不是由使用 Open App Model 等通用开放规范的 Mecha 运行时来提供是合理的。
多运行时微服务架构 Dapr

Dapr 是 Distrubuted application runtime 的缩写,即分布式应用运行时。Dapr 是一个可移植的、事件驱动的运行时,它使任何开发人员能够轻松构建出弹性的、无状态和有状态的应用程序,并可运行在云平台或边缘计算中,它同时也支持多种编程语言和开发框架。

Dapr 的发展非常迅速,目前 Dapr 最新的稳定版为 1.5。

Dapr 设计理念

Dapr 将构建微服务应用的最佳实践设计成开放、独立和模块化的方式,开发者能够使用任意的开发语言和框架构建可移植的应用程序。每个构建块都是完全独立的,可以采用其中一个、多个或全部来构建应用。

Dapr 是和平台无关的,可以在本地、Kubernetes 集群或者其它集成 Dapr 的托管环境中运行应用程序,能够在云平台和边缘计算中运行微服务应用。

Dapr 技术架构

Dapr 架构主要由 API、Building Blocks、Components 三部分组成。

Dapr API

Dapr 利用标准 API 暴露各种分布式能力。API 定义了应用所需的分布式能力。Dapr 提供两种 API:HTTP 1.1/REST 和 HTTP2/gRPC,两者在功能上是等价的。这些 API 是平台无关的,或者说是实现无关的。

应用只需要按照 API 规范发起,不管是服务访问,还是存储,还是发布消息到队列里,都是 HTTP 接口。不管是操作 redis 还是 mysql 都是一样的 API。在应用看来,一切所需的能力,都可以用 HTTP 协议来表示,这些能力的获取是标准化的,只要应用需要的分布式能力不变,那应用的代码就不需要改变。

将「分布式原语」映射到 Http API 上,极大地减少了程序员心智的开销。在应用代码中不再需要引入相关的组件调用库,不需要去封装组件的具体调用方式,不需要对不同的实现做区分。在用户应用侧,Dapr 还提供了多种语言的 SDK,这些 SDK 的目的是用更便捷的方式来暴露 Building blocks 的 API,用更加语义化的方法调用,来封装 Http/gRPC 的调用。

Dapr 构建块(Building Blocks)

构建块(Building Blocks)是 Dapr 对外提供能力的基本单元,是对分布式能力的抽象和归类。Dapr building blocks 实现了 multi runtime 中的 networking、state 和 Bingding(lifecycle 由 Kubernetes 等平台提供)能力。Dapr 中的构建块是完全独立的,应用可以按需调用。

Dapr 构建块

Dapr 构建块包括以下几大类:

  • 服务调用(Service-to-service invocation)

服务调用使应用程序能够通过 Http 或 gRPC 消息形式相互通信。Dapr 提供了一个终结点,它充当反向代理与内置服务发现的组合,同时内置分布式跟踪和错误处理。

  • 状态管理(State management)

发布/预订是松散耦合的消息传递模式,发送方 (或发布者) 将消息推送到订阅者预订的主题。Dapr 支持应用程序之间的发布/订阅模式。

  • 发布订阅(Publish and subscribe)

绑定提供一个外部云与本地服务或系统的双向连接。Dapr 允许您通过 Dapr 绑定 API 调用外部服务,也可以通过已连接的服务发送的事件来触发应用程序。

  • 资源绑定(Resource bingdings)

参与者是孤立的独立计算单元,具有单线程执行。Dapr 提供了基于 Virtual Actor 模式的 actor 实现,该模式提供了单线程编程模型,并且在不使用 actor 时会对其进行垃圾回收。

  • Actors

参与者是孤立的独立计算单元,具有单线程执行。Dapr 提供了基于 Virtual Actor 模式的 actor 实现,该模式提供了单线程编程模型,并且在不使用 actor 时会对其进行垃圾回收。

  • 可观测性(Observability)

Dapr 系统组件和运行时记录 metrics,log 和 trace 以调试,操作和监视 Dapr 系统服务,组件和用户应用程序。

  • 密钥(Secrets)

Dapr 提供一个机密构建块 API ,并与 Azure Key Vault 和 Kubernetes 等机密商店集成,以存储机密。服务代码可以调用密钥 API 从 Dapr 支持的密钥存储中检索密钥。

Dapr 组件(Components)

被用于构建块和应用程序的模块化功能。Dapr 使用模块化设计,将功能作为组件来提供。每个组件都有接口定义。所有组件都是可插拔的,因此您可以将组件换为另一个具有相同接口的组件。Dapr 的本质是对分布式能力的抽象。

分布式能力抽象示意图

构建块可以使用任何组件组合。Dapr 提供的以下组件类型:

  • 绑定

构建块使得外部资源可以连接到 Dapr 以触发服务或作从应用触发外部服务。

  • 状态存储(State stores)

状态存储组件是存储键值对的数据存储(数据库、文件、内存),其作为 状态管理的构建模块之一。

  • Pub/Sub 代理

发布/订阅 组件是消息分发器,可以作为应用程序之间进行消息发布 & 订阅构建块。

  • 可观测性

利用 Dapr 构建块来执行服务到服务调用和 pub/sub 消息传递构建应用程序时, Dapr 拥有相对于 distributed tracing 的优势,因为此服务间通信全部流经 Dapr sidecar,sidecar 处于这样独特的位置,可以消除应用程序级别检测的负担。

  • 中间件

Dapr 允许将自定义 中间件 插入请求处理管道。中间件可以在请求路由到用户代码之前,或者在将请求返回给客户端之前,对请求执行额外的操作(例如,认证,加密和消息转换)。中间件组件与 服务调用 基础结构块一起使用。

  • 服务发现

服务发现组件与 服务调用 构建块配合使用,与托管环境集成以提供服务到服务发现。例如,Kubernetes 服务发现组件与 Kubernetes DNS 服务集成,而自托管时使用 mDNS。

Dapr 实例化讲解

这是一个简单的采用 Dapr 的服务调用。示例中实现功能如下:Python code 发送请求到 Node code,Node code 将调用中间件 redis,并将结果返回给 Python。

在图中的 ①,Pytchon Code 发送请求,流量转发 python code sidecar,python code sidecar 将流量路由到 Node code sidecar,Node code sidecar 将流量转发到 Node code中(图中的 ②),Node code 通过 sidecar 将向 dapr component 发起请求 http 的 redis 请求(图中的 ③),请求的 component 类型和具体实现在 componet 声明式文件中的的 type 字段中定义,图中的 ③ type:state.redis 等价于组件类型是 state store(状态存储),组件实现是 redis。

因此,在 ② 中通过 http 请求就能获取 ③ 中 redis 数据,而不需要单独的 redis 客户端。完全实现业务逻辑与 redis 的解耦,调用分布式中间件就是发起一个标准的 rest api 请求。

通过组件的方式,可以松耦合低成本的替换具体的中间件,例如将 redis 存储换成 memcached,只需要在声明式配置文件中将 type:state.memcached,其他的无需任何改造,就能轻松的对 memcached 进行数据操作,开发者可以轻松的获取各种分布式的能力,实现分布式能力的开箱即用。这是 dapr 对分布式能力抽象及架构的一个实例化解释。

特点:

  • 业务逻辑与分布式能力彻底解耦;
  • 分布式能力开箱即用,最大程度减少开发人员的非业务价值交付活动;
  • 统一的标准访问方式,跨平台和跨语言。
多运行时微服务架构的优势和不足
优势
  • 以“以应用为中心”;
  • 将业务逻辑与非功能性需求、中间件能力彻底解耦;
  • 面向分布式能力编程,简化分布式微服务应用的复杂性;
  • 强大且灵活,对多语言、多平台、多环境的天然友好支持。
不足
  • 性能受损较为严重;
  • 成熟度低,缺乏大规模实践验证;
  • 生态不够完善,对组件的支持能力比较有限;
  • 能力模型难统一,能力和场景受限。
多运行时微服务架构发展趋势
  • 进一步完善生态能力;
  • 与容器平台深度融合;
  • 与 servicemesh 深度融合;
  • 与无服务器架构深度融合。

《数字化 IT 从业者知识体系》背景

数字化和可持续发展是中国企业未来发展的两大主题,掌握数字化知识,具备数字化能力,应用数字化技术是我们 IT 从业者未来核心竞争力所在。《数字化 IT 从业者知识体系》的初衷是为 IT 从业者提供的系统性的数字化知识体系,内容涵盖管理实践、工程实践、技术实践三个层次,涉及软件开发方法、应用技术架构、应用部署与管理、软件交付与协作四大方面。

在接下来的《数字化 IT 从业者知识体系》系列文章,何文强将从软件开发方法、应用技术架构、应用部署与管理、软件交付与协作四个方面,为大家进行逐一分享介绍:

1. 软件开发方法主要包括瀑布、敏捷、精益等;

2. 应用技术架构主要包括微服务架构、服务网格架构、无服务器架构、分布式多运行架构等;

3. 应用部署与管理主要包括但不限于虚拟化技术、容器技术与容器编排等;

4. 软件交付与协作主要包括但不限于 CMMI、ITIL、DevOps 等。

相信该知识体系有利于 IT 从业者构建丰富的技术体系、全面的技术视野和系统的能力建设。欢迎大家前往《数字化 IT 从业者知识体系》话题进行详细阅读。

1 人点赞