目录
- 一、云原生架构定义
- 二、云原生架构原则
- 三、云原生架构主要架构模式
- 3.1 服务化架构模式
- 3.2 Mesh化架构模式
- 3.3 Serverless模式
- 3.4 存储计算分离模式
- 3.5 分布式事务模式
- 4.6 可观测架构
- 3.7 事件驱动架构
- 四、云原生架构反模式
- 五、云原生架构技术
- 5.1 容器技术
- 容器编排K8S
- 5.2 云原生微服务
- 5.3 无服务器技术
- 5.4 服务网格
- 六、云原生架构案例
一、云原生架构定义
云原生 来自于 Cloud Native 的直译,拆开来看,
Cloud 就是指其应用软件是在云端而非传统的数据中心。
Native代表应用软件从一开始就是基于云环境、专门为云端特性而设计,可充分利用和发挥云平台的弹性+分布式优势,最大化释放云计算生产力。
DevOps 可以看作是开发、技术运营和质量保障三者的交集,
促进之间的沟通、协作与整合,从而提高开发周期和效率。
而云原生的容器、微服务等技术正是为 DevOps提供了很好的前提条件,保证 IT 软件开发实现 DevOps 开发和持续交付的关键应用。
从技术的角度,云原生架构是基于云原生技术的一组架构原则和设计模式的集合,
旨在将云应用中的非业务代码部分进行最大化的剥离,从而让云设施接管应用中原有的大量非功能特性(如弹性、韧性、安全、可观测性、灰度等), 使业务不再有非功能性业务中断困扰的同时,具备轻量、敏捷、高度自动化的特点。
由于云原生是面向“云”而设计的应用,因此,技术部分依赖于传统云计算的3层概念,即基础设施即服务 (IaaS)
、 平台即服务 (PaaS)
和软件即服务 (SaaS)
。
云原生的代码通常包括三部分:业务代码
、三方软件
、处理非功能特性的代码
。
其中“业务代码”
指实现业务逻辑的代码;
“三方软件”
是业务代码中依赖的所有三方库,包括业务库和基础库;
“处理非功能性的代码”
指实现高可用、安全、可观测性等非功能性能力的代码。
三部分中只有业务代码
是核心,是对业务真正带来价值的,另外两个部分都只算附属物,但是,随着软件规模的增大、业务模块规模变大、部署环境增多、分布式复杂性增强,使得今天的软件构建变得越来越复杂,对开发人员的技能要求也越来越高。云原生架构相比较传统架构进了一大步,从业务代码中剥离大量非功能性特性(不会是所有,比如易用性还不能剥离)到 IaaS和PaaS 中,从而减少业务代码开发人员的技术关注范围,通过云厂商的专业性提升应用的非功能性能力。
此外,具备云原生架构的应用可以最大程度利用云服务和提升软件交付能力,进一步加快软件开发。
二、云原生架构原则
助记:服持弹韧零自测
服务化原则
拆分为微服务
架构、小服务架构,分别迭代。
弹性原则
系统的部署规模可以随着业务量的变化而自动伸缩
,无须根据事先的容量规划准备固定的硬件和软件资源。
可观测原则
通过日志
、链路跟踪
和度量
等手段,使得一次点击背后的多次服务调用的耗时、返回值和参数都清晰可见
韧性原则
当软件所依赖的软硬件组件出现各种异常时,软件表现出来的抵御能力。
韧性从多个维度诠释了软件持续提供业务服务的能力,核心目标是提升软件的平均无故障时间 (Mean Time Between Failure,MTBF)。
从架构设计上,韧性包括服务异步化能力
、重试/限流/降级/熔断/反压
、主从模式
、集群模式
、 A Z 内的高可用、单元化、跨 region 容灾、异地多活容灾等。
所有过程自动化原则
通过 IaC(Infrastructure as Code)、GitOps、OAM(Open Application Model)、Kubernetes Operator 和大量自动化交付工具在 CI/CD 流水线
中的实践,一方面
标准化企业内部的软件交付过程,另一方面
在标准化的基础上进行自动化,通过配置数据自描述和面向终态的交付过程,让自动化工具理解交付目标和环境差异,实现整个软件交付和运维的自动化
。
零信任原则
默认情况下不应该信任网络内部和外部的任何人/设备/系统
,
需要基于认证和授权重构访问控制的信任基础,诸如 IP地址、主机、地理位置、所处网络等均不能作为可信的凭证。
零信任对访问控制进行了范式上的颠覆,引导安全体系架构从“网络中心化”
走向“身份中心化”
,其本质诉求是以身份为中心进行访问控制
。
架构持续演进原则
今天技术和业务的演进速度非常快,
很少有一开始就清晰定义了架构并在整个软件生命周期里面都适用,
相反往往还需要对架构进行一定范围内的重构
,
因此云原生架构本身也必须是一个具备持续演进能力的架构
,而不是一个封闭式架构。
三、云原生架构主要架构模式
助记:ssh tcoe
Service、Serverless、Mesh、
Distributed Transaction、Storage/Computation Seperation、Observability、EDA
3.1 服务化架构模式
服务化架构是云时代构建云原生应用的标准架构模式,
要求以应用模块
为颗粒度划分一个软件,
以接口契约(例如 IDL)
定义彼此业务关系,
以标准协议 (HTTP、gRPC 等)
确保彼此的互联互通,
结合DDD (领域模型驱动)
、TDD (测试驱动开发)
、容器化部署
提升每个接口的代码质量和迭代速度。
服务化架构的典型模式是微服务和小服务模式。
3.2 Mesh化架构模式
Mesh化架构是把中间件框架(如 RPC、 缓存、异步消息等)
从业务进程中分离,让中间件SDK与业务代码进一步解耦,从而使得中间件升级对业务进程没有影响,甚至迁移到另外一个平台的中间件也对业务透明。分离后在业务进程中只保留很“薄”的 Client部分
, Client通常很少变化,只负责与 Mesh 进程通信,原来需要在 SDK中处理的流量控制、安全等逻辑由 Mesh进程完成。
3.3 Serverless模式
Serverless 将“部署”
这个动作从运维中“收走”,使开发者不用关心应用运行地点、操作系统、网络配置、 C P U性能等,
从架构抽象上看,当业务流量到来/业务事件发生时,云会启动或调度一个已启动的业务进程进行处理,处理完成后云自动会关闭/调度业务进程,等待下一次触发,也就是把应用的整个运行都委托给云
。
Serverless 并非适用任何类型的应用,因此架构决策者需要关心应用类型是否适合于Serverless运算。
- 如果应用是有状态的,由于 Serverless 的调度不会帮助应用做状态同步,因此云在进行调度时可能导致上下文丢失;
- 如果应用是长时间后台运行的密集型计算任务,会无法发挥 Serverless 的优势;
- 如果应用涉及频繁的外部 I/O (网络或者存储,以及服务间调用),也因为繁重的 I/O 负担、时延大而不适合。
- Serverless 非常适合于事件驱动的数据计算任务、计算时间短的请求/响应应用、没有复杂相互调用的长周期任务。
3.4 存储计算分离模式
在云环境中,推荐把各类暂态数据(如 session)、 结构化和非结构化持久数据
都采用云服务来保存
,从而实现存储计算分离。
但仍然有一些状态如果保存到远端缓存,会造成交易性能的明显下降,
比如交易会话数据太大、需要不断根据上下文重新获取等,
这时可以考虑通过采用时间日志+快照(或检查点)
的方式,实现重启后快速增量恢复服务,减少不可用对业务的影响时长。
3.5 分布式事务模式
大颗粒度的业务需要访问多个微服务,必然带来分布式事务问题,否则数据就会出现不一致。架构师需要根据不同的场景选择合适的分布式事务模式
- (1) 传统采用XA模式,虽然具备很强的一致性,但是性能差。
- (2) 基于消息的最终一致性 (BASE) 通常有很高的性能,但是通用性有限。
- (3) TCC模式完全由应用层来控制事务,事务隔离性可控,也可以做到比较高效;但是对业务的侵入性非常强,设计开发维护等成本很高。
- (4) SAGA 模式与TCC模式的优缺点类似但没有try这个阶段,而是每个正向事务都对应一个补偿事务,也是开发维护成本高。
- (5) 开源项目 SEATA 的 AT 模式非常高性能且无代码开发工作量,且可以自动执行回滚操作,同时也存在一些使用场景限制。
4.6 可观测架构
可观测架构包括Logging、Tracing、Metrics
三个方面,
其中 Logging提供多个级别 (verbose/debug/warning/error/fatal) 的详细信息跟踪,由应用开发者主动提供;
Tracing提供一个请求从前端到后端的完整调用链路跟踪,对于分布式场景尤其有用;
Metrics则提供对系统量化的多维度度量。
3.7 事件驱动架构
事件驱动架构 (EDA,Event Driven Architecture) 本质上是一种应用/组件间的集成架构模式。
事件和传统的消息不同,事件具有 schema, 所以可以校验 event的有效性,同时EDA具备QoS 保障机制,也能够对事件处理失败进行响应。事件驱动架构不仅用于(微)服务解耦,还可应用于下面的场景中。
- (1) 增强服务韧性:由于服务间是异步集成的,也就是下游的任何处理失败甚至宕机都不会被上游感知,自然也就不会对上游带来影响。
- (2) CQRS(Command Query Responsibility Segregation): 把对服务状态有影响的命令用事件来发起,而对服务状态没有影响的查询才使用同步调用的API 接口;结合EDA 中的 Event Sourcing机制可以用于维护数据变更的一致性,当需要重新构建服务状态时,把EDA 中的事件重新“播放”一遍即可。
- (3) 数据变化通知:在服务架构下,往往一个服务中的数据发生变化,另外的服务会感兴趣,比如用户订单完成后,积分服务、信用服务等都需要得到事件通知并更新用户积分和信用等级。
- (4) 构建开放式接口:在EDA 下,事件的提供者并不用关心有哪些订阅者,不像服务调用的场景——数据的产生者需要知道数据的消费者在哪里并调用它,因此保持了接口的开放性。
- (5) 事件流处理:应用于大量事件流(而非离散事件)的数据分析场景,典型应用是基于Kafka 的日志处理。
- (6) 基于事件触发的响应:在 IoT时代大量传感器产生的数据,不会像人机交互一样需要等待处理结果的返回,天然适合用EDA来构建数据处理应用。
四、云原生架构反模式
庞大的单体应用
单体应用硬拆为微服务
缺乏自动化能力的微服务
五、云原生架构技术
5.1 容器技术
Docker, K8S
容器编排K8S
Kubernetes 已经成为容器编排的事实标准,被广泛用于自动部署,扩展和管理容器化应用。
Kubernetes 提供了分布式应用管理的核心能力。
- 资源调度:根据应用请求的资源量CPU、Memory, 或者GPU等设备资源,在集群中选择合适的节点来运行应用。
- 应用部署与管理:支持应用的自动发布与应用的回滚,以及与应用相关的配置的管理;也可以自动化存储卷的编排,让存储卷与容器应用的生命周期相关联。
- 自动修复: Kubernetes能监测这个集群中所有的宿主机,当宿主机或者OS出现故障,节点健康检查会自动进行应用迁移;K8S也支持应用的自愈,极大简化了运维管理的复杂性。
- 服务发现与负载均衡:通过Service资源出现各种应用服务,结合D N S和多种负载均衡机制,支持容器化应用之间的相互通信。
- 弹性伸缩: K8s可以监测业务上所承担的负载,如果这个业务本身的CPU利用率过高,或者响应时间过长,它可以对这个业务进行自动扩容。Kubernetes 的控制平面包含四个主要的组件: APIServer、Controller、Scheduler 以及 etcd。
- 声明式API: 开发者可以关注于应用自身,而非系统执行细节。比如Deployment (无状态应用)、 StatefulSet (有状态应用)、 Job (任务类应用)等不同资源类型,提供了对不同类型工作负载的抽象;对Kubernetes实现而言,基于声明式API的 “level-triggered”实现比 “edge-triggered” 方式可以提供更加健壮的分布式系统实现。
- 可扩展性架构:所有K8s组件都是基于一致的、开放的API实现和交互;三方开发者也可通过CRD(Custom Resource Definition)/Operator等方法提供领域相关的扩展实现,极大提升了K8s的能力。
- 可移植性: K8s通过一系列抽象如Load Balance Service (负载均衡服务)、 CNI (容器网络接口)、 CSI (容器存储接口),帮助业务应用可以屏蔽底层基础设施的实现差异,实现容器灵活迁移的设计目标。
5.2 云原生微服务
设计约束:
- 1)微服务个体约束 - 服务拆分、单一职责、高内聚低耦合、独立性
- 2)微服务间的横向关系 - 服务注册发现、客户端负载均衡、限流熔断等
- 3)微服务与数据层之间的纵向约束 - 零共享架构
- 4)全局视角下的微服务分布式约束 - 自动化CI/CD、可观测、蓝绿/金丝雀发布等
主要技术:阿里Apache Dubbo、Spring Cloud、Eclipse MicroProfile、腾讯Tars、蚂蚁金服SOFAStack、微软DAPR
5.3 无服务器技术
BaaS(Backend as Service)
随着以Kubernetes 为代表的云原生技术成为云计算的容器界面, Kubernetes成为云计算的新一代操作系统。面向特定领域的后端云服务 (BaaS) 则是这个操作系统上的服务API, 存储、数据库、中间件、大数据、 AI等
领域的大量产品与技术都开始提供全托管的云形态服务,如今越来越多用户已习惯使用云服务,而不是自己搭建存储系统、部署数据库软件。
FaaS(Function as Service)
通过把应用逻辑拆分多个函数,每个函数都通过事件驱动的方式触发执行,例如,当对象存储 (OSS)
中产生的上传/删除对象等事件,能够自动、可靠地触发 FaaS 函数处理且每个环节都是弹性和高可用的,客户能够快速实现大规模数据的实时并行处理。同样,通过消息中间件和函数计算的集成,客户可以快速实现大规模消息的实时处理。
目前函数计算这种 Serverless 形态在普及方面仍存在一定困难,例如:
- (1) 函数编程以事件驱动方式执行,这在应用架构、开发习惯方面,以及研发交付流程上都会有比较大的改变;
- (2) 函数编程的生态仍不够成熟,应用开发者和企业内部的研发流程需要重新适配;
- (3) 细颗粒度的函数运行也引发了新技术挑战,比如冷启动会导致应用响应延迟,按需建立数据库连接成本高等。
容器作为载体
针对这些情况,在 Serverless计算中又诞生出更多其他形式的服务形态,典型的就是和容器技术进行融合创新,通过良好的可移植性,容器化的应用能够无差别地运行在开发机、自建机房以及公有云环境中;基于容器工具链能够加快解决 Serverless 的交付。
- 云厂商如阿里云提供了弹性容器实例 (ECI) 以及更上层的 Serverless 应用引擎 (SAE),
- Google 提供了CloudRun服务,这都帮助用户专注于容器化应用构建,而无需关心基础设施的管理成本。
- 此外 Google 也开源了基于 Kubernetes 的 Serverless应用框架Knative。
相对函数计算的编程模式,这类Serverless应用服务支持容器镜像作为载体,无需修改即可部署在 Serverless环境中,可以享受Serverless带来的全托管免运维、自动弹性伸缩、按量计费等优势。
Serverless计算包含以下特征:
- (1)全托管的计算服务
- (2)通用性,集合云BasSAPI的能力,能够支撑云上所有重要类型的应用
- (3)自动弹性伸缩
- (4)按量计费
5.4 服务网格
服务网格 (ServiceMesh) 是分布式应用在微服务软件架构之上发展起来的新技术,旨在将那些微服务间的连接、安全、流量控制和可观测等通用功能下沉为平台基础设施,实现应用与平台基础设施的解耦。这个解耦意味着开发者无需关注微服务相关治理问题而聚焦于业务逻辑本身,提升应用开发效率并加速业务探索和创新。换句话说,因为大量非功能性从业务进程剥离到另外进程中,服务网格以无侵入的方式实现了应用轻量化。
主要技术:Istio(envoy、xDS)、Linked(linkerd-proxy)、Consul、Conduit