开发者学堂课程【微服务全生命周期稳定性实践 :微服务全生命周期稳定性实践(一)】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/1205/detail/18172
微服务全生命周期稳定性实践
内容介绍
一、微服务架构演变
二、微服务稳定性实践
三、SOFA 微服务从开发到运维
今天分享的是微服务全生命周期稳定性实践,我们会从以下三个角度去切入,首先是微服务架构的演变。第二点是微服务稳定性的实践以及 sofa 微服务从开发到运维。我们会从整个微服务架构的演变,到最后会以 sofa 为例,介绍一下微服务到底应该怎么样从开发到运维在全生命周期中去保障它的稳定性。
一、微服务架构演变
第一部分是微服务架构的演变。在过去一些传统企业直到今天,他还在采取单体架构的模式,之前是一些在软件工程中间叫做瀑布流的一些开发的模式,单体架构就相当于把所有的大的应用系统中间所有的功能集中在某一个应用中,应用指的是一个进程,该进程部署在一台机器上,在它的周边会有包括 cdn ,反向代理服务,器负载均衡等等的一些包括分布式缓存以及其他的网站,服务器,数据库之类的。
某一个大的应用系统,它是承载所有的业务功能,它部署在一台服务器上,这种模式过去大家很熟悉它的优点和缺点,后来我们发现这种单体的模式在扩展性,在运维的难度各方面都不太适应业务的快速发展,此时会产生对业务的一个垂直的拆分,形成一个较早期的这种分布式的架构,这种分布式的架构实际上是对业务做一个垂直的拆分。
比如说在一个购物的流程中间,把购物车包括订单,这种不同的能够明确地拆开的一些业务,垂直的把它拆成不同的系统,对于不同的系统,它只承担整个大的应用系统中间的一部分,比较独立的职能。
但是拆分的力度相对来说比较粗的,此时会引入一些比较多的中间件包括消息队列的服务,或者是一些其他的能把这些不同的功能的这些应用串联起来的一些中间件,但拆分力度还是不够细,我们发现在迭代依然会存在为修改一个小小的功能,上线一个大的系统的情况,系统发布也会很久,为解决这一问题,推出面向服务的这种开发模式,叫做 soa 的架构。这在前几年包括现在都是一个非常热门的一个概念,甚至认为一些基于 RPC 的一些 soa 的架构,它甚至就是微服务的一个雏形,或者说跟微服务的理念基本都类似。当 soa 架构的出现的一开始是有一个 es b 的模式,它是把服务从这种业务的垂直拆分更加细粒度的划分成不同的服务,这些服务是能够承载比较紧耦合的一些业务功能。它的缺点是在于因为依赖 esb 的总线,所有的服务要通过走线来进行交互,服务总线很显然会成为整个系统的一个瓶颈。服务总线它能够承载多少的这种访问量,是否需要能够把服务拆的更细,就是一个完全面向服务的一个开发模式,把所有的服务全部都拆成这种原子的能够独立去运行的这种小的模块,小的功能,每一个都是一个独立的进程,每一个微服务都变成一个独立的进程,此时每一次去迭代的,都可以单独的把这一个进程重新进行一个更改或者迭代,此时迭代效率就会很高。更理想的状态是结合容器技术,在微服务架构之下是能够非常弹性的扩容。这里包含整个把一个大的业务应用,甚至说是业务应用系统,从非常庞杂,完全无从下手的状态,将他一点一点地拆分,然后变成每一个人都可以独立地去 owner 其中的一小块功能,他专注于自己这一块业务的开发会带来更小的迭代的风险。此时迭代就会变得更快,最后会面向敏捷,甚至到现在会有一种叫做 service mesh 的这种模式,后面就会发现开发会变得越来越敏捷,越来越快。业务迭代会变得越来越快。这是微服务的一个演变的过程。
是不是微服务的这种演变过程都是好的,其实也会带来一些烦恼。我们将从简单的单体架构到微服务来讨论一下他们中间到底有哪些优势和劣势。从最早的单体架构的这种应用系统,
我们认为它架构简单,是因为它架构从外面来看是真的很简单,因为它就是一个独立部署的一个应用,就可以承担整个应用系统和整个业务流程。
但是它内部是非常复杂的耦合的状态,当要去排查问题我们知道问题就在这一台机器上。但是问题是在这一台机器上面有许多的分支,有很多的业务逻辑,到底哪个逻辑出问题,就会变得很困扰。
举个例子,当系统有一个新人来接手的,要让它迭代一个功能,它首先要去解整个系统,在做什么,每一个模块是怎么样去互相串联的。他敢不敢下手改代码,可能改一行代码就会引起一系列的问题,拆东墙补西墙,这种事情会经常的发生。业务模块紧耦合是一个是比较严重的问题。因为它是一个单体的架构,所以部署和测试被认为是简单的,只需要部署这么一个应用系统,测试就只需要针对一个应用系统从头错到尾。但问题在于它严重地阻碍发布迭代的效率。因为每次想要修改一个很简单的功能,甚至说想要修改一行代码的 bug,就要把整个系统全部重新发布,因为系统太复杂,发布的时间会很长,部署的时间会很长也是一个问题。另外传统的运维认为单体应用简单,指的是说所有的问题都集中在这一台服务器上,我们不需要去不同的服务器上去找想要的信息,包括一些服务这些指标包括一些日志信息,只需要关注于某一台部署单体应用的机器。但问题在于因为他只有一台机器,或者说它都部署在一起,所以它难以做到扩缩容。因为一台整个的服务器是有很多资源的,他可以在不同的比如说对 CPU,对计算比较高消耗的一些业务流程中间,要让他用一些 CPU 性能比较好的一些机器,如果有一些业务流程,认为是吃内存甚至 io 的,会给他配一些这种 io 和内存会比较优秀这种机器,这本身是可以拆分的。但因为他在同一台机器上,他在一个应用上,没有把应用拆开,所以造成这种资源上的浪费。如果要扩内存,只能把整个机器的这种配置都升上去,然后其他的应用就其他的业务流程跟着一起,同一个应用,一起不上去,这是一种资源上的浪费。另外它是没有这种故障隔离的能力的,如果产生某一个模块,产生这种故障是只能要不就任由故障发展下去,不然就把整个的应用服务停掉。这种没有故障隔离的能力,现在看肯定是不能允许的。当发展到这种分布式的架构,就是把业务垂直拆分之后,缓解了一部分的迭代效率的问题,就是因为只要有解耦就能对这种迭代的效率做到一些缓解,另外一点是这种扩缩容以及资源浪费的问题,它因为有这种解耦,它能够做到一定的缓解。他也有这种有线的故障隔离能力,为什么说它是有限的,因为毕竟它只是按照业务去做垂直的拆分,还是不够犀利。但这里也有一个问题是它相比单体架构,它一定是调用复杂,另外因为根据业务去做的这种垂直拆分一开始会有一些重复造轮子的情况,因为难免有一些模块,它是不同的业务都要去依赖的。当然此时企业就会想到做一个类似于这种公共服务,此时也是架构在逐渐的演变的过程。等到 soa 这种面向服务的架构出现的,做到这种更细粒度的一个解耦,迭代的效率也提高不少,另外在扩缩容方面也是更加便捷,尤其是当基于这种容器的技术快速的发展,后面的微服务甚至做到这种无状态的弹性伸缩,另外在高可用方面,因为它是更细粒度的一个拆分。对不同的业务都能够对它的一个服务等级做一个有效的或者说是一个科学的定级,对不同级别的服务会有不同的保障手段,这方面提高了它的可用性。另外故障隔离或者后期想要对他做一些开关,这种操作都是可以很方便的进行,也是保障它的高可用。但是调用链就会相对之前就会变得更长,此时就会发现同事去排查问题的,他就会去不同的机器上需要去找日志,派送会变得复杂。另外在这种 esb 模式下,它是依赖总线的,eSB 它本身有没有瓶颈也是需要考虑的一个问题。再往后发展,当把微服务架构提出来,我们认为定义说微服务是一个承担单一职责的服务,更细粒度的解耦,继承前面所有的 soa 架构的所有的优点,它解决这种迭代效率的问题,它甚至会更便捷的去做这种自动化的扩容,如果微服务能够做到这种无状态,并且是基于容器去部署的,甚至可以做到自动化的扩缩容。另外故障隔离,限流熔断,这些的高可用的手段都可以用到。但是问题就是他调用关系会非常地复杂,甚至有一些较长的调用链,他经过几十个应用,甚至上百个应用,都是有的。再去排查问题的必须要依赖一些其他的工具,比如说这些分布式链路跟踪这种能够提高排查效率的工具,另外就是应用系统的管理会变得更为复杂,包括这种测试,发布和运维,测试在此过程中他不再针对眼前的某一个系统,而是会在全链路进行一个测试,然后需要去不同的应用寻找到底哪里有问题,它的测试力度会变得更细,上面会比之前会更为复杂一些。发布和运维也是一样。在微服务这种状态下上下一个大的业务,需要发布很多个服务,他的服务的发布一定是有一个顺序,以及一个相互的校验关系,发布也会变得更为复杂。运维为什么在这里会更为复杂就是在发现问题时要去排查的,需要费时间去不同的机器上去找一些日志。
二、微服务稳定性实践
微服务的稳定性实践,微服务的稳定性实践是基于以前的一些经验,在不同的行业监管方面会有不同的要求,大家也可以根据自己行业对监管的一些要求来做一些细节的调整,但是整体的方法论是是大差不差的,甚至说不光是在 sofa 稳定性实践是适用的,今天只是探讨一个整体的微服务稳定性实践的一个方案。
sre 叫做 site reliability engineer 就是网站可靠性工程师,为什么今天会提及 sre ,大家应该有了解过是谷歌提出的一个概念,它不只是一个岗位,他更是一种保障稳定性的一个策略和方法。不说运维,而是说 sre 是因为到已经上云的微服务的阶段。很多微服务的稳定性不能只靠运维团队来保障。而是说运维要联合开发,然后测试,包括一些比如说架构师,然后安全生产部门,然后应急值班的部门一起联合起来来保障微服务的稳定性。他们核心的目标,都是保障业务的连续性,核心的手段,或者说落地的一些方式就是这些角色要一起协同。在应用的全生命周期内去考虑高可用的方案,把运维做在日常,而不是说业务一上线,事情稳定性的事情全部都是运维的事情,传统上是行的通的,但在今天微服务的架构之下,这方面行不通。
怎么样在微服务的全生命周期中间去做好它的稳定性。比如说在架构设计阶段,把微服务的整个的上线过程粗浅地分为 5 个阶段,架构设计阶段,编码实现阶段,测试验证阶段,投产发布阶段以及最后的稳定运行阶段。
1、架构设计阶段
在此阶段,首先是要有一个合理的方案选型,应用设计的够合理,才能保障后面不会出现一些比较浅显的错误和稳定性的大问题,如何去考虑方案是否合理。一定是从需求出发,在整个微服务架构设计阶段,要做截藕以及说哪一些应该是仅有的流程,哪一些应该是拆分出来的,所有流程就把它揭露出来,还有一点是业务,哪一些是关键业务流程,哪一些是旁支业务流程,需要在设计之初考虑到这些问题,并且帮其把业务梳理出来,甚至在设计之初就可以根据业务的重要性,去对这种业务流程做一些定级。这里的方案选型包括微服务的中间件。这种同步调用 rpc 调用和队列的调用,甚至通过一些定时任务这种的驱动,或者一些事件的驱动来去触发,这里面包不包含一些分布式事物的问题,这些都是要在设计时就去考虑好的。
日志和监控方案的设计
日志和监控很多人认为永远不如业务重要,这是传统的观念,但是在今天认为要保障服务的稳定性监控和日志很重要。在日志和监控应该是在架构设计一开始就把它作为一个非常关键的点,考虑进去,当业务需要哪一些信息,应该在架构设计阶段就要把这些该埋点的点要提出来,要设计进去,要在这里打日志,日志要采取一种什么样的格式,日志要用统一的怎么样的编码,监控应该在哪些地方布点这里跟业务哪一些地方是关键流程有关,在架构设计阶段就应该定下来。另外一个就是极端情形下的一个应对方案的设计,这里更多的是一些高可用方案,比如当业务遇到一个洪峰,峰值分流量非常大的,有没有一些手段,比如说哪些业务是可以熔断的,有没有留一些业务的开关可以通过不发布,而是远程的这种动态配置的方式把有一些不太重要的业务,降级,让更重要的业务运行得更稳定,这些都是要在架构设计阶段去考虑的。编码实现的阶段是对架构设计阶段的提出的这些方案的一个落实,一定要严格地执行设计的方案和规范,良好的一个编码习惯是程序员的自我修养。另外就是要发挥团队的力量,要做这种科学的 code review,在今天来看对代码质量的保证是一个非常有效的手段。
2、测试验证的阶段
当架构演化成微服务架构时,它对于测试的要求比之前的传统的单体应用会更高,不但要关注业务的功能性是否正常,流程能不能运转下去。更重要的还要关注非功能性测试,尤其是中间件,包括上下游的链路,全链路的一个压力测试,业务能够预估到的系统能够承载的一个大概最高的容量峰值是多少,冲着峰值去摸高,需要看到说单排应用,或者说单组应用,能够成长多少的业务量,后面比如说一旦真实的这种流量峰值来时,可以根据它来做一些线性扩容,就不会陷于被动。另外需要去关注有依赖的剩下的中间件,它的容量有没有瓶颈比如一些一步的这种业务流程,中间依赖的消息对列,业务应用是顶住,然后消息队列本身作为一个能够有一定的这种削峰填谷能力的中间件,理论上它不会影响业务,但是当业务到一个非常高的峰值的,必须要考虑消息对列是不是容量能力是满足的。他需不需要去扩容,broker 够不够,消息一直堆积,对业务肯定也是非常不利的。这只是举一个例子,另外也要关注这些高可用方案是不是有效。测试阶段在已经把这些设计阶段的架构是给到高可用方案。在编码的落地之后测试的阶段,还是需要去验证一把,这些高可用的方案到底在这种极端的情况下能不能生效。
3、投产发布的阶段
投产发布的阶段,在过去就是点点鼠标,但是在有完整的 cd 的流程的情况下,就是还是点点鼠标,但是 cd 的流程自动化的流程,需要在里面要做很多事情的,首先投产的准入的检查你当前的业务,准备投产的业务测试报告是不是完备然后发布手册是不是准备好,甚至说上线之后的运维手册是否准备好,这些都要作为投产前的一个转入的检查,另外就是投产的环境的检查,比如说根据前面测试的情况,要承载多少的流量,要准备多少的机器,当前的环境是否已经准备好,准备部署。第三个是要严格执行投产计划,发布手册或者投产计划制定出来之后,要按照它上面的顺序什么时间点,然后先发布的一些应用,后发布哪些应用服务,都是要严格去执行的。另外最后一个阶段,在发布最后的阶段是要复查监控是否完备。前期在架构设计阶段已经设想好,要把监控布在哪些点,但是在最后投产之后,还是要再去检查一下,再去 check 到底是否真的这么做。
4、稳定运行的阶段
已经投产成功,稳定运行的阶段也是有很多工作要去做的。比如要去严格的执行变更监控,巡检和应急的规范。包括阿里提出像变更有三板斧,可灰度,可回滚,可监控,都是业界都已经比较有共识的一些方案,另外就是要熟练地使用一些常见的一些排障工具,尤其是像 java 的应用,对一些 GVM 自带的一些工具,是不是能够合理地去使用,然后用它去高效地协助去排查问题。另外会去做一些定期或者是不定期的应急演练来检查系统到底是不是能够应对这种突发的状况,然后需要从过去的一些故障和问题,以及应急演练中间积累的一些经验中,要不断的完善应急预案。因为有预案才能更加稳定。所以我们认为微服务的稳定性不光是在最后投产之后交给运维去保障。很多生产环境,一些稳定性的故障都是能够在前期做好。前期的工作把它避免掉,今天就希望能传达给一个概念,即尽量把稳定的工作往前提。甚至说在架构实施的架构设计阶段就已经要考虑进去,越早的去考虑这些事情,后面真正在遇到问题的就会更有把握。