正文如下:

公司在19年实现了业务系统的整体上云,合作的云厂商是腾讯云。当前系统上云也是主流互联网公司的趋势,使用各种云产品和服务也带来了*大的好处,有效的降低了成本,提高了运维部署的效率,提升了业务的可靠性。因此过了一年,大数据平台又从自建的机房,搬上了华为云,从此从单一云厂商也变成了多云厂商,公司的DevOps平台也需要去适应这种变化从而进行改造。

背景说明
这里对我们公司的devOps平台简单概述下:
DevOps平台概述
对于有一定规模的互联网公司,devOps平台是必不可少的。好处和优势就不多介绍了。

我们公司的devOps平台主要的系统有:
工单系统: 关于机器的申请,云产品的创建回收等等流程化的操作,都需要接入工单系统进行逐级的审批和自动化操作
发布系统:  对于一线业务开发人员在开发应用时,只需要提交代码,在发布系统新建一次变更,就可以自动将代码集成到对应环境的机器上。
cmdb和应用管理系统:对公司的机器资源以及应用资源进行管理
部署系统:能够给机器下发各种部署任务,完成软件的部署工作
各种域名DNS管理以及配置管理等。
当然还有其他系统
( 然而这些系统现在都是我一个人进行开发和维护  – – )

言归正传,回到今天需要描述的场景,如何在devOps平台上支持多云厂商云产品的管理。
以下描述都以机器申请的场景为例

单一云场景
在业务系统上腾讯云以后,业务方在新应用申请或是应用服务器扩容的场景,发起工单用于审核和服务器自动化扩容。

当时的技术实现,主要涉及到工单系统和资源管理系统的改造,工单负责流程的流转和审核,资源管理系统负责调用对应的云平台API进行对云资源的操作,从而做到系统间的解耦。由于系统来来回回负责开发的人员太多,我刚接手工单系统的时候,已经支持了腾讯云cvm的创建,但是所有的逻辑代码都放在了工单系统中,包括调用腾讯云平台API的实现。

在我前期熟悉代码的时候,遇到了以下问题:

代码的逻辑比较混乱,结构不清晰,代码注释较少,阅读理解起来比较复杂
代码的可扩展性不高,存在不少的if else代码来扩展实现,当场景多的时候代码量就过多
代码的可复用性不高,存在不少重复代码
起初我也对系统进行了改造,在资源管理系统中新增了调用腾讯云API的接口实现,希望能够先将系统解耦,将云资源在一个系统中进行统一管理。
然而这个时候,我开发接口的角度依然是对照腾讯云API的文档,基本是一个接口对应腾讯云的API的接口。
申请CVM的流程如下:

%title插图%num

工单通过审批,随后调用资源管理系统中的创建CVM接口,资源管理系统调用腾讯云平台接口创建CVM,返回申请的情况和实例的id列表。然而这个时候虽然腾讯云返回了实例id,但并不是说机器已经创建完成了,也可能在准备中,因此这个时候工单还需要定时任务查询机器状态是否在运行中,只有等所有的机器创建完成才说明这次机器申请完成,随后才能进行后续的部署操作.

这样看来整体的流程还算是清晰的。

随后过了一年,当大数据选择上华为云时,新的需求出现了,工单系统需要支持华为云ECS的创建.虽然说,按照之前的流程去开发好像也没什么问题,工单之前的审批逻辑不变,只是*后审批通过以后选择调用资源管理系统的华为云创建ECS接口,当时的我也正打算这么干,毕竟这种逻辑也比较简单,不需要考虑什么。

但是在前期准备前,我梳理了下整体的开发流程和思路,发现了一些问题,导致我打算开始优化和重构整个系统.
华为云和腾讯云在处理上方式不同。华为云和腾讯云在调用创建接口后,后续的操作并不是相同的方式,华为云创建后会返回joid来标记这次申请,随后需要根据jobid查询本次申请的状态,是否已经创建成功,成功后再去查询相关的机器信息。
如果按照以前的流程,由于华为云和腾讯云在后续的操作不同,导致在完成后续操作时,工单系统中需要有两种实现方式来适应华为云和腾讯云的不同,如果说以后有第三种云,那代码的可扩展性不高。
然后我开始意识到这样的方式并不是很好,根本原因是思考角度的问题。

由于在单云场景中,所有的流程都是按照腾讯云的规范和方式来设计的,对后期代码扩展性的考虑较少,然而在当前需要支持多云资源管理的场景下,并不是很友好.因此我觉得需要对原来的方式进行优化。

多云场景

在多云场景的角度下,我开始思考,既然是资源管理系统,为什么不从资源本身的角度出发,来思考对其生命周期的管理。

以腾讯云的cvm和华为云的ecs为例,其本质都是弹性云服务器.聚焦弹性云服务器,我们需要做到对其生命周期的管理,例如创建、回收、查询、更改配置等操作,这是不论哪个云厂商都需要支持的功能.

从这种角度出发,流程就可以梳理成这样:
工单系统审批完成后,调用资源管理系统的接口创建云服务器,资源管理系统返回申请id,是记录在系统中标识唯一一次申请的记录,后续的操作就由资源管理系统来完成,工单系统只需要定时根据申请id查询本次申请的状态是否是已完成,完成后获取机器的基本信息.

这种做法从工单系统的角度来说,就简单了很多,只需要去调用接口申请机器,后面不论是腾讯云还是华为云的逻辑都无需关心,这样相对来说是比较合理的。

接下来就需要对资源管理系统进行改造和优化了。
以下是我设计的类图:

%title插图%num

简单介绍下每个类各自的作用:

CvmService接口:
在这个接口中,我主要定义了关于弹性服务器在创建的场景下,需要提供的方法,和我上面描述的一样,包含一个创建服务器的接口和查询创建申请状态的接口。在这个接口类的方法更主要为弹性服务器自身生命周期或者其他需要对外提供的方法,类似以后我会提供回收服务器,查询服务器信息等接口。

BaseCvmServiceImpl抽象类:
在这个抽象类中,我主要做了两件事情,定义公共的函数以及确定一些方法的流程。定义公共函数应该比较容易理解,例如无论是腾讯云或是华为云,创建成功以后一定需要插入cmdb中,或者是对申请记录的增删改查,这些都是公共的方法,可以将它们放在这个公共类中,减少重复代码的出现。另外确定一些方法的流程,我还是以创建的方法举例,在抽象类中,我实现了createCvmInstance接口方法,在方法的实现中,我约定了创建的整个流程。
%title插图%num

首先是对参数的校验,校验通过后,开始在服务器申请表中新增一条记录,然后调用云平台API创建机器,然后更新申请的状态,将申请id返回给调用方。随后通过定时任务去完成后续的操作。

以抽象类中的createCvmInstance为例,将上述我说的流程进行了约定和实现,其中校验参数的checkCreateCvmParam方法和invokeCreateCvm方法都是定义的抽象方法,需要各自云平台的实现类需要去实现。

同样的 completeCvmCreateApplyTask方法是用来完成调用创建后后续的操作的,我也进行了同样的约定和实现,在这里就不多讲了。

另外说明一点就是我对申请状态的定义:

%title插图%num

大致概括了所有会出现的场景。

各自云平台的实现类:
各自云平台的实现类就没什么好说的了,就是实现一些父类中的抽象方法和自己的方法。这里我在编写的过程中有个改变就是,将*终调用云平台的API单独放在了一个Api类中,这里的一个方法对应着云平台的一个方法,这样拆分,使得细粒度上允许这些API方法的重复使用,也更加的清晰

以上的架构相较之前有什么优势,我认为是以下几点:

1.系统间的耦合度降低
2.系统内重复代码更少
3.系统更具有扩展性

在开发过程中,我约定好以上的结构后,首先开发了华为云ECS创建的实现,随后又把之前已有的腾讯云的逻辑按照现在的结构也重写了一遍。在写腾讯云的过程,我的感受就是的确比*次写的时候轻松很多,因为很多方法的结构已经确定了,也存在很多公用的代码已经开发完成,只需要补一些个性的代码,整体流程就完成了。

以上方法实现以后,对于接入层来说,也只需要一套代码就可以搞定,可以使用工厂模式,获取对应云平台的实现类来调用。

不过没有一样东西是完美的,架构也是。上面的这种方法,其实对基类中的流程约定是有一定要求的,需要具有一定的通用性。如果太过通用,就会出现很多重复代码,对流程的限制也少了。但是如果不够通用,那么以后在扩展时,就会很头疼,有时候可能需要硬生生往上靠。不过系统本来就是需要一步步优化的,区别就是有的人看得近,有的人看得远。

思考

以上的优化,我从中的思考有两点:

1.优化后,云资源就可以做到真正的管理,这样的话后续的就可以在成本管理上做些文章。成本管理对所有互联网公司来说,都是必不可少的(此处忽略那些财大气粗的场)。当整体系统都上云以后,每个月都可以统计公司在成本上的支出,同时也可以多种角度多维度进行比较分析数据,帮助公司省钱。

2.另一点则是这次改造后我的想法,由于之前看过公司内,公司外部的开源代码库,对于知名的框架例如:springboot、dubbo、mybatis等,在阅读源码理解原理的同时,我也一直感叹这些代码的架构之美,但是反观自己,可能更多的是在写一些模块的业务逻辑,要么就是写MVC的东西、要么就是别人已经设计好框架,只需要去填充就好了,在架构上并没有好好的思考过。即使是在互联网公司,更多的是注重快速,快速的实现、发布、迭代、反馈。然而随着时间的推移,场景的变化,往往起初的设计思想和架构体系需要更新换代,这个时候沉下心去思考下,即使花更多的时间,我觉得也是更有意义的。而且大部分的系统和代码都是需要有一批批的开发者来维护和创新,只有前面的骨架搭得好,系统才能逐渐完善和壮大。

————————————————

原文链接:https://blog.csdn.net/qq_20614905/article/details/109703337