案例研究|海通证券云管理平台微服务化改造实践与思考

发布于 2020年08月27日

编者注:本文选自《交易技术前沿》总第三十九期文章(2020年第二期),作者:陆颂华、王朝阳、张真真、胡晶玉(均来自海通证券股份有限公司)。

海通证券混合金融云平台在集团内部广泛推广和使用,承载的应用超过500个,集团总部、子公司和分支机构也对日常使用的云管理平台提出了更高的要求。本文主要介绍为了能够满足更多复杂多变的使用场景,海通证券对云管理平台进行微服务化、容器化改造的最佳实践,以及改造过程中的一些总结与思考。

1 项目背景

以赋能业务创新为基础,提升资源效能为动力,践行合规风控为准则,通过使用国产化的软硬件技术,实践组织与制度的创新架构,并结合证券行业大量真实应用场景,海通证券建设完成了由云管理平台统一纳管、编排私有云(桌面云、研发测试云、生产云、灾备云和托管云)和公有云的混合金融云平台。此平台在集团内部广泛推广和使用,承载的应用超过500个,使用的部门有集团总部、子公司和分支机构。

1.1 微服务化改造的必要性

云管理平台对外是面向最终客户和业务运营侧的管理软件,相对于对内面向基础设施层的多云平台,其面临场景更复杂多变,尤其是随着托管云战略的深入推进,越来越多的子公司和分支机构租户将通过该平台使用和运营混合金融云平台资源,而每一个租户对于云资源使用和运营都可能会有不同的要求,这就要求云管理平台具有更好的“柔性”,能够快速适应复杂多变的租户需求。为此,对云管理平台的功能模块进行更细粒度的微服务化拆分并通过微服务架构进行整合成为必要。

随着容器技术的逐步成熟和在金融行业的落地使用,海通证券也将建设容器云平台。作为新一代的基础设施管理平台,容器云平台提供了一致的环境部署能力、强大的调度和自愈能力、简单便捷的应用快速发布能力。作为混合金融云面向最终用户和业务运营的唯一入口,云管理平台也希望能利用到这些能力,降低平台日常运维工作量,提升开发运维效率,为未来混合金融云大规模对外服务提前做好准备。

1.2 微服务化改造的目标

基于以上原因,海通证券从2019年开始对云管理平台微服务化改造并明确了以下三点关键目标。

1、实现云管理平台从面向功能场景设计向面向服务设计转变。通过面向服务的设计方式,将云管理平台内的核心服务进行抽象、复用并独立演进,进一步在面向客户场景支持时实现核心服务的灵活组合。通过这一转变来应对云管理平台在面向越来越复杂场景需求(尤其是托管云场景)时的现实挑战。

2、实现整个云管理平台的容器化部署并在容器云平台内实现自动化调度。云管理平台内所有微服务组件需要遵循主流微服务框架开发,并能够完整在容器云平台内部署运行,充分利用容器云内的调度能力实现平台的分布式高可用部署以及常见故障的自愈处理,从而提升云管理平台的服务水平,降低平台维护成本。

3、构建适应容器环境、基于核心框架的二次研发迭代流程。在完成微服务化改造以及容器化部署后,平台在公司内的日常演进和迭代开发工作也需要构建在相应的容器化开发工具链,这样才能更好发挥云管理平台微服务化的价值,并持续深化。

2 建设思路

在确定好建设目标后,我们将工作的重点放在整个平台提升建设的落地思路上,重点从产品框架模块化、业务逻辑微服务化、部署方式容器化以及交付流程自动化这四个方面着手考虑,具体如下。

2.1 产品框架模块化

对典型业务系统进行微服务化改造是一个众所周知的难题,寄希望于一步到位的改造路径很多时候都会事倍功半。为此,我们本次改造选择了先模块化再微服务化的渐进式模式。传统典型应用的产品框架一般都是分层架构,业务功能及业务逻辑的复用多是通过公共代码库来实现。显然,这些实现方式和框架模块化并不匹配。为此,我们为产品模块化改造引入两条基本原则,即“面向场景划分模块”和“每个模块独立运行”。

所谓“面向场景划分”就是从平台使用场景的角度把相应的功能放到一个模块。比如,用户需要利用云管理平台管理主机资源,则所有和主机相关的功能划分到一个模块。这个场景包括多个不同角色,所以这个模块也需要支持该场景下所有角色的功能。为此,我们将云管理平台按场景分成了十多个模块。并且,每个模块的实现是一个完整的技术堆栈(包括独立数据库或者表、独立的业务逻辑,独立的UI界面)。

所谓“每个模块独立运行”是指每个模块有自己独立的运行时,每个模块可以独立启停。系统层面会有独立的模块注册、加载和管理的能力。需要注意的是,这个阶段,模块之间的数据交互还是通过底层数据库直接完成,并没有通过模块化之间的API调用进行。多个模块还是共同访问一个完整的“大”数据库且数据库表结构基本不做太大变化。

基于以上两条原则,整个产品框架模块化改造按以下三步有序推进:

第一步:设计模块框架。这部分工作包括描述模块的基本数据结构,相应元数据的数据库存储结构,以及模块集中注册、加载和管理等生命周期操作。平台需要为每个运行的模块启动一个独立的运行时,并按照生命周期操作来启动或停止相应模块的运行时。另外,任何一个模块运行过程中都可以读取当前模块元数据和当前运行情况,并根据以上信息决定是否在UI上显示相关模块功能。

第二步:设计模块细粒度访问权限体系。这部分工作包括对于模块内部功能点的描述方式定义,并能够实现不同角色对于该模块内功能点的细粒度授权管理。目前,平台使用JSON格式的描述方式定义每个模块的功能点,并在模块内部界面加载过程中按照实际授权情况动态加载相应的界面UI元素。

第三步:将现有平台的功能按“面向场景划分”的原则迁移到相应的模块,并按模块功能需要定义出相应需要进行细粒度管理的功能点。

最后补充说明一下,我们之所以先做模块化改造然后再做业务逻辑微服务化而不是直接就进行公共服务抽取并直接微服务化,是基于以下两点具体考虑:

1、未完成面向场景的模块化设计前,我们很难准确认识到应该如何抽取公共服务。通过面向场景的模块化设计,我们很容易发现重复的业务逻辑和数据结构,不同模块之间的依赖关系,而且可以梳理清楚需要抽象的公共服务具体接口。

2、如果直接简单进行公共服务抽象,我们担心最后的结果是公共服务式抽出来了,剩下的各个不同场景的功能仍然是“一团浆糊”存在于一个遗留工程中。而我们云管理平台的功能迭代和暴露还是要在这个遗留工程中,接下来的开发和迭代仍然很难。与其这样,还不如最开始就从模块化入手来改造项目。

2.2 业务逻辑微服务化

在解决了产品模块化之后,我们需要重点解决云管理平台业务逻辑的微服务化。有了平台模块化建设的基础,这部分工作就会变得容易很多。一方面,需要抽象的公共服务和其需要暴露的接口已经显现出来,另外一方面,通过面向场景的模块化改造,功能模块和公共服务层次关系也变得很清晰。具体来说,这个过程包括以下三个方面工作:

1、引入微服务开发、运行和管理框架,为所有微服务模块的开发、运行、分布式事务和治理提供基础性支撑。在本项目由于之前开发基于Spring Boot框架,所以自然延续下来使用Spring Cloud微服务治理框架。

2、建设公共微服务。具体来说,我们建设了包括“权限管理中心”、“流程管理中心”、“订单管理中心”、“工单管理中心”、“模块管理中心”、“用户管理中心”、“租户管理中心”和“IP池管理中心”等公共服务。

3、改造面向用户的模块,使其依赖于公共微服务并将自己也变成一个微服务组件。这次过程中我们改造了“平台管理”、“资源管理”、“主机交付”、“运营分析”、“监控告警”、“容器管理”和“网络管理”等十几个功能模块。

改造过程有一个非常大的工作量就是数据库的拆分和跨服务之间调用的API化。我们需要让每一个微服务依赖自己独立的数据库,并通过API进行数据交换。所以,通过这个过程后,我们平台后台数据库将从一个“大而全”的实例变成很多“小而专”的数据库实例。

2.3 部署方式容器化

在微服务化改造前,整个云管理平台的部署方式如图1。

图1-云管理平台改造前部署架构图

从以上部署架构图可以看出,平台部署采用的是典型主-备部署方案,分成业务接入层、业务逻辑层和数据库存储层三个部分,并部署在两台独立的物理设备上。其中,业务接入层采用的是典型“VIP + keepalive”模式,实现系统故障时候的自动切换。业务逻辑层则在两台独立物理机上分别部署运行,并同时连接到主数据库。而数据库层采用最典型的MySQL主从部署方案实现数据库的高可用。

在完成云管理平台微服务化改造后,整个平台是要在容器云环境内运行的,并将系统的高可用交给容器云平台自行编排,而不是现有的传统主从模式配置和切换。具体来说包括以下三个方面。

1、业务接入层不会再是主从切换模式,而应该换成负载均衡模式。用户访问平台的流量会被容器云平台内的负载均衡设备分发,所有运行的云管理业务实例都会同时对外提供服务,这需要进一步细化云管理业务模块中的状态管理。同时,需要增强每个云管理服务的状态监测能力,让负载均衡设备能更精确决策流量分发。

2、所有云管理平台业务都将在容器里面运行,需要改进现在的业务运行监控模式,能够适配在容器环境中采集监控数据并对外展示。这和基于操作系统部署业务的传统模式有非常大的不同,有较多的适配工作。

3、在数据库层面,采用了保守的迁移策略,先将数据库保留在传统操作系统上面并依然按照主从模式部署运行。经过改造后,整个平台的部署运行图2。

经过改造后,整个平台的部署运行图2。

图2-云管理平台容器化部署架构图

2.4 交付流程自动化

如前所述,整个云管理平台微服务改造的一个重要目标就是改进软件交付流程。在这一次软件交付流程的改进过程中,我们从传统的基于物理主机的构建、打包和部署的流程切换为基于容器的CI/CD流程,并依赖容器云的部署调度能力实现平台的高可用部署。具体的流程如下。

1、首先定义一个流水线(Pipleline)。

2、源代码在GitLab中管理,当新特性的代码合并到主分支后,自动触发Jenkins基于dockerfile进行构建打包。并把产生的容器镜像存放在容器云平台的制品仓库中。

3、利用容器云平台的发布及编排功能,将生成的容器镜像部署在指定的容器云应用集群并完成相关配置。类似,我们仍然是编制相应的部署描述文件并上传到容器云镜像以实现整个发布过程的自动化。

3 实践总结

回顾整个项目微服务化、容器化改造的过程,有几点实践值得总结和交流。这些实践经验贯彻整个项目改造过程并一直指导项目在正确的道路上前进。

3.1 按产品实际功能需求和定位定义推进方式

微服务化改造对于典型应用是有着极其巨大的挑战,最容易犯的一个错误就是参照经典理念,选择一个微服务框架,然后就进行业务模块的拆分和相应的开发。这样激进的操作非常容易造成整个改造过程的失控。一定要从产品实际定位和真实痛点出发。在本次微服务化改造过程,一个重要的出发点是使平台在面对未来越来越复杂的需求时,具有面向不同场景的“柔性”。所以,在微服务改造过程中,第一个想法不是去抽取公共服务,而是做面向场景的模块化改造。这样一方面方便将不同场景进行切割,另一方面也为接下来做微服务改造打下基础,降低改造风险和项目失控风险。

3.2 微服务模块的粒度和边界控制非常重要

当进行业务逻辑微服务化改造时,如何划分微服务模块(包括公共服务)并控制好其调用关系变的尤为关键。粒度划分过细导致管理难度增加并且会引入不必要的分布式复杂度,划分过粗会导致相互调用和依赖关系混乱,无法合理管理和跟踪。在整个改造过程,我们采用渐进式拆分思路,遵循仅垂直依赖而不是平行乃至反向依赖的模式。具体来说,只会在有多个模块有共同依赖的情况下才会主动把共同依赖部分拆分成为公共服务,而公共服务部分也采取先大颗粒度建设,直到上层模块依赖复杂到必须进行细化时候再做拆分。

除了模块之间的调用外,另外一个非常困难的地方在于数据库的切分。传统应用集中访问数据库,并利用数据库软件的事务功能解决数据一致性问题,而微服务化后,首先每个微服务模块都将拥有自己的独立数据库,跨微服务的操作会转换成为对多个微服务接口调用,这样就无法利用数据库管理软件内的事务能力,而需要在API调用层引入分布式事务管理框架,从而保障数据的一致性。

在拆分过程中,首先定位相应微服务模块的核心能力以及对应的核心数据模型是什么,先将其纳入到微服务模块自己的数据库内,并基于此做相应功能开发和接口暴露,遇到对外部数据库表的依赖时候,首先仍然以对外部数据库的直接方式访问实现。通过这个过程让我们重新梳理模块之间的数据依赖情况,然后再将这些数据库直接依赖转换成为模块之间的API调用。

3.3 保持业务在线运行并不断在真实环境中验证

在整个改造过程,我们遵循一个原则,就是业务需要持续在线运行不中断。我们每做一步改造和服务抽象,都会发布一个完整的服务版本,并经过测试环境、仿真环境和生产环境的路径反复验证并试运行,通过这个策略保证整个平台改造质量的把控,同时又能实现无缝升级。当然,这会给整个过程的业务保障带来很大挑战,需要我们对于每一步升级都有完整的升级方案和回滚方案。这个需要在工程管理上做好大量细致性的工作。

4 规划与展望

在完成以上微服务化改造后,整个项目建设已经达到最初设想的整个目标并在真实的容器云环境运行起来,对外提供服务。随着投产运行,我们也对微服务化体系架构及其日常运维管理有了更深一步的理解和认识。基于这些认识,下一步会重点筹备分库后的DBaaS建设和持续提升整个微服务架构应用的服务治理能力。