第14章 云原生架构设计理论与实践

我们的目的是啥,最大程度的复用资源,这样提升效率和生产力,降本增效啊,云原生的是在云上的,基于云的环境和软件,这样复用程度更高了,而且云上还有一些很牛的价值比如云计算等等。

14.1 云原生架构产生背景

Cloud Native。Cloud 指软件都是在云端而非传统数据中心。 Native代表应用软件一开始就是基于云环境、专门为云端特性设计,可充分利用和发挥云平台的优势(如弹性+分布式)。
发展历程:
瀑布式流程--->敏捷开发--->DevOps。
烟筒模式:各自为政,各部门有自己的应用和数据,甚至一个部门多个系统的数据都没办法共享,部门间交互就更费劲了。
瀑布式流程:开发关心相应速度,运营关心系统可靠与安全性,业务关心更多特性给用户,
一方面造成了开发上下游的信息不对称,一方面拉长了开发周期和调整难度。
敏捷开发只是解决了软件开发的效率和版本更新的速度,还没有和运维打通。出于协调开发和运维的“信息对称”问题,开发者又推出了一套新的方法——DevOps,DevOps可以看作是开发、技术运营和质量保障三者的交集,促进之间的沟通、协作与整合,从而提高开发周期和效率。而云原生的
容器、微服务等技术正是为DevOps提供了很好的前提条件,保证IT软件开发实现DevOps开
发和持续交付的关键应用。

14.2 云原生架构内涵

14.2.1 云原生架构定义

定义不唯一。

从技术的角度,云原生架构是基于云原生技术的一组架构原则和设计模式的集合,旨在将
云应用中的非业务代码部分进行最大化的剥离,从而让云设施接管应用中原有的大量非功能特
性(如弹性、韧性、安全、可观测性、灰度等),使业务不再有非功能性业务中断困扰的同时,
具备轻量、敏捷、高度自动化的特点。
基础设施即服务(IaaS)、平台即服务(PaaS)和软件即服务(SaaS)。
云原生的代码通常包括三部分:业务代码、三方软件、处理非功能特性的代码。
  • "业务代码”指实现业务逻辑的代码;
  • “三方软件”是业务代码中依赖的所有三方库,包括业务库和基础库;
  • “处理非功能性的代码”指实现高可用、安全、可观测性等非功能性能力的代码。
三部分中只有业务代码是核心,是对业务真正带来价值的,另外两个部分都只算附属物,但是,随
着软件规模的增大、业务模块规模变大、部署环境增多、分布式复杂性增强,使得今天的软件构建变得越来越复杂,对开发人员的技能要求也越来越高。
云原生架构相比较传统架构进了一大步,从业务代码中剥离大量非功能性特性(不会是所有,比如易用性还不能剥离)到IaaS和PaaS中,从而减少业务代码开发人员的技术关注范围,通过云厂商的专业性提升应用的非功能性能力。
1.代码结构发生巨大变化

目前的开发基本都需要考虑文件、网络、线程等等这些元素,这样可充分利用单机资源的好长,但同时也带来了分布式编程的复杂性,大量的问题都涌现出来(分布式环境种网络调用问题、高可用问题、CPU争用问题、分布式存储等等)。

在云环境种这些就考虑的元素升级成服务,在需要的直接调用即可。

2.非功能性特性大量委托

开发的时候,还有考虑一些非功能特性,比如相应时间,容灾能力,安全性,易于运维等等,这些在开发的时候需要加上大量代码来实现。

在云环境中,这些非功能特性尽最大限度的剥离,让云环境承载这些,开发只需要专注业务代码。

3.高度自动化的软件交付

软件开发完成需要部署,单个服务器的很容易,但是集群的这种有成千上万的节点的部署起来就很痛苦,而且先部署哪些,后部署哪些都是有顺序的,云环境提供自动化部署策略,自动部署,按照设定的规则部署等等。

14.2.2 云原生架构原则

云原生架构作为一种架构 ,也是遵循一些架构原则的。

1.服务化原则

当代码规模超出小团队的合作范围时,就有必要进行服务化拆分了,包括拆分为微服务架构、小服务(MiniService)架构,通过服务化架构把不同生命周期的模块分离出来,分别进行业务迭代,避免迭代频繁模块被慢速模块拖慢,从而加快整体的进度和稳定性。同时服务化架构以面向接口编程,服务内部的功能高度内聚,模块间通过公共功能模块的提取增加软件的复用程度。
分布式环境下的限流降级、熔断隔仓、灰度、反压、零信任安全等,本质上都是基于服务流量(而非网络流量)的控制策略,所以云原生架构强调使用服务化的目的还在于从架构层面抽象化业务模块之间的关系,标准化服务流量的传输,从而帮助业务模块进行基于服务流量的策略控制和治理,不管这些服务是基于什么语言开发的。
2.弹性原则

弹性则是指系统的部署规模可以随着业务量的变化而自动伸缩,无须根据事先的容量规划准备固定的硬件和软件资源。
比如,集群访问量上来的时候,增加节点即可,访问量下去的时候,关闭闲置节点即可。
3.可观测原则

单机软件可调试调试所有功能,根据日志打印、数据变化等等各种手段很简单的分析出问题原因影响了哪些数据等等,但是在云上分布式环境下需要对多个主机的信息关联才能明确问题原因,影响了哪些数据哪些用户等等,这时候就需要系统具备更强大的可观测能力了(这些都要求系统具备更强的可观测能力。可观测性与监控、业务探活、APM等系统提供的能力)。

比如主动通过日志、链路跟踪和度量等手段,使得一次点击背后的多次服务调用的耗时、返回值和参数都清晰可见,甚至可以下钻到每次三方软件调用、SQL请求、节点拓扑、网络响应等,

4.韧性原则

韧性代表了当软件所依赖的软硬件组件出现各种异常时,软件表现出来的抵御能力,这些异常通常包括硬件故障、硬件资源瓶颈(如CPU/网卡带宽耗尽)、业务流量超出软件设计能力、影响机房工作的故障和灾难、软件bug、黑客攻击等对业务不可用带来致命影响的因素。
韧性从多个维度诠释了软件持续提供业务服务的能力,核心目标是提升软件的平均无故障时间(Mean Time Between Failure,MTBF)。
从架构设计上,韧性包括服务异步化能力、重试/限流/降级/熔断/反压、主从模式、集群模式、AZ内的高可用、单元化、跨region容灾、异地多活容灾等。
5.所有过程自动化原则

大量使用第三方组件,降低分布式复杂性和提升迭代速度的同时,因为整体增大了软件技术栈的复杂度和组件规模,所以不可避免地带来了软件交付的复杂性。

通过IaC(Infrastructure as Code)、GitOps、OAM(Open Application Model)、Kubernetes
Operator和大量自动化交付工具在CI/CD流水线中的实践,一方面标准化企业内部的软件交付
过程,另一方面在标准化的基础上进行自动化,通过配置数据自描述和面向终态的交付过程,
让自动化工具理解交付目标和环境差异,实现整个软件交付和运维的自动化。
6.零信任原则
默认情况下不应该信任网络内部和外部的任何人/设备/系统,需要基于认证和授权重构访问控制的信任基础,诸如IP地址、主机、地理位置、所处网络等均不能作为可信的凭证。
7.架构持续演进原则
能持续演化的能力。

14.2.3 主要架构模式

云原生架构有很多模式,以下是主要有价值的。

1.服务化架构模式

这是标准的云原生架构模式。要求以应用模块为颗粒度划分一个软件,以接口契约(如IDL)定义批次业务关系,以标准协议(如HTTP、gRPC等)确保彼此的互联互通结合DDD(领域模型驱动)、TDD(测试驱动开发)、容器化部署提升每个接口的代码质量和迭代速度。

典型模式:微服务和小服务模式。

小服务:一组关系密切的服务的组合,这组服务共享数据。适用于非常大型的软件系统,避免接口颗粒度太细导致过多的调用损耗和治理复杂度。

意义:

1.通过服务化架构,把代码模块关系和部署关系进行分离,每个接口可以部署不同数量的实例,单独扩缩容,从而使得整体的部署更经济。

2.由于在进程级实现了模块的分离,每个接口可单独升级从而提升了整体的迭代效率。

需要匹配的能力:因为拆分导致要维护的模块数量增多,需要自动化能力和治理能力。

2. Mesh化架构模式

Mesh化架构是把中间件框架(如RPC、缓存、一部消息等)从业务进程中分离,让中间件SDK与业务代码进一步解耦,从而使中间件升级对业务进程没什么影响。

分离后,业务进程只保留clinet部分,它只负责与Mesh通信,原来的流量控制、全等逻辑也由Mesh进程完成。当然实施了Mesh化后,大量分布式架构模式(熔断、限流、降级、重试、反压、隔仓....)都由Mesh进程完成,业务代码没第三方的软件包(主要是中间件);同时安全性(比如零信任框架能力)、按流量进行动态环境隔离、基于流量做冒烟/回归测试等等。

3.Serverless模式

Serverless将“部署”这个动作从运维中“收走”,使开发者不用关心应用运行地点、操作系统、网络配置、CPU性能等,从架构抽象上看,当业务流量到来/业务事件发生时,云会启动或调度一个已启动的业务进程进行处理,处理完成后云自动会关闭/调度业务进程,等待下一次触发,也就是把应用的整个运行都委托给云。
Serverless并非适用任何类型的应用,因此架构决策者需要关心应用类型是否适合于Serverless运算。
  • 如果应用是有状态的,由于Serverless的调度不会帮助应用做状态同步,因此云在进行调度时可能导致上下文丢失;
  • 如果应用是长时间后台运行的密集型计算任务,会无法发挥Serverless的优势;
  • 如果应用涉及频繁的外部I/O(网络或者存储,以及服务间调用),也因为繁重的I/O负担、时延大而不适合。
Serverless非常适合于 事件驱动的数据计算任务、计算时间短的请求/响应应用、没有复杂相互调用的长周期任务。

4.存储计算分离模式

C(一致性)、A(可用性)、P(分区容错性)

分布式环境中的CAP困难主要是针对有状态应用,因为无状态应用不存在C(一致性)这个维度,因此可以获得很好的A(可用性)和P(分区容错性),因而获得更好的弹性。在云环境中,推荐把各类暂态数据(如session)、结构化和非结构化持久数据都采用云服务来保存,从而实现存储计算分离
但仍然有一些状态如果保存到远端缓存,会造成交易性能的明显下降,比如交易会话数据太大、需要不断根据上下文重新获取等,这时可以考虑通过采用时间 日志+快照(或检查点)的方式,实现重启后快速增量恢复服务,减少不可用对业务的影响时长。

5.分布式事务模式

微服务模式提倡每个服务使用私有的数据源,而不是像单体这样共享数据源,但往往大颗粒度的业务需要访问多个微服务,必然带来分布式事务问题,否则数据就会出现不一致。架构师需要根据不同的场景选择合适的分布式事务模式。
  • (1)传统采用XA模式,虽然具备很强的一致性,但是性能差。
  • (2)基于消息的最终一致性(BASE)通常有很高的性能,但是通用性有限。
  • (3)TCC模式完全由应用层来控制事务,事务隔离性可控,也可以做到比较高效;但是对业务的侵入性非常强,设计开发维护等成本很高。
  • (4)SAGA模式与TCC模式的优缺点类似但没有try这个阶段,而是每个正向事务都对应一个补偿事务,也是开发维护成本高。
  • (5)开源项目SEATA的AT模式非常高性能且无代码开发工作量,且可以自动执行回滚操作,同时也存在一些使用场景限制。

6.可观测架构

可观测架构包括Logging、Tracing、Metrics三个方面:
  • 其中Logging提供多个级别(verbose/debug/warning/error/fatal)的详细信息跟踪,由应用开发者主动提供;
  • Tracing提供一个请求从前端到后端的完整调用链路跟踪,对于分布式场景尤其有用;
  • Metrics则提供对系统量化的多维度度量。
架构决策者需要选择合适的、支持可观测的开源框架(比如Open Tracing、Open Telemetry等),并规范上下文的可观测数据规范(例如方法名、用户信息、地理位置、请求参数等),规划这些可观测数据在哪些服务和技术组件中传播,利用日志和tracing信息中的spanid/traceid,确保进行分布式链路分析时有足够的信息进行快速关联分析。
由于建立可观测性的主要目标是对服务SLO(Service Level Objective)进行度量,从而
化SLA,因此架构设计上需要为各个组件定义清晰的SLO,包括并发度、耗时、可用时长、容
量等。

7.事件驱动架构

事件驱动架构(EDA,Event Driven Architecture)本质上是一种应用/组件间的集成架构模式

事件和传统的消息不同:
事件具有schema,所以可以校验event的有效性,同时EDA具备QoS保障机制,也能够对事件处理失败进行响应。事件驱动架构不仅用于(微)服务解耦, 还可应用于下面的场景中:
  • (1)增强服务韧性:由于服务间是异步集成的,也就是下游的任何处理失败甚至宕机都不会被上游感知,自然也就不会对上游带来影响。
  • (2)CQRS(Command Query Responsibility Segregation):把对服务状态有影响的命令用事件来发起,而对服务状态没有影响的查询才使用同步调用的API接口;结合EDA中的EventSourcing机制可以用于维护数据变更的一致性,当需要重新构建服务状态时,把EDA中的事件重新“播放”一遍即可。
  • (3)数据变化通知:在服务架构下,往往一个服务中的数据发生变化,另外的服务会感兴趣,比如用户订单完成后,积分服务、信用服务等都需要得到事件通知并更新用户积分和信用等级。
  • (4)构建开放式接口:在EDA下,事件的提供者并不用关心有哪些订阅者,不像服务调用的场景——数据的产生者需要知道数据的消费者在哪里并调用它,因此保持了接口的开放性。
  • (5)事件流处理:应用于大量事件流(而非离散事件)的数据分析场景,典型应用是基于Kafka的日志处理。
适应场景:
基于事件触发的响应:在IoT时代大量传感器产生的数据,不会像人机交互一样需要等待处理结果的返回,天然适合用EDA来构建数据处理应用。

14.2.4 典型的云原生架构反模式

企业做云原生架构演进的时候需要充分考虑不同场景选择不同技术,否则会适得其反,反例:

1.庞大的单体应用
庞大单体应用的最大问题在于缺乏依赖隔离,包括代码耦合带来的责任不清、模块间接口缺乏治理而带来变更影响扩散、不同模块间的开发进度和发布时间要求难以协调、一个子模块不稳定导致整个应用都变慢、扩容时只能整体扩容而不能对达到瓶颈的模块单独扩容等。因此当业务模块可能存在多人开发的时候,就需要考虑通过服务化进行一定的拆分,梳理聚合根,通过业务关系确定主要的服务模块以及这些模块的边界、清晰定义模块之间的接口,并让组织关系和架构关系匹配。
2.单体应用“硬拆”为微服务

服务的拆分需要适度,过分服务化拆分反而会导致新架构与组织能力的不匹配,让架构升级得不到技术红利,典型的例子包括:
  • (1)小规模软件的服务拆分:软件规模不大,团队人数也少,但是为了微服务化,强行把耦合度高、代码量少的模块进行服务化拆分,一次性的发布需要拆分为多个模块分开发布和维护。
  • (2)数据依赖:服务虽然拆分为多个,但是这些服务的数据是紧密耦合的,于是让这些服务共享数据库,导致数据的变化往往被扇出到多个服务中,造成服务间数据依赖。
  • (3)性能降低:当耦合性很强的模块被拆分为多个微服务后,原来的本地调用变成了分布式调用,从而让响应时间变大了上千倍,导致整个服务链路性能急剧下降。
3.缺乏自动化能力的微服务
软件架构中非常重要的一个维度就是处理软件复杂度问题,一旦问题规模提升了很多,那就必须重新考虑与之适应的新方案。在很多软件组织中,开发、测试和运维的工作单位都是以进程为单位,比如把整个用户管理作为一个单独的模块进行打包、发布和运行;而进行了微服 务拆分后,这个用户管理模块可能被分为用户信息管理、基本信息管理、积分管理、订单管理等多个模块,由于仍然是每个模块分别打包、发布和运行,开发、测试和运维人员的人均负责模块数就会直线上升,造成了人均工作量增大,也就增加了软件的开发成本。

14.3 云原生架构相关技术

14.3.1 容器技术

1.容器技术的背景与价值
容器作为标准化软件单元,它将应用及其所有依赖项打包,使应用不再受环境限制,在不同计算环境间快速、可靠地运行。容器部署模式与其他模式的比较如图14-3所示。
容器技术简单理解:把软件运行需要的依赖的各种资源(比如依赖的包)全部和软件一起打包放在一起,这样软件犹如运行在一个独立的环境中,此外容器不仅仅是把依赖项和软件一起打包在一起,还提供了很多其他的功能,比如自动发布、自动伸缩扩展、资源调度、自动修复等等功能。
  
Kubernetes已经取代Docker成为事实上的容器技术标准。
   
   
容器技术获得了越发广泛的应用的同时,三个核心价值最受用户关注:
1.敏捷弹性可移植性容器技术提升企业IT架构敏捷性的同时,让业务迭代更加迅捷,为创新探索提供了坚实的技术保障。
比如疫情期间,教育、视频、公共健康等行业的在线化需求突现爆发性高速增长,很多企业通过容器技术适时把握了突如其来的业务快速增长机遇。据统计,使用容器技术可以获得3~10倍交付效率提升,这意味着企业可以更快速地迭代产品,更低成本进行业务试错。
在互联网时代,企业IT系统经常需要面对促销活动、突发事件等各种预期内外的爆发性流量增长,
  
2.通过容器技术,企业可以充分发挥云计算弹性优势,降低运维成本。一般而言,借助容器技术,企业可以通过部署密度提升和弹性降低50%计算成本。
以在线教育行业为例,面对疫情之下指数级增长的流量,教育信息化应用工具提供商希沃(Seewo)利用阿里云容器服务ACK和弹性容器实例ECI大大满足了快速扩容的迫切需求,为数十万名老师提供了良好的在线授课环境,帮助百万学生进行在线学习。
  
3.容器已经成为应用分发和交付的标准技术,将应用与底层运行环境进行解耦
Kubermetes成为资源调度和编排的标准,屏蔽了底层架构差异性,帮助应用平滑运行在不同基础设施上。CNCF云原生计算基金会推出了Kubernetes一致性认证,进一步保障了不同K8s实现的兼容性,这也让企业愿意采用容器技术来构建云时代应用基础设施。
2.容器编排
Kubernetes已经成为容器编排的事实标准,被广泛用于自动部署,扩展和管理容器化应用。
Kubernetes提供了分布式应用管理的核心能力。
  • ●资源调度:根据应用请求的资源量CPU、Memory,或者GPU等设备资源,在集群中选择合适的节点来运行应用。
  • ●应用部署与管理:支持应用的自动发布与应用的回滚,以及与应用相关的配置的管理;也可以自动化存储卷的编排,让存储卷与容器应用的生命周期相关联。
  • ●自动修复:Kubernetes能监测这个集群中所有的宿主机,当宿主机或者OS出现故障,节点健康检查会自动进行应用迁移;K8s也支持应用的自愈,极大简化了运维管理的复杂性。
  • ●服务发现与负载均衡:通过Service资源出现各种应用服务,结合DNS和多种负载均衡机制,支持容器化应用之间的相互通信。
  • ●弹性伸缩: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(容器存储接口),帮助业务应用可以屏蔽底层基础设施的实现差异,实现容器灵活迁移的设计目标。

14.3.2 云原生微服务

1.微服务发展背景

以前开发个后端应用,最直接的方式就是通过单一后端应用提供并集成所有服务,即单体模式。

可这有个问题,项目小,参与人少还可以,庞大复杂的项目,参与人众多的时候,这种方式在开发、测试、发布、沟通等效率严重下滑,由此微服务诞生了。

微服务是根据业务逻辑相对独立性,把单体应用拆分成一个个的子功能,这些子功能就是微服务。这样在开发、测试、发布等等各方面效率提升了,同样的一件事有好的方面也就有不好的方面,微服务面临的挑战:如何高效调用远程方法、如何实现可靠的系统容量预估、如何建立负载均衡体系、如何面向松耦合系统进行集成测试、如何面向大规模复杂关联应用的部署与运维。

现在是云原生大行其道的时候,微服务+云原生就形成了云原生微服务体系。利用云上的各种资源开发微服务功能,这样系统更好的保障、安全、稳定、可观测、可控制。。。。

2.微服务设计约束

相较于单体应用,微服务架构提升了开发、部署等环节灵活性,但是也增加了运维、监控环节的复杂性,为了设计出一个优秀的微服务系统,应遵循以下设计约束:

1)微服务个体约束

业务域划分应是相互独立的,这样不同业务域可选择不同的技术去实现。还有微服务也应具备正交分解特性,即SOLID原则中单一职责原则(Single Responsibility Principle,SRP)。

2)微服务与微服务之间的横向关系

划分好微服务间边界后,主要从微服务的可发现性可交互性处理服务间的横向关系。

可发现性:当服务A发布和扩容的时候,依赖服务A的服务B如何在不重新发布的情况下感知服务A的变化。

解决方式:引入第三方服务注册中心,来满足服务的可发现性。特别是大规模微服务集群,服务注册中心的推送和扩展能力尤为关键。

可交互性:服务A采用什么样的方式可以调用服务B。

解决方式:由于服务自治的约束,服务之间的调用需要采用与语言无关的远程调用协议,比如REST协议就满足,"与语言无关"和"标准化"两个重要因素;在高性能你场景下,基于IDL的二进制协议是更好的选择。

实践中大多没有达到HATEOAS启发式的REST调用,还是服务间事先约定来完成,为了进一步解耦,建立一个独立的元数据中心来存储服务的元数据信息,服务通过查询源数据中心来理解和发起服务。

面向失败设计的原则的重要性:
伴随着服务链路的不断变长,整个微服务系统也就变得越来越脆弱,此原则非常重要。
措施:
对于微服务应用个体,限流、熔断、隔仓、负载均衡等增强服务韧性的机制成为了标配。为进一步提升系统吞吐能力、充分利用好机器资源,可以通过协程、Rx模型、异步调用、反压等手段来实现。
3)微服务与数据层之间的纵向约束

  • 在微服务领域,提倡数据存储隔离(Data Storage Segregation,DSS)原则,即数据是微服务的私有资产,对于该数据的访问都必须通过当前微服务提供的API来访问。
  • 同时,出于性能考虑,通常采取读写分离 (CQRS)手段。
  • 同样,由于容器调度对底层设施稳定性的不可预知影响,微服务的设计应当尽量遵循无状态设计原则。
  • 对于有数据存取(即有状态)的微服务而言,通常使用计算与存储分离方式,将数据下沉到分布式存储,通过这个方式做到一定程度的无状态化。
4)全局视角下的微服务分布式约束
从微服务系统设计一开始,就需要考虑以下因素:高效运维整个系统,从技术上要准备全自动化的CICD流水线满足对开发效率的诉求,并在这个基础上支持蓝绿、金丝雀等不同发布策略,以满足对业务发布稳定性的诉求。面对复杂系统,全链路、实时和多维度的可观测能力成为标配。
为了及时、有效地防范各类运维风险,需要从微服务体系多种事件源汇聚并分析相关数据,然后在中心化的监控系统中进行多维度展现。伴随着微服务拆分的持续,故障发现时效性和根因精确性始终是开发运维人员的核心诉求。

3.主要微服务技术

1.Apache Dubbo作为源自阿里巴巴的一款开源高性能RPC框架,特性包括基于透明接口的RPC、智能负载均衡、自动服务注册和发现、可扩展性高、运行时流量路由与可视化的服务治理。

2.Spring Cloud作为开发者的主要微服务选择之一,为开发者提供了分布式系统需要的配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性Token、全局锁、决策竞选、分布式会话与集群状态管理等能力和开发工具。
3.Eclipse MicroProfile作为Java微服务开发的基础编程模型,它致力于定义企业Java微服务规范,MicroProfile提供指标、API文档、运行状况检查、容错与分布式跟踪等能力,使用它创建的云原生微服务可以自由地部署在任何地方,包括服务网格架构。
4.Tars是腾讯将其内部使用的微服务框架TAF(Total Application Framework)多年的实践成果总结而成的开源项目,在腾讯内部有上百个产品使用,服务内部数千名C++、Java、Golang、Node.Js与PHP开发者。Tars包含一整套开发框架与管理平台,兼顾多语言、易用性、高性能与服务治理,理念是让开发更聚焦业务逻辑,让运维更高效。
5.SOFAStack(Scalable Open Financial Architecture Stack)是由蚂蚁金服开源的一套用于快速构建金融级分布式架构的中间件,也是在金融场景里的最佳实践。MOSN是SOFAStack的组件,它一款采用Go语言开发的服务网格数据平面代理,功能和定位类似Envoy,旨在提供分布式、模块化、可观测、智能化的代理能力。MOSN支持Envoy和Istio的API,可以和Istio集成。
6.DAPR(Distributed Application Runtime,分布式应用运行时)是微软新推出的一种可移植的、无服务器的、事件驱动的运行时,它使开发人员可以轻松构建弹性,无状态和有状态微服务,这些服务运行在云和边缘上,并包含多种语言和开发框架。

14.3.3 无服务器技术

1.技术特点
随着以Kubernetes为代表的云原生技术成为云计算的容器界面,Kubernetes成为云计算的新一代操作系统。面向特定领域的后端云服务(BaaS)则是这个操作系统上的服务API,存储、数据库、中间件、大数据、AI等领域的大量产品与技术都开始提供全托管的云形态服务,如今越来越多用户已习惯使用云服务,而不是自己搭建存储系统、部署数据库软件。
   
当这些BaaS云服务日趋完善时,无服务器技术(Serverless)因为屏蔽了服务器的各种运维复杂度,让开发人员可以将更多精力用于业务逻辑设计与实现,而逐渐成为云原生主流技术之一。
    
理解:Kubernetes的普及,像存储、数据库、中间件、大数据等等大量的各种产品和技术依托云形态,用户已经习惯用云服务,不再自己搭建服务器、安装软件等等,当BaaS越来越完善,无服务器技术(Serverless)诞生了,它屏蔽了服务器的各种运维复杂度,让开发专注业务设计与实现,这也是云原生的主流技术之一。
   
Serverless计算包含特征:
(1)全托管的计算服务,客户只需要编写代码构建应用,无需关注同质化的、负担繁重的基于服务器等基础设施的开发、运维、安全、高可用等工作;
(2)通用性,结合云BaaSAPI的能力,能够支撑云上所有重要类型的应用;
(3)自动弹性伸缩,让用户无需为资源使用提前进行容量规划;
(4)按量计费,让企业使用成本得有效降低,无需为闲置资源付费。
  
Serverless最具代表性的产品形态:函数计算(Function as a Service,FaaS)
通过把应用逻辑拆分多个函数,每个函数都通过事件驱动的方式触发执行.
例如,当对象存储(OSS)中产生的上传/删除对象等事件,能够自动、可靠地触发FaaS函数处理且每个环节都是弹性和高可用的,客户能够快速实现大规模数据的实时并行处理。同样,通过消息中间件和函数计算的集成,客户可以快速实现大规模消息的实时处理。
  
目前,函数计算这种Serverless形态在普及方面存在的困难:
(1)函数编程以事件驱动方式执行,这在应用架构、开发习惯方面,以及研发交付流程上都会有比较大的改变;
(2)函数编程的生态仍不够成熟,应用开发者和企业内部的研发流程需要重新适配;
(3)细颗粒度的函数运行也引发了新技术挑战,比如冷启动会导致应用响应延迟,按需建立数据库连接成本高等。
  
因为这些困难暂时没有好的办法,换了一种思路:
把Serverless计算和容器技术结融合,通过良好的可移植性,容器化的应用能够无差别地运行在开发机、自建机房以及公有云环境中;基于容器工具链能够加快解决Serverless的交付。
如:阿里的 弹性容器实例(ECI)以及更上层的Serverless应用引擎(SAE),Google提供了CloudRun服务。
  
相对函数计算的编程模式,这类Serverless应用服务支持容器镜像作为载体,无需修改即可部署在Serverless环境中,可以享受Serverless带来的全托管免运维、自动弹性伸缩、按量计费等优势。
2.技术关注点
1)计算资源弹性调度
为了实现精准、实时的实例伸缩和放置,必须把应用负载的特征作为资源调度依据,使用“白盒”调度策略,由Serverless平台负责管理应用所需的计算资源。平台要能够识别应用特征,在负载快速上升时,及时扩容计算资源,保证应用性能稳定;在负载下降时,及时回收计算资源,加快资源在不同租户函数间的流转,提高数据中心利用率。因此更实时、更主动、更智能的弹性伸缩能力是函数计算服务获得良好用户体验的关键。通过计算资源的弹性调度,帮助用户完成指标收集、在线决策、离线分析、决策优化的闭环。在创建新实例时,系统需要判断如何将应用实例放置在下层计算节点上。
  
放置算法应当满足如下多方面的目标:
(1)容错:有多个实例时,将其分布在不同的计算节点可用区上,提高应用的可用性。
(2)资源利用率:
在不损失性能的前提下,将计算密集型、I/O密集型等应用调度到相同计算节点上,尽可能充分利用节点的计算、存储和网络资源。动态迁移不同节点上的碎片化实例,进行“碎片整理”,提高资源利用率。 --- 简单理解:把这些计算、I/O操作调度到别的闲置或者资源充足的节点上来执行,提高资源利用率。
(3)性能:例如复用启动过相同应用实例或函数的节点、利用缓存数据加速应用的启动时间。
(4)数据驱动:
除了在线调度,系统还将天、周或者更大时间范围的数据用于离线分析。
离线分析的目的是利用全量数据验证在线调度算法的效果,为参数调优提供依据,通过数据驱动的方式加快资源流转速度,提高集群整体资源利用率。
2)负载均衡和流控

资源调度服务是Serverless系统的关键链路。
为了支撑每秒近百万次的资源调度请求,系统需要对资源调度服务的负载进行分片横向扩展到多台机器上,避免单点瓶颈分片管理器通过监控整个集群的分片和服务器负载情况执行分片的迁移、分裂、合并操作,从而实现集群处理能力的横向扩展和负载均衡。在多租户环境下,流量隔离控制是保证服务质量的关键。由于用户是按实际使用的资源付费,因此计算资源要通过被不同用户的不同应用共享来降低系统成本。这就需要系统具备出色的隔离能力,避免应用相互干扰。
  
流量隔离:接口分组,例:没有汽车的年代,我们的道路很简单,就一条,行人、洋车都在上边走,随着车多了慢慢地有了高速、辅路、人行道等等。
  
分片的简单理解: 例如拿<任务分片>来解释

⼀个⼤的⾮常耗时的作业Job,⽐如:⼀次要处理⼀亿的数据,那这⼀亿的数据存储在数据库中,如果⽤⼀个作业节点处理⼀亿数据要很久,在互联⽹领域是不太能接受的,互联⽹领域更希望机器的增加去横向扩展处理能⼒。所以,ElasticJob可以把作业分为多个的task(每⼀个task就是⼀个任务分⽚),每⼀个task交给具体的⼀个机器实例去处理(⼀个机器实例是可以处理多个task的),但是具体每个task执⾏什么逻辑由我们⾃⼰来指定。比如有10台机器,每个task处理1000条记录。

3)安全性
Serverless计算平台的定位是通用计算服务,要能执行任意用户代码,因此安全是不可逾越的底线。系统应从权限管理、网络安全、数据安全、运行时安全等各个维度全面保障应用的安全性。

14.3.4 服务网格

前面我们说过云架构可以把大量非功能性特性剥离,让开发聚焦于业务代码,服务网格就是这些剥离的技术之一。

先说说面临的问题:

 1.治理难度大、技术门槛高

随着微服务实施水平的不断深化,除了基础的服务发现,配置中心和授权管理之外,在实施的过程中不可避免的需要在服务治理层面面临着各种新的挑战如分布式跟踪,熔断降级,灰度发布,故障切换等等治理需求。这些众多的非业务性需求,涉及到运维、运营管理层面,这使得整个项目在组织、分工、权责上变得交叉模糊,同时对相关人员提出了非常高的技术要求,然而我们开发的是业务程序,它的核心价值是业务逻辑的处理和实现,将越来越多的时间和精力花费在这些非业务功能上是非常不合理的。

2.多语言支持不足 

对于稍具规模的团队,多语言的技术栈和跨语言调用是常态,然而目前开源社区上并没有一套统一的跨语言的微服务技术,那些没有框架支持的语言编写的服务很难融入面向微服务的已有架构体系中,想因地制宜的用多种语言实现架构体系中的不同模块在现实开发中很难做到

3.代码侵入性强 

主流的微服务实现框架或多或少都对业务代码有一定的侵入性,比如Spring Cloud框架中几乎每个微服务都需要集成Eureka、Feign等组件,这些组件框架替换成本高,复杂项目依赖时的库版本兼容问题也非常棘手,同时,框架库的升级也无法对服务透明,服务会因为和业务无关的依赖库升级而被迫升级,我们希望的是尽量将负责服务间通信的这种非业务代码从业务功能代码中剥离出来

再来看看我们的解决方案:

1.Service Mesh架构思想

为解决上述微服务存在的问题,Service Mesh(服务网格)应运而生,它主要作为处理服务间通信的基础设施层,独立于具体的服务而存在,目的是从根本上解决了多语言支持不足以及代码侵入性的问题,并且凭借服务网格的独立性,使得业务团队不再需要关心复杂的服务治理工作,可以全权交给服务网格处理

  • 核心思想

服务网格的核心思想为Sidecar模式(边车模式)即将每个服务的负载、限流和服务发现等等通信功能和应用业务本身功能进行解耦分离,其负责服务间通信的部分称之为Sidecar代理,业务功能代码只和同机器下的不同进程的代理通信。如图2所示。

2.名称由来

由于每一个服务实例都会有一个Sidecar代理与之配对,服务之间的通信都是通Sidecar进行,在部署图表示为代理的交叉连接形成了一种网络网格,故称之为“服务网格”。目前所说的Service Mesh在若干服务的Sidercar代理基础上提供了统一集中式管理的运维入口即控制面平面, SideCar代理也称为数据平面 ,因此我们通常说Service Mesh由数据平台和控制平面组成,其结构如图3所示。

3.提供的功能
  • 服务发现和负载均衡: 服务网格可以自动管理服务实例的位置,并将请求路由到可用的实例,实现负载均衡。

  • 流量控制和超时处理: 通过服务网格,你可以设置流量控制策略,限制对某些服务的访问,并定义超时和重试机制。

  • 安全性和认证: 服务网格可以处理服务之间的安全通信,确保请求和响应的机密性和完整性。

  • 监控和跟踪: 服务网格可以收集有关请求和响应的数据,提供可观察性,帮助你分析和优化通信性能。

4.服务网格的组件和工作原理

服务网格通常由两个主要组件构成:

  • 数据面(Data Plane): 数据面处理实际的请求和响应流量。它位于服务之间,负责请求的路由、负载均衡、流量控制等。

  • 控制面(Control Plane): 控制面管理服务网格的配置和策略。它负责服务发现、路由规则、安全性设置等。

服务网格的工作原理:

客户端向服务网格发送请求。服务网格根据配置和策略,将请求路由到适当的服务实例。

服务实例处理请求并返回响应。服务网格可以收集有关请求和响应的数据,用于监控和跟踪。

5.服务网格的实现
  • Envoy: 由CNCF维护的高性能代理,支持负载均衡、流量控制、安全性等功能。

  • Istio: 基于Envoy的服务网格平台,提供丰富的策略配置和监控功能。

  • Linkerd: 轻量级服务网格,专注于简化通信和监控。

6.具体实例
Istio简介

- Istio是什么?

Service Mesh(服务网格)只是一种架构思想,主流的实现方案有Istio、Linkerd、Linkerd2、Consoul等等。其中Istio是目前最受欢迎且在实际生产中应用最为广泛的服务网格,它是由Google,IBM和Lyft这三家互联网巨头联合开发的一个基于服务网格的开源项目,功能丰富,成熟度高。下面将简单介绍Istio的框架及功能。

- Istio架构

Istio架构如下图所示,在逻辑上与Service Mesh框架思想保持一致,分为数据平面和控制平面两大部分,整体架构如图4所示。

①数据平面Data Plane

数据平面由一组以Sidecar方式部署的Envoy代理组成所有进入和流出服务的流量都会被Envoy拦截,并与控制平面进行交互,根据配置执行相应的通信功能

Envoy是用C++开发的高性能代理,Envoy代理作为唯一与数据平面流量交互的 Istio组件,相对于其他服务网格实现方案代理来说有着更丰富的治理能力和灵活的配置方式,并且支持各种插件可用于扩展流量治理能力,可生成遥测数据。

Envoy和Istio并不是强绑定关系,Envoy可以在其他框架中使用,Istio也可以采用其他代理。Envoy本身的内置功能有:负载均衡、TLS 终止、动态服务发现、HTTP/2&gRPC 代理,熔断器,健康检查,基于百分比流量拆分的分段推出,故障注入等。Envoy允许在不需要重新设计架构或重写代码条件下,启用或执行的一些Istio的功能和任务,比如:流量控制功能、网络弹性特性、安全性和身份认证特性基于WebAssembly的可插拔扩展模型等。

②控制平面

Istio的控制平面提供服务发现、配置和证书管理。由Pilot、Citadel、Galley三个组件整合成了一个单进程、多模块的istiod,极大的降低了部署的复杂度。在整个运行流程中,需要这些组件协同工作。

Pilot组件是控制面最重要的组件,负责提供服务发现、流量路由及服务治理功能,其架构如图5所示。

服务发现:Pilot通过插件的形式可以支持多种服务注册平台(K8s、Mesos等),通过平台适配器(Platform Adapter)将服务注册平台的服务数据填充为标准服务模型(Abstract Model),例如Pilot通过K8s适配器,将K8s中的Service及Pod实例等服务信息,转换为标准模型供Pilot使用。Pilot在得到统一的服务信息后,将服务信息通过Envoy API下发到数据面Envoy代理,实现服务发现功能。

流量路由及服务治理:运维人员可以通过Rules API指定各种高级流量管理规则(Gateway、VirtualService等),这些规则将被转换为数据面Envoy可以识别的格式,通过Envoy API下发给Envoy,Envoy在得到这些规则后,按照规则进行流量转发及安全认证

Gally是负责配置的验证和处理的组件,从底层平台获取配置,验证配置信息的格式和内容的正确性,并将这些配置信息提供给Pilot使用。

Citadel 是与安全相关的组件,主要负责密钥和证书的管理,可以实现强大的授权和认证等功能。

Istio总结:

任何一种方案都很难做到一劳永逸,Istio只是把原来分散在应用内部的复杂性统一抽象出来放到了统一的地方,且Istio的架构相对复杂,在具体生产中,必须做好清楚的规划,权衡它带来的好处是否远大于额外维护它的花费,选择合适的架构方案。

7.传统微服务调用和服务网格服务调用

8.总结

微服务架构的复杂通信问题可以通过服务网格得到解决。服务网格提供了一种管理、简化和增强微服务通信的方式,通过数据面和控制面的结构,实现负载均衡、流量控制、安全性和可观察性。在构建和维护微服务架构时,考虑使用服务网格来应对通信挑战,将有助于提高系统的稳定性和性能。

​​​​​​​

14.4 云原生架构案例分析---看看即可

14.4.1某旅行公司云原生改造

14.4.2云原生技术助力某汽车公司数字化转型实践

14.4.3某快递公司核心业务系统云原生改造

14.4.4某电商业务云原生改造

14.4.5某体育用品公司基于云原生架构的业务中台构建

站在巨人的肩膀上:

服务网格技术浅析-51CTO.COM

https://author.baidu.com/home?from=bjh_article&app_id=1695948768434894

  • 48
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

辣香牛肉面

感谢有缘之人的馈赠

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值