1.3 微服务治理的范畴
1.3.1 微服务是一种研发模式
任何组织在设计一套系统(广义概念上的系统)时,所交付的设计方案在结构上都与该组织的沟通结构保持一致。
—康威定律
换个角度理解这句话,如果团队管理模式及工程管理模式和组织所采用的技术架构不匹配,就会延缓研发进度,降低研发效率及架构落地质量。
因此,微服务是一种研发模式,一旦企业决定采用微服务架构,就必须在组织架构、管理策略、研发模式、测试、运维等领域都做出相应的调整,为微服务架构的落地创造合适的“土壤”。本章后续几节将尝试从不同领域的视角来看待微服务架构所带来的冲击及领域治理的调整策略。
1.3.2 微服务的架构模式及治理
1.3.2.1 高内聚、低耦合
微服务的架构特点首先是“微”,即“小”,但究竟要多小才算“微”,其实没有定论和一成不变的评判标准。一般的看法是,根据业务的边界来确定服务的边界,只要符合领域驱动设计(Domain-Driven Design,DDD),专心完成一件不可再分割的完整业务操作功能,即可称为“微服务”,这也符合设计上的“单一职责原则”。
从微服务的单个实体角度看,一个微服务就是一个独立的部署包,或一个独立的操作系统进程。从微服务的整体集群角度看,服务和服务之间通过网络调用进行通信,调用双方遵循“服务接口契约”,即我们常说的服务API。所以对于一个服务来说,需要考虑的是什么应该暴露,什么应该隐藏。如果暴露过多,服务消费方会与服务的内部实现产生耦合,这就会使得服务和消费方之间产生额外的协调工作,降低服务的自洽性。
所以,从微观角度看架构,一个微服务一定是对内“高内聚”、对外“低耦合”的。
1.3.2.2 独享资源
微服务强调能够独立演进,互不影响(除了接口契约)。不像传统多个服务共享一个数据库,微服务架构中每个服务都有自己的数据库,这样才能保证松耦合。这种拆分获得的好处是,各个服务可以自由选择适合自己的数据库,如果需要复杂的查询操作,可以选择关系数据库;如果需要针对海量数据进行存储及检索,可以选择NoSQL数据库。此外,各个服务所对应的数据库不会相互影响。
拆分带来的坏处是,由于查询的需要,一些诸如字典表之类的基础数据可能需要冗余,在不同的库之间做复制。另外,事务的一致性保障变得复杂了,我们往往需要使用分布式事务来做最终一致性的保障,但分布式事务也不是“银弹”,它会增加微服务或者微服务框架的复杂度,降低处理效率。所以,为了获得微服务的好处,总是需要承受一些代价,在架构上做些取舍。
1.3.2.3 同构还是异构
微服务虽然功能单一,但这只是针对业务而言,如果考虑服务跨网络调用的协议暴露、负载均衡、限流、降级、熔断、监控等能力支持的话,整体功能还是非常复杂的。为了防止这些服务管控能力干扰业务功能的简单性,在微服务架构中,会把这些管控能力抽取到微服务支撑框架中,这一点和分布式服务框架是一致的。微服务框架分两种模式。一种是基于SDK的合设部署模式,如图1.20所示。SDK和微服务业务逻辑合设部署,共同跑在同一个进程中,在这种模式下,微服务和SDK所采用的开发语言必须是一致的,否则无法合设。另外一种采用新兴的SiteMesh的所谓边车(SideCar)机制,如图1.21所示。微服务和负责服务路由及管控的SideCar是两个独立运行的进程,双方借助基于网络层(三层)和传输层(四层)的操作系统本地环回网络进行通信,在这种模式下,SideCar对微服务而言就是一个全透明的“代理人”,微服务可以自主选择适合自己的开发语言和技术,不受SideCar所使用技术的影响。
图1.20 基于SDK的微服务框架
图1.21 基于边车模式的微服务框架
综上所述,如果采用基于SDK的微服务框架,一般建议统一技术框架;如果采用基于“边车”模式的微服务框架,则在技术选型上没有强制的需求(不排除许多公司试图避免混乱,只提供某些技术选择)。
1.3.2.4 架构治理
由于单个微服务的逻辑简单,从微观角度来看架构其实并不存在多大的问题。但从整个微服务集群来说,讨论架构这个事情就复杂了。微服务是一种自底向上的架构模式,在大的IT规划下,各个团队野蛮生长,到最后,没有一个人能说清楚整体架构是什么。这时候,架构上可能就会出现如下的一些隐患。
单点依赖:在网站的服务层中,各个服务的重要性各不相同,服务的相互调用会形成一张密集的“网”。在这张网中,一些通用的服务会被越来越多地调用,形成一个被密集调用的节点,这往往构成了微服务集群中的“单点风险”。这类服务一旦出问题,会导致服务应用出现大面积的故障,如图1.22所示,一旦图上的G点所对应的服务出现问题,所有业务请求都要“停摆”。所以,一方面对这一类“被依赖度”更高的服务,要设定更高的运维等级,在资源配置及日常维护上做重点关照;另一方面,要分析其是否被过度依赖,是否要在粒度上做更细化的拆分等。
图1.22 微服务调用网络示例
循环调用:如果服务A调用B,B调用C,C在特定条件下又调用A,这样A→B→C→A就形成了一个循环调用,如图1.23所示。这构成了线上的一个隐患,也许平时正常调用没有问题,可一旦在特定条件下,这种循环关系被触发,就会导致业务异常。而对于每个微服务而言,它只关心直接调用的服务,不关心也无力看到隔代调用。所以,在单个微服务节点上,是无法看到这种调用的不合理性的,只有通过梳理所有服务的整体调用关系,才可能发现这种风险点。
服务冗余:所谓服务冗余,可能是有些微服务不再被调用了,还可能是微服务的老版本,依赖它的其他应用或者服务已经消亡了,这些服务不会再被调用,这时需要将它们找出来,并清理下线,优化线上的资源配置。笔者所在公司会定期梳理不用的服务,并将其下线。
图1.23 微服务的循环调用
以上种种,都是架构腐化的表现。所以,在微服务架构下,需要对服务的整体架构进行不断优化。但要优化架构,首先要“看到”架构。面对成千上万的微服务节点,要做调用关系的梳理,靠人是不行的,要靠自动化。有两种典型的手段:
● 静态代码调用链路分析;
● 动态线上调用依赖关系分析。
找出关系还不够,还需要在调用关系上做依赖聚合,形成人能看懂的部署或者调用架构,以便分析。我们将在3.2节和6.1节中详细讲解如何做“微服务与微服务”之间的架构梳理及优化,在3.6节中详细介绍“微服务与资源”之间的架构梳理及优化。
1.3.3 研发治理
1.3.3.1 小团队、小工程
我们在1.2.3.1节中提到,技术映射到业务,当业务按产品线来划分时,研发团队也会被按产品线拆分。同样,当应用继续拆成更小粒度的服务、微服务的时候,研发团队也会从紧耦合的大团队被拆成松耦合联系的各个小团队,原来几个程序员负责一个应用或者服务的开发,拆到后面可能一个程序员就能负责几个微服务的开发。Amazon著名的“Two Pizza Team”理论(一个团队的所有成员用两张比萨就能养活)就是这种拆分的典范。而Netflix做得更彻底,在决定往微服务架构转型时,就直接从研发团队开始动手,拆分成多个独立的小团队,以保证开发出来的服务能独立演进,快速优化。
由于微服务是独立部署的,所以在项目工程的组织上,不同微服务之间要做好隔离,并独立打包。有些刚转型微服务的团队,可能会习惯性地采用大工程模式,构建一个工程,按一个文件夹一个模块的方式来组织微服务,然后通过CI服务的Pipeline构建策略来构建多个微服务的部署包,如图1.24所示。这种方式的后果是,所有团队的提交耦合在一起,每次提交都会导致构建,而针对大工程的构建是一个非常漫长的过程,这完全是不必要的效率浪费。
图1.24 共享工程模式
因此,比较推荐的微服务工程组织模式如图1.25所示:每个微服务都是独立的工程,独立组织,独立存放在代码库中,并且在CI服务中有独立的Pipeline专门负责其构建。这样,各个工程的提交不会影响各自的构建,构建及部署效率会更高。
图1.25 独立工程模式
在微服务模式下,团队隔离了,工程隔离了,CI构建流水线也隔离了,每个微服务都有了很大的空间来按自身的节奏进行自由演进。这种自由度一方面促进了快速迭代及灵活变更,另一方面,也挖了一个大大的“陷阱”,一旦滥用了这种自由度,往往会在代码质量、接口契约遵循上失控。所以,针对微服务的研发,同样需要治理。
1.3.3.2 工程及代码质量治理
一个微服务项目刚开始时,我们通常很谨慎,会精心地设计架构,会制定完备的设计规范和编码守则,团队成员也会尽可能遵守规则。项目推进顺利,过程规范,一切都是我们想要的模样。
随着业务的快速迭代,要不断地增加新功能和修改旧功能,时间紧、任务重。我们会经常面临选择:一种是临时方案,它不符合约定的设计规范和编码守则,从长远看也有些风险,但它能在短期内满足业务需求,最关键的是短时间内就可以完成;另一种是严格按照规程设计或修改,这种方案可能要修改底层架构,开发时间长,而且由于连带影响导致测试范围要扩大,测试成本也随之上升。怎么选?这是个问题!
面对进度压力,很多程序员会避重就轻,采用在当下看来最便捷的方案,保证快速上线,“先用临时方案顶一顶,等后续腾出手来再重构”。但实际情况是,需求源源不断,研发力量会很快投入新的开发中,只要临时方案没出问题,没有人顾得上去重构。就这样,项目中引入了一个又一个“临时方案”,这个微服务就这样“腐化”了……
我们虽然制定了各式各样的规范,甚至为程序员提供了很好的范例和代码模板,但这些并没有强制约束力,只能寄希望于程序员的主动性和自觉性。代码审核可以在相当程度上保证代码质量,但不能保证每个团队都会执行,也不能保证会覆盖到所有的代码。所以,随着时间的推移,我们往往丢掉了微服务的“微”这个初心。代码变得臃肿,逻辑上多了很多冗余,甚至在某个托底的逻辑分支中出现了某个代码失误。平时看不出来,可一旦某天这个逻辑分支被触发,悲剧就会出现了……
所以,对微服务的治理,不仅仅是针对线上微服务的治理,还需要对微服务项目的研发过程演变及代码质量进行治理。我们将在后续章节中详细介绍如何通过自动化的手段,对微服务工程代码的扫描来挖掘微服务的深层调用链路(与动态调用链路的分析有区别)及分析其合理性,并通过纵比的方式勾绘微服务的研发演变过程及评估代码质量的变化趋势。
1.3.3.3 接口契约治理
一个微服务需要以接口的形式将内部的功能暴露出去,微服务之间的调用需要遵循某种契约,防止服务提供方的随意变动导致服务调用方的异常。在微服务架构下,虽然团队之间的关系变得更松散了,但团队之间的正常沟通还是必需的,我们会在定期的交流中讨论并通报相关服务接口的变更情况。
实际上,一旦团队多了、规模大了,人与人的沟通协调往往不一定可靠,经常会发生服务的接口或者逻辑变更了,但负责的团队忘了通知相关调用方,直接导致线上出现故障的情况。这种情况很难通过纯管理手段来解决,毕竟只要有人的参与,就一定有主观性的判断。程序员在修改代码的时候,也许觉得自己并没有破坏接口逻辑,殊不知,其增加的某一行代码,会引发某个隐性的逻辑旁路。
所以,我们需要一种可靠的自动化手段,能够有效识别出线上大量的微服务是否依然遵循接口契约。“契约测试”可以有效地实现这点。我们将在第2章中详细介绍如何通过构建基于接口的“契约测试”能力,来针对微服务接口的有效性进行治理。
1.3.4 测试治理
1.3.4.1 单元测试及冒烟测试的挑战
假设一个新的业务,需要同时开发A、B、C这3个上下游微服务,调用关系为A→B→C,这3个微服务的开发团队在确定接口契约之后,各自进行所负责微服务的开发。理想情况下,应该是C服务最先被开发出来,这样B服务开发完随即就可以和C服务进行联调测试。同样,B服务的开发进度也要先于A服务,这样A服务才能在开发完之后,不耽搁和B服务的联调测试。
但现实往往不会这么理想,很有可能的情况是A服务先于B服务开发完,这样,A服务的负责团队就得等待,等待B服务完成开发并和C服务联调完才能与其进行联调测试,如图1.26所示。这样,研发效率因为服务之间的互相依赖一下就降低了。
图1.26 微服务的测试依赖
这时候,我们会采用一些打桩的方式来解决服务的依赖问题。比如B服务的开发团队可以在完成开发之后,构造一个C服务的stub,把它Mock掉,这样B服务就可以在C服务还没有完成开发的时候,直接进行内部调测,无须再等待。同样的做法也适用于A服务。以下就是一段基于mockito的典型Mock代码:
上述代码表示,当调用C服务的function1方法的时候,直接返回数值0.5。通过这种方式,可以有效地解除服务之间的耦合,让原来串行的开发模式变成并行的开发模式。但采用这种Mock方式,我们需要从头到尾梳理代码,再写一堆的Mock语句把远程服务全Mock掉。每次业务逻辑发生变化,我们均需同步修改Mock代码。如果依赖的服务上线了,还要把相应的Mock代码去掉。对测试代码的修改工作贯穿于整个开发过程,工作量很大,测试用例的复用率很低。
另外,传统的Mock方式无法模拟网络延时和网络错误导致的故障和异常,因此,使用它所获得的测试结果具有一定的局限性。
1.3.4.2 集成测试的挑战
以上是单元测试和冒烟测试会遇到的问题,如果进行端到端的集成测试,则会遇到一些新的问题。
要进行一个完整的端到端测试,必须确保整个微服务集群的调用链路中所有的主流程服务和依赖服务都部署到位,只要有任何一个微服务缺位,测试就无法进行。所以端到端测试对线上服务完备性的依赖很强。
测试成功,大家皆大欢喜。但如果失败,我们希望知道究竟失败在哪个微服务上,具体错误是什么,引起错误的原因是什么。这时,就无法让各个开发团队自由发挥了,必须协同一致,共同进行测试异常的排查,这种协作模式,完全违背了微服务松耦合的原则。
1.3.4.3 测试治理
所以,在微服务架构下,对服务进行测试是一件非常有挑战的事情。我们需要一些高效率和低成本的方式来构建针对微服务的测试能力。在6.2节中将详细阐述如何构建适合微服务架构的测试体系,以及针对这种测试体系的持续治理。
1.3.5 运维治理
1.3.5.1 微服务对传统运维的挑战
当我们从单个微服务节点来看微服务架构的时候,往往给我们一种错觉,觉得它很简单,架构简单、依赖简单、部署结构简单。可一旦微服务数量增加之后,复杂度就开始呈指数级上升,传统服务可能只有十几个、几十个服务,转型微服务后,会有几百个、上千个服务,每个微服务都有独立的数据库,可能还需要相对隔离的分布式缓存服务和消息服务,一个完整的微服务集群涉及的节点动辄成千上万,一些大型互联网公司的服务集群达到百万个也很常见。因此,微服务时代,在规模压力下,传统运维方式受到了前所未有的挑战。
规模上的压力是一方面,效率及可靠性的要求是另一方面,微服务之间还可能存在深度很长的调用依赖关系。图1.27是笔者之前负责业务的一个业务请求在内部的调用关系梳理,可以看到,请求从服务集群的第一个微服务被调用一直到数据进数据库,一共经过了6级层层调用。所以,在一个业务上线的时候,我们不仅要在短期内调配大量的服务节点上线,还需要对这些节点进行精细的编排,保证被依赖的服务或者资源能够优先被调度。
服务之间通过脆弱的网络进行通信,不出问题是不可能的,另外硬件故障、程序Bug、高并发、资源冲突等也都会导致远程调用故障。为了保障服务集群的高可用,运维人员必须能够在故障出现后,快速实现故障的定界定位,快速对故障点进行隔离、移除替换、限流、降级等操作,更进一步,甚至能做到基于线上监控数据分析,主动进行健康度检查,对故障提前预警,提前采取措施规避。
图1.27 某业务请求的调用关系梳理
1.3.5.2 自动化服务运维
传统运维的一大特点是围绕ITIL构建流程,强调的是基于人的标准化。进入大规模的微服务时代的运维,人的因素的比例被降低了,强调的是基于自动化的标准化操作。企业采用微服务架构,自动化运维是基本要求,针对微服务几十上百、甚至上千个节点实例的批量部署已经不是“人肉”方式能承受得了的,更别提还涉及在这一过程中由于依赖关系所导致的部署编排操作。
基于专家系统的自动化运维可以提供比人工方式更快速的响应速度。比如,我们可以设置一旦某个服务的调用出错率超过50%,自动把此服务节点隔离出服务集群,并把资源回收,同时部署一个新的服务节点加入服务集群替代旧节点;我们也可以设置,当QPS/TPS超过某一个阈值时,自动调配相当于现有线上服务节点数量20%的新节点加入服务集群进行扩容等操作。
目前普遍在PaaS平台上进行微服务的生命周期管理。PaaS服务有很多种选择,如果我们自己部署私有云,可以使用包括自顶向下规划的CloudFoundry,或者自底向上规划的Kubernetes、Swarm等来构建PaaS服务。除此之外,还有很多第三方公有云服务提供商提供的PaaS服务可用,这类PaaS服务都提供了一定的资源编排及调度功能,可以通过自动化的方式,根据预先定义的资源编排文件,进行批量的服务上下线、扩缩容等操作。将微服务的生命周期管理自动化能够有效提升稳定性,因为机器非常擅长做这类固化的、重复性强的操作,从而提高线上服务的整体稳定性和可控性。
除了微服务的生命周期管理要自动化,针对微服务的监控也要自动化。监控是运维的基础,而日志收集又是监控的基础。在微服务架构下,一个业务请求层层贯穿多个微服务,在任何一个微服务上观察到的只是这个业务请求的一部分,我们只有集合所有关联微服务节点上的相关日志,进行综合分析,才能勾画出这个业务请求的全貌,在此基础上,才能做全链路的故障定界定位、性能瓶颈分析、容量规划等。所以,从单个节点上增量地获取日志后,要把它发送到统一的日志中心,日志会进行从非结构化到结构化的解析、清洗、格式转换,以及数据(如性能指标)的聚合计算,再完整汇总调用链,自动构建分钟、小时、天等多个时间维度的报表,并入库存储,以供其他运维活动使用。以上描述的整个过程实现自动化后,就可以非常快速地获得从微观(单个微服务节点)到宏观(整个微服务集群)的运行状况。
实现了微服务的生命周期管理及线上监控自动化,运维人员就可以从重复枯燥的日常操作中解放出来,将更多的时间和精力投入运维自动化平台的建设中。让自动化运维能力以服务的形式暴露出来,进一步推动部署这类工作不断前移,让研发人员以自助的方式介入服务的“看”和“管”的操作,甚至直接和CI平台对接,实现研发人员直接构建、部署等一条龙操作,这就是所谓的DevOps。
1.3.5.3 智能化服务运维
在大部分情况下,自动化运维可以很好地应对微服务运维的需求。当服务出现故障(调用失败、抛出错误)或者出现故障征兆(处理延时变长、系统负载持续升高)时,自动化运维可以保证我们及时获得一份故障报告,做得好的话,甚至能通过专家系统将故障报告在专家库做匹配,基于服务预案直接做一些简单的故障自愈操作。但在一些复杂场景下,包括调用链故障根因分析、多因素故障止损、长期容量预测等方面自动化运维就无能为力了。这时候,基于AIOps的智能化服务运维就登场了。
早在2016年的时候,Gartner就提出了AIOps的概念,图1.28是Gartner对AIOps的概念定义图。我们可以看到,AIOps是在自动化的基础上,基于运维大数据(日志、监控指标、服务与应用信息等)及广义的人工智能算法,通过机器学习的方式来解决已知的问题和潜在的运维问题、并通过持续度量来不断进行优化的一种技术解决方案。
图1.28 AIOps的概念定义图(注:图来自Gartner)
因为AIOps不需要由人来指定规则,所以它不依赖于预定义的专家库,它能够基于机器学习算法自动从海量运维数据(包括运维事件日志及事件处理日志)中提炼规则。也就是说,它可以自主地构建专家库,在此基础上自动对事件进行匹配、分析,给出决策建议,并通过自动化运维操作将决策直接落地,从而构成一个无人干预的、全自动化的运维闭环体系。
当然,以上是AIOps的理想情况,目前由于算法的误差率无法完全消除,这种全自动的运维闭环体系没有办法全面推广,只能在一定范围内尝试。在很多情况下,AIOps只是给出辅助的运维决策,最终执行还是需要人工判别和干预。但不管怎么说,AIOps极大地改善了微服务架构体系下运维的窘境。
1.3.5.4 微服务的运维治理
线上服务的运维治理是微服务治理中最核心的部分,毕竟对技术团队而言,最重要的职责就是保证线上服务的稳定及可靠。由于微服务是从分布式服务演化而来的,所以1.2.3.3节中所描述的治理动作,在微服务治理中都是需要继承和进一步深化的。同时,在自动化和AIOps的支持下,对微服务的运维治理还有如下几方面的动作。
● 智能化故障分析:在微服务架构下,业务组网更加复杂,变更频繁、复杂路由、深度依赖带来的直接后果就是,我们每天都会在线上遇到之前没碰到过的问题。这时候,需要基于历史故障事件数据及事件处理数据,通过机器学习自动提取故障特征,生成故障特征库,再通过特征匹配,自动定位故障并提供决策建议。
● 智能决策:在复杂的运维场景下,基于机器学习的训练结果—决策特征库,根据线上服务的监控数据智能化地做出是否进行扩缩容、服务重启或者重新调度等决策。
● 资源优化分析:根据线上微服务的长期资源消耗监控指标(CPU、内存、I/O),自动对其进行分类,并通过优化部署调度策略,实现不同资源消耗类型的微服务的混部,以提高整体资源的利用率。
● 安全管控:由于微服务架构采用了更细粒度的分布式拆分,对于服务调用安全方面的问题更复杂,更需要重视,需要整体的系统化解决方案。将在4.6节的服务授权小节中对此做详细介绍。
1.3.6 管理治理
根据康威定律,组织和系统架构之间存在映射关系,有什么样的架构就需要有什么样的组织与其适配。微服务架构强调的是灵活快速,以保证技术能为业务提供及时的支持。笔者目前从事互联网金融工作,大的产品版本发布周期是两周一迭代,至于紧急运营需求和线上Bug修复等更是不计其数,导致每天都会有上线发布。传统的基于“需求设计→需求评审→概要设计→概要评审→详细设计→详细设计评审→开发→测试→发布评审→协同发布”的瀑布模式完全无法满足业务快速试错的需求。Scrum这类敏捷开发模式就很适合微服务架构下小团队、短周期的快速迭代。
1.3.6.1 敏捷:产品与研发高效协同的不二之选
采用敏捷模式,产品经理再不能以大而全的思路来设计产品需求,需要基于对用户和市场的研究,采用“用户故事(User Story)”的形式来组织需求。所谓的用户故事是从用户的角度描述用户渴望得到的功能。一个好的用户故事包括如下要素。
● 有价值:业务价值、技术价值均可,但一定要有价值,否则就是无用功。
● 小而独立:对应一个完整的简单功能。大的需求可以将大故事再提炼、分解成小故事。只有够小,才能在短周期迭代中完成。
● 工作量可评估:这是用户故事成熟度的标志,包括必须具备评估工作量的基本资料,一般要有原型,如果涉及前端,还需要有“高保”。
● 可确定优先级:需求总是有轻重缓急之分,业务要发展,一定要优先实现高价值、高优先级的需求。
一个基于敏捷的研发流程由如下步骤构成。
1)标注了优先级的“用户故事”首先进入产品Backlog库。
2)产品负责人通过需求宣讲会向研发团队详细讲解高优先级的用户故事,并解答相关疑问。
3)研发团队将用户需求分解成研发任务,评估各任务的工作量。再根据本轮迭代的可用人力资源确定进入本轮迭代的用户故事(需求)列表,按优先级排序,排不进的排入下一轮迭代。
4)研发团队进行开发,通过每日站会的方式同步项目进度信息。这个阶段必须完成产品的开发及测试。
5)召开迭代复审会议,由研发团队向产品负责人展示开发的产品,产品负责人进行验收和反馈。
6)在迭代最后召开迭代回顾会议,总结经验教训,并提出下一个迭代的优化(改进)策略。
以上步骤可以用图1.29形象地展示。敏捷缩小了产品需求和开发之间的隔阂,而且人人都是架构师—研发人员直接负责产品的架构设计,这些都有效地缩短了产品开发的周期,提高了效率。
图1.29 敏捷研发流程
但这还不够,研发团队开发出来的产品和服务还必须进行及时、充分的测试并部署到线上,让用户能平稳地使用。因此,研发人员和运维人员的衔接还必须足够顺畅,这就需要通过下一节即将介绍的DevOps来整合研发和运维了。
1.3.6.2 DevOps:研发、运维、质量一体化的必然选择
我们在1.3.5.2节中已经涉及DevOps,通过运维自动化可以将大部分运维人员对服务的“看”和“管”的能力让渡给开发人员,由开发人员直接负责服务的部署、运维和监控。但DevOps的范畴远不止这些,它还涉及软件或服务的质量(测试)领域。从概念上说,DevOps是一种方法论,是一组过程、方法与系统的统称,用于促进应用开发、应用运维和质量保障(QA)部门之间的沟通、协作与整合。简而言之,就是实现研发、运维、质量一体化。
具体到落地层面,DevOps最核心的工作就是构建标准化、规范化和自动化的研发流水线或工具链,实现计划、设计、开发、测试、发布和运维的紧密协同。它通常包括如下工作:
● 测试用例管理;
● 测试环境管理;
● 自动化持续构建(CI);
● 持续部署(CD);
● 发布管理;
● 负载测试;
● 应用系统监测;
● 反馈管理。
敏捷解决的是如何将需求快速地转换成软件产品的问题,而DevOps则解决软件产品的快速部署和灵活管理的问题,是敏捷的补充和延续。两者相结合就能够完整覆盖微服务的全生命周期管理,如图1.30所示。在实际应用中,由于部署构件及制品需要基于开发代码版本库进行构建,所以现在很多DevOps Pipeline产品往往也会覆盖开发阶段。
图1.30 基于敏捷及DevOps的微服务全生命周期管理
1.3.6.3 痛点及治理对策
敏捷流程中的迭代回顾会议会总结迭代中的不足并提出优化建议,这本身就是对敏捷管理的不断治理。但还存在如下不足:
● 由于敏捷周期较短,一次敏捷迭代看到的往往只是一个短周期内的问题和风险。对一些长期问题,包括代码腐化趋势和团队产出效能变化的监督无法及时到位。
● 迭代回顾会议更多的还是基于人的感觉来做判定,主观性因素比较多,缺乏科学的数据分析支持,而能够支撑决策的数据是需要长期积累的,一个迭代周期观察的数据显然不够。
在微服务架构下采用敏捷过程管理,传统的树形管理模式被打破,大量的权利被下沉到一线团队,设计由开发人员直接负责,监督管理变成了自管理。但这并不意味着没有管理,只要企业存在,对团队和员工的监督考核就一定不会消失。管理变得更“轻”的同时也变得更离散化了,这时候自动化的辅助管理支撑手段显得尤为重要。
所以,需要构建对敏捷管理的过程监控体系,包括对人(开发、测试)、事(User Story)、物(代码、可发布软件包)的监控,通过横跨多个敏捷迭代周期的数据的横比和纵比来进行更客观的度量和评估,如图1.31所示。
图1.31 敏捷系统过程的指标度量及效率监控
DevOps本身就包含了很多的治理思想和具体措施,包括应用系统监控、反馈管理等。一些DevOps产品还会集成团队协同管理能力,这些能力和在此基础上所做的持续改进等都是典型的治理动作。
我们将在后续的章节中详细介绍如何通过对开发过程、测试过程及线上服务的自动化监控及分析,并结合精益看板来进行开发人员和开发团队的开发质量、协同管理效率的综合立体化评估及治理。