微服务及其发展趋势
云原生与微服务
不同组织对云原生的定义都不同,对于 privatol 公司,他们认为微服务至少具备如下特性:
微服务 形式
容器化 运行
CICD 交付
DevOps 组织文化
而 CNCF 对于云原生的定义则是:
微服务
服务网格:主要指新一代微服务治理体系
声明式 API
不可变基础设施
容器化
无论是哪个版本对云原生定义,都强调了微服务。它具备哪些特性,为什么在现代化应用的构建中,微服务如此重要?
微服务的前身是由单体应用延伸而来的。在单体应用中,它把应用程序的所有功能都构建在一个应用程序当中,并且不同的功能表现为不同的模块。后来单体应用发展到分布式概念,演化为可构建多个分布式应用。而微服务则是在传统的分布式微应用之上,进一步发展到极致的分布式。这可理解为应用程序的每个独立的小功能都做成独立的小程序,这就是分布式微服务发展到某个极致阶段后的结果。
实际上,分布式并非新概念。
分布式的概念实际上由来已久,只不过微服务时代对于分布式应用的强调特征较之过去传统的分布式有着不同的表现。为什么应用程序必然从单体,走向分布式,甚至是微服务,需要从康定定律说起。
康威定律
Melvin Conway 是一位计算机科学家,他在 1968 年提出了著名的"Conway's Law"(康威定律),表达了组织结构与其产出的设计之间的关系。康威定律如此描述:
"Any organization that designs a system (defined more broadly here than just information systems) will inevitably produce a design whose structure is a copy of the organization's communication structure."
“设计系统的任何组织,最终产生的设计结构都会复制该组织的沟通结构。”
也就是说,组织出来的系统,将反映出他们自己的沟通结构。
目前被引申为四条定律:
组织设计的产品,等价于组织的沟通结构;
罗马并非一天建成的,学会先解决首要问题;
时间再充裕,也不可能将一件事情做完美,但总有时间做完一件事情;
忽略次要的需求,“先完成,再完善”;
mvp 法则:最小可行性原则。无论是创业也罢,开发产品也罢,可以先打造其最为核心的功能,甚至界面也不用美观,先投放到市场验证是否可行。因为可能我们当初设想的需求和用户期望的需求完全不匹配,天壤之别。前期投入合适的成本,比事先砸入过多成本而后推翻前期的所有付出要有效和可行多得多。
线性系统和线性组织架构间有潜在的异质同态特性;
创立独立的子系统,减少沟通成本;
一个人通过原生的方式,自己精力直接管理的人是有限的。通常一个小的管辖范围内,一个人在同一个层级范围内直接管理其他人,7 个最优。最多一般而言不超过 50 个人。自然组织当中也不会超过 50 个,比如猴群或群落性的组织,如果其沟通方式通过原生的比如发声沟通,一般不会超过 50 个,因为这是自然触达边界的限制。
“线性子系统”,或“分布式子系统”对应着不同的产品结构
线性子系统是一体化的,统一的单体系统。而分布式子系统的沟通结构是在一个小团队内的,完成的。线性系统对应的产品结构,是把一个系统划分为前端团队,后端团队和 DBA 团队,最重要的产品形态表现为 UI,MIddleware 和 DBA。
早期很多系统都表现为这种单体的系统。
如果划分为前端团队、后端开发团队和 DBA 团队的组织,其最终产品形态通常表现如下:
随后,分布式子系统所构建出来的结构是基于业务边界划分为的,每个小团队都有前端,中间件和 dba。每个组织都是一个完整的职能设定,但是这个组织要小得多,他是一个独立的完整体系的产品团队。如果基于业务边界划分为多个小团队的组织,各团队按照业务目标去构建小的系统或产品,其最终产品形态如下:
这些团队之间是需要的协作,分布式应用产品和产品之间存在外向型的耦合关系,它们之间该如何协作? 这就需要统一的管理权限的人确保在设计产品应用时,其接口遵循某种契约或约定。如此双方开发的应用才能完全协同,也就是说开发需要遵循接口契约。
分布式应用的小团队按照自己的业务目标或产品,这里的每个小产品都可独立演进,按照各自的节奏交付产品,彼此间按照网络通信进行协同。服务端监听在某个套接字,能对外提供服务,这个套接字是提供 API 对外调用的远程调用接口,比如基于 rest 或 rpc,在服务之间调用,并确保被调用服务的调用接口能够满足调用者所需的功能,并且前者提供的接口和支持传输的协议是双方共同支持的,因此需要契约。
演进中,较之小系统,大系统具有更强的分解倾向。
线性子系统对应着不同的产品结构,应该把大的组织系统切分为小的组织系统,让其内部正常可自行进行独立迭代和演进。并且,大系统具有更强的分解倾向。
康威定律在著名公司的体现:
amazon:早期时等级分明的树状体系,因此他们的系统也会表现成这个样子
google:表现为网状的沟通结构,不过依然是等级分明
facebook:真正意义上的网状结构,更符合其社交属性
microsoft:内部构建竞争属性的产品,以赛马的形式决定哪个胜出而最终存活下来
apple:中心化组织,早期的所有产品需求基本都围绕着乔布斯实现
oracle:法务部和工程部相比较而言,表现为两种组织。法务部非常赚钱,通过打官司作为公司盈利的重要手段
这就是康威定律在多个 IT 公司所表现的属性,这也大体表现出他们的产品属性之上,附加并表现为产品特性和产品组织特性。
随着云的发展,各种团队都试图将自己的单体应用,在当今敏捷需求和业务模型之下,拆分为微服务。
如何拆分微服务
一般按三个维度拆分微服务:
X 轴扩展:多个相同实例之间实现请求的负载均衡,这是扩展单体应用程序的常用方法,横向扩展。从一个实例,扩充为多个实例,以实现水平扩展。在微服务时代,每个微应用也需要支持。
提升吞吐量
提高可用性
注意:这对于无状态应用而言容易管理,而有状态应用则限制很多。比如保证 session 保持的机制,会话粘性,session replicaiton,session server,这无非是把有状态应用的状态信息存储到外部组件当中,以确保负载均衡被调度的组件是无状态的。
Y 轴扩展:微服务化。基于功能将应用拆分为多个子应用(服务),这是一种功能性分解机制;也可业务边界拆分
每个服务时一个小的应用程序,它实现了一组相关的功能
服务也可以在需要时借助 X 轴或 Y 轴进行扩展
本质上是分布式系统
注意:根据业务功能的边界把有限几个拥有紧密关系的功能放在一起,关联度不紧密的拆分开来,这种操作逻辑就是微服务化的拆分机制。不过微服务化的粒度该有多大呢?是每个功能都该独立,还是具有紧密关联关系的几个功能放置在一个应用当中同时提供呢?这取决于组织内部的管理逻辑和技术能力,没有一个统一的标准。
Z 轴扩展:目标是根据请求的某个属性路由请求,通常也需要运行单体应用程序的多个实例,但每个实例仅负责数据的一个子集
例如,应用程序可能会使用请求标头中包含 userID 来路由请求
后端多个程序实例各自仅负责处理指定范围内的用户请求
将数据集划分为多个子集,通过前端路由的方式把大的需求同时并行分发到多个同时运行的子系统之上所实现的拆分机制,这需要请求路由的功能。
这是一种功能性分解机制,对应着 MySQL 的分区分表。
小结
随着业务规模的扩展,将单个大应用扩展成多个实例运行以实现负载均衡。但是,单个实例会超出单台服务器的资源边界,此时将大应用拆分为多个小应用,根据功能边界或根据业务功能拆分。比如电商的首页独立出来, 搜索功能,库存功能等都独立出来,实现功能边界的拆分。功能之间彼此独立,通过服务接口相互调用。这实际上就是微服务化的一种表现。
如果库存应用程序无法承载库存搜索的压力时,比如大量的数据集放在一起搜索可能对性能产生影响。因此,可将数据分散存放以提高性能。比如,将一个搜索应用再一次拆分,把搜索功能面向的数据集划分为多个不同的子集。我们可以把访问日志根据应用和生成时间的不同,每天生成一个 index,随后当某些搜索可能围绕着一天的或者有限几天的数据集之上的,如此限制某些操作只面向过去累计下来的业务数据的子集。
上述的垂直拆分,就是微服务化;而路由拆分,就相当于把数据集拆分为多个子集,根据拆分的键和用户请求的标准实现路由请求的标准。这就是一个应用进行拆分时通常遵循的几种维度。
现在的微服务体系一般是三个方向结合起来使用的。一个应用,基于功能的维度,拆分为多个微服务;当某个服务对应的后端的数据过大,则基于 z 轴的方式通过路由逻辑将计算需求分布到多个不同的实例上。每个实例同时运行多个副本的方式来扩展。
如果强调微服务,基于业务边界的垂直拆分更算得上是一种 MSA 架构。
MSA 架构
微服务如何体现“微”的特性?
体积小:微小的甚至不超过 100 行代码
开发周期短:必须在两周内完成开发或迭代
…
Netflix 的架构师 Adrian Cockcroft 认为,微服务架构是面向服务的架构,它们由松耦合和具有边界上下文的元素组成;
而世界知名的软件大师 Chris Richardson 在“Microservices Patterns”一书中,通过一种三维扩展模型的“扩展立方体”给出了不一样的定义:
把应用程序功能性分解为一组服务的架构风格,每一个服务都是由一组专注的、内聚的功能职责组成;
微服务的大小并不重要,更好的目标是将精心设计的服务定义为能够由小团队开发的服务,并且将会时间最短,与其它团队协作最少;
微服务架构应用程序通过一些小的、松耦合的服务组织在一起,从而提升开发效率、可维护性、可测试性和可部署性;
微服务架构与单体架构最显著的区别在于,单体应用程序只是单个应用程序,而微服务则是许多小的应用程序协同工作:
服务和服务之间基于服务发现总线发现彼此,通过管理总线去管理服务的协同,配置等和各种韧性等功能参数的设定。为了接入客户端请求,并分发到服务之上,或者把本身不具备服务发现的客户端,统一起来以让请求接入。此时 API-Gateway 负责把用户请求,根据请求的目标服务,通过服务总线发现出目标服务,并把请求传递到服务端。因此 API-Gateway 有两重作用:
作为网关为客户端提供统一入口
为客户端提供服务,并且客户端不具备服务发现的情况下,把客户端请求的服务基于内部的服务发现总线找到他们。
因此必然依赖 API-Gateway 组件,否则需要把客户端做成智能的并且对接到服务发现总线上,显然不太现实。
小结
微服务的好处:
每个应用都可独立迭代了
代码复杂度降低,且容易维护了。
如果基于单体模式开发,一个应用程序在三年五年维护下来后,内部可能堆积大量模块,它们之间有着非常复杂的依赖关系,内部模块可能是小组各自维护和开发的,久而久之会形成,自己内部的程序文档都无法描述出谁和谁有调度关系,因此整个应用程序的开发和维护非常麻烦和困难,以至于后续新人来接手应用架构时,需要消耗大量时间去搞明白,更遑论快速迭代和开发了。
为了避免这种问题的出现,微服务化后每个服务都是独立实体,各自独立迭代。不过调用关系依然存在的。过去时在单体内部的调用关系,如今外化了。此时开发人员无需维护调用关系,仅需知道自己调用服务的名称和基本功能。所以开发人员只需要集中精力开发自己的应用,并且知道有哪些被依赖的服务即可。
这些调用关系本身的维护和组织就可以畅通无阻运行,只要保证每个被调用者都存在。
因此,从单体走向微服务的变化是,早期运维工程师从维护一个或几个单体应用,转变为维护一大堆复杂的应用及其调用关系了。实际上问题并没有消失,不过从研发团队转移到运维团队,不过运维团队也无法承载,因此借助容器编排系统和服务发现总线来使其得以落地。
在没有服务发现总线时,要调用哪个服务一般是写死在配置文件中的。
服务注册总线确保服务之间可相互发现和调用,而调用拓扑还需要确保维护出来。而后调用关系需要 SRE 人员确保链路是畅通的。这种外化还带来一个问题:某个被调服务出现故障,可能导致前一个服务被反压,进而导致级联故障。因此最好服务和服务之间基于异步通信的方式,并且,服务和服务之间的调用关系也无需显性外化的方式维护,每个组件的工作功能通过一个又一个独立的事件去驱动的。只要某个事情发现了,根据事情发生本身和上下文来决定,后面应该执行的操作。这种机制称为事件驱动的架构:EDA。
如此每个应用只需要接收和响应事件就可以了 。如果没有事件的发生, 就不用管。
如此维护好事件驱动的拓扑图,将调用关系转化为一个又一个的消息中间件的 broker 或 channel,而 broker 能做好路由,被外化的复杂关系的维护就变成有限几个消息总线的维护了。在 broker 定义好路由逻辑即可,这就是事件驱动架构。
通俗来说,从过去需要明确定义 API 接口的调用方法和接口文档,转变为无需暴露 API,仅定义好内部事件的消息格式即可。
现代的分布式系统要求云原生系统走向事件驱动的逻辑。一般来说,在微服务架构中,可以同时使用这两种架构:API 网关处理对外部的同步请求,而内部服务之间通过事件进行异步通信。
微服务架构的好处与弊端
好处:
使大型的复杂应用程序可以持续交付和持续部署
每个服务都相对较小且容易维护
服务可以独立部署
服务可以独立扩展
微服务架构可以实现团队的自治
更容易实验和采纳新技术
更好的容错机制
弊端:
服务的拆分是一项挑战
分布式系统带来的各种复杂性,使得开发、测试和部署变得更困难
跨服务的事务可能需要 Saga 来维护服务间的数据一致性,同时还要使用 API 组合获 CORS 视图实现跨服务查询
依赖高度自动化的基础设施
自动化部署工具,例如 Netflix Spinnaker
产品化的 PaaS 平台
Docker 容器编排平台,例如 Kubernetes
服务间通信存在不同程度的延迟
当部署跨越多个服务的功能时需要谨慎地协调更多的团队
开发者需要思考到底应该在应用的什么阶段使用微服务架构
微服务面临的架构挑战
运维成本增高:服务越小,独立性更好,但是相应的服务数量越多。每个服务都需要独立配置、部署、监控、日志搜集等,成本呈指数增长。
异步性:微服务经常使用异步编程、消息队列及并行处理,如果要求一个操作必须是同步且具有事务性,就需要管理好相关联服务及分布式事务操作的复杂性
分布式系统复杂性:作为一种分布式系统、微服务引入了复杂性、入网络延迟、容错性、消息序列化等一系列问题
必要 DevOps 能力:基于微服务架构的应用,与其运行环境紧密关联,需要开发团队及运维团队无缝协作才能保障此类应用的成功开发和运行
测试困难:无论手工还是自动测试、通常都很难一致性的方式重现微服务应用环境
依赖管理复杂:当把传统的系统拆分成多个相互协作的独立服务后,随着服务数量的增多,如何清洗明了的展示服务间的依赖关系逐渐成为挑战
何时引入微服务
何时从单体走向微服务?随着业务复杂程度和团队规模的增加,业务的沟通成本必然会成倍增加。如果继续采用单体系统,那么效能就会呈现急剧下降趋势。而微服务的生产能力,随着业务系统的增加,基本能保持线性。对于较大规模的系统,显然更适用于微服务体系。
二者之间存在交点,如果纵轴作为生产力,横轴理解为复杂程度,则认为在二者交点左侧,单体具有较低的复杂性和较高的生产力;而右侧是单体具有较高的复杂性和较低的生产能力, 而微服务反而复杂性较低,生产能力较高。
这个交点就是提示着,随着规模的增加和团队规模的提升,生产效能急剧下降。此时,就该考虑引入微服务了。
遵循的路径一般如下:
单体优先
刚刚创立的公司或者组织,使用单体进行开发模式,复杂程度较低,人才技能要求较低,生产效率较高,此时采用单体。只有单体效能遇到边界时,才转为微服务体系。而不是刚刚创业,构建一个应用时就考虑微服务架构,这对组织的成本带来巨大规模的挑战 。
中台战略和微服务
业务前台(应用)
业务中台(核心业务层)
技术中台(PaaS 云平台/IaaS 云平台)
微服务总体技术架构
对于微服务架构的分层和分解机制,把整体的微服务架构分成如下:
基础设施层:IaaS 及其提供的基础能力
平台服务:功能性特征
支撑服务:功能性特征,和微服务治理有更大的关系,注册发现等
业务层:聚合服务和基础服务两部分,比如前端和业务服务的部分,比如用户管理,支持,电商、搜索,这些功能都需要使用用户的能力,将它聚合起来,谁需要就去调用,这就是服务化的一种需求
网关层:负责鉴权、服务发现和服务调用、卸载 tls 等
接入层:外部+内部 LB
微服务技术趋势
一、以阿里云产品为例的模型架构:微服务架构分层逐渐形成
后端 BaaS 化:当用户需要运行容器时,将其定义为声明式配置,提交给 BaaS 就可以自动跑起来了。
客户端轻量化:主容器+sidecar
业务侧 Serverless 化:面向客户端的 pod 都是无状态的,而且可能基于函数编程,让业务聚焦于业务本身,提升研发效率的
二、微服务技术标准逐步形成
Istio/Envoy 成为服务网格控制平面和数据平面的事实技术标准
微服务竞争进入深水区,服务网格、服务治理、分布式事务、零信任会成为差异化竞争力
三、数据平面 SidecarProxy 与 Proxyless 模式的融合
Sidecar Proxy 的发展推动了数据平面的标准化,目前 gRPC 已经支持 xDS 协议
Dubbo 社区提供完善的 xDS 服务治理能力的支持,完成 sidecar proxy 与 proxyless 模式的融合
sidecar proxy 是新一代的,以 sidecar 方式治理的服务网格,而 proxyless 逐渐引起人们都关注 。因为前者在规模较大,压力较大时,有着不可忽视的性能损耗。因此 proxyless 引起关注。
基于 xds API,可以治理数据平面,目前有三种模式:
sidecar 方式运行为代理的模式
基于 grpc 融合到 dubbo 的模式
基于内核 eBPF 的 proxy 模式:后者看起来比前面性能更好,但是成熟到可用还有不短路程要走。
dubbo 和 spring-cloud 倡导的模式有 gRPC 和 JavaAgent,目前面向应用研发 为中心的角度而言,这依然是主流的解决方案。但是新一代的微服务治理体系,proxy 是新生微服务架构体系下人们最为关心的微服务治理体系。
有朝一日,proxy 可能被内核的 eBPF 取代进而走向第三种模式:在内核当中基于 eBPF 框架载入各种各样的 sidecar proxy 拥有的高级流量治理能力的模式。
四、服务治理数据面透明化,控制面标准化
服务治理数据平面将会逐步下沉,与业务逻辑逐步解耦,透明的实现治理技术的眼睛和升级
数据平面多种形态并存
Java 语言领域,以 Java Agent 为形态的 服务治理技术正在兴起并逐步成为趋势
针对非 Java 语言,基于 Sidecar 的 Service Mesh 技术正在被越来越多的企业采用
控制平面标准化
逐步统一到一 Kubernetes CRD 为中心的服务治理控制平面中
服务质量的范围扩展到以开发、测试、发布、运维、安全等多场景的全生命周期
五、云原生网关逐步成型
2020 年,有 37%的 Ingress 实现选择使用 Envoy(比 2019 年增加了 116%),大量公司基于 Envoy 构建下一代网关技术(引自 CNCF)
随着 Kubernetes 完成对 Ingress Gateway 的标准化,Ingress 作为容器、微服务的连接点,以 Isito 为控制平面向下聚合 Kubernetes、Nacos 多种服务,对上控制 Ingress(Edge)/Sidecar(Runtime)东西南北流量
随着 Ingress 将 Gateway 标准化,网关呈高集成发展趋势,云原生网关作为下一代网关将流量网关和业务网关合二为一
集成安全能力从入口建立安全防线
集成服务治理和可观测能力,从入口提高整个网站的高可用
支持单体应用,Nac、Kubernetes、Serveless 多种服务发现来源,统一接入,统一认证登录
版权声明: 本文为 InfoQ 作者【蝉翼2u】的原创文章。
原文链接:【http://xie.infoq.cn/article/491abb6a4b3adc52ff8c2af84】。文章转载请联系作者。
评论