APP下载

大型互联网平台微服务化改造六得

2017-12-19李忠民齐占新周庆虎

科技创新与应用 2017年35期

李忠民+齐占新+周庆虎

摘 要:根据最近在为某大企业G做电子商务平台(文章称其为E系统)的微服务化改造,该平台为年交易额数千亿的大型招投标交易平台,拥有供应商用户数十万,采用微服务架构,基于G企业的私有云建设。G公司原有的E系统(后文简称E1.0)投产比较早,是一个典型的单体应用,当初没有预料到会有这么大的交易量,一直处于小马拉大车的状态,且由于架构因素导致扩展性很差,改进困难,故G公司下决心进行E系统的彻底改造,而实施微服务化改造的新版E系统(后文简称E2.0)则是一个集云计算、容器化、微服务架构等技术于一体的系统,这个转变过程非常具有代表性,故根据实践经验总结出几个原则以供探讨。

关键词:大型联网平台;微服务架构;微服务化;组件化设计

中图分类号:F713.36 文献标志码:A 文章编号:2095-2945(2017)35-0001-06

1 背景介绍

E系统是一个大型招投标交易平台,是G公司的核心应用之一,该系统的1.0版本已经投入运营近十年,目前拥有注册用户30余万个,设计目标是100万用户。目前该系统年处理采购申请80万份,存储非结构化数据1.7亿份,计30TB左右。

该系统有一种典型的应用,即大批次招投标业务,其对性能提出了较高的要求:

(1)该业务要求系统能够在规定期限内上传5TB的投标文件。

(2)投标文件都是加密、压缩传输,要求在2小时内完成2.4TB数据的解密、解压处理。该交易是E系统的关键应用,也是特色应用,该交易的设计指标极大地影响着E系统架构设计的方方面面,如网络入口带宽、存储设备性能、应用服务处理性能、内网局域网的带宽要求等等。

E1.0版本有几根本性的问题:

(1)开发时间比较早。由于业务发展比较快,当初的架构已经不适应如此大业务量的需要,长期处于小马拉大车的窘境。

(2)架构腐化非常严重。系统呈现一团面條状,改动和优化非常困难,导致扩展性很糟糕。

(3)业务特点决定了在某种特殊投标业务时,需要在规定时间内处理非常大量的数据(据测算达到5TB之多),故而在这些交易上需要非常高的性能,而平时这些交易又几乎没有流量,故性能要求高,且波动幅度非常大。

(4)采用集群化部署,资源配置缺乏弹性。

以上几个问题正是微服务架构大显身手之处,故对于E系统来说,实现微服务化是正确的举措。今年正当G公司实施新的IT信息化战略的第一年,新战略以私有云建设为重头戏,引入一平台一系统规划理念,E系统作为G公司最大的核心应用系统之一,上云发展、采用分布式架构既是公司整体战略的要求,也是E系统自身的必然选择,故G公司决定彻底重建E系统,重新分析、设计、开发。E2.0系统采用微服务架构,实现单体应用向微服务架构的转变,实现传统集中式集群化系统向分布式、私有云转变。

2 E系统微服务化面临的困难

网上有很多对比单体架构和微服务架构的文章,其中不乏对微服务颂扬有加的激进观点,但是当面临一个真实的大型应用,要真正地操刀微服务化时,首先要做的是充分考虑到其中的风险,个人认为还是要相对务实一些、保守一些,不要被那些纯技术派的观点误导。

在实施E系统的微服务化改造中,我们主要面临几个问题:

(1)首先微服务化引入了复杂性技术,微服务架构是分布式架构,凡是分布式架构所具有的复杂性其都具有,而每个架构师都应该努力避免引入无谓的繁杂。

(2)其次微服务架构只有和云计算、容器化等一系列技术结合使用才能发挥其效果,这附带着需要整个技术生态发生变化。

(3)微服务化必然引起设计、开发、测试、运维支持等工作的一系列变化,对于一个有着很多成熟应用、运维技术已经相对固定的大型企业来说,引起的变化已经超出技术范畴。

(4)微服务架构引起的一系列技术路线方面的变化,在一个有着成熟完善的IT管理制度和规范战略的企业中意味着需要很多突破,需要企业信息化管理制度方面的许多变革,故而有很多请示、汇报、研讨、论证环节,产生巨大的协调、沟通成本,作为一个资源有限、工期限制严格的项目,要在时间、人力资源等方面充分考虑,否则很可能技术上没有问题,但是项目反而失败了。

故而在对E1.0系统进行微服务拆分的过程中,项目组坚持了一个原则:要建设一个可用的E系统,而不是一个十分先进的E系统。微服务架构是一种手段,我们用它是要解决问题的,不能为了微而微。应该注意到微服务架构在解决一些问题的同时,也不可避免地提高了复杂性,盲目的微服务化,片面强调微服务的“微”,而忘了为什么要微,会使得引入的问题比解决的问题还多,导致项目失败。

3 一得:微服务架构本质是“解耦”

首先我认为微服务这个概念有一定误导性,相对于传统单体应用,将其称为“多体应用”更准确些。微服务架构仅仅是一种新的解耦方式,是一种“彻底解耦的多实体应用”,实体间彻底解耦,然后按照规范的方式协作是微服务架构的根本特征。

一个系统可以分为开发态和运行态,开发态即我们通过设计、开发、测试等过程逐渐构建出来的系统,此时系统是作为静态的代码、配置文件和数据的集合存在于硬盘中,是没有行为的。运行态即系统运转起来以后具有的结构。

传统单体应用的特征为:其开发态是一个实体,其运行态是该实体的多个实例,就像类与对象的关系。传统的单体应用一般采用单机部署(很少,除非非常小的应用或者实验性的系统)或者集群化部署,其根本特征是“一个设计、开发、测试实体,一个或者多个运行实体”。

而微服务架构在开发态时就是多个实体,运行态更是每个开发态实体又产生多个实例,且如果与云技术结合,这些实例数可以动态调整,故微服务架构是一个“多个设计实体、多个开发实体、多个测试实体、多个运行实体”的架构。endprint

4 二得:可用性第一、非功能需求优先

一个系统最重要的是可用性,可用性包括功能完备性、可维护性、可改进性,失去了可用性,谈论什么其他都失去意义,故在做架构设计时,所有技术决策都要确保和增强系统可用性,违背了这一原则引入的技术决策都是有问题的,而微服务架构使用不当是会引入过多的复杂性的,此时是违背了上述原则,为了避免该问题,在E系统的微服务拆分时我们始终坚持可用性第一、非功能需求优先的原则,笔者认为这个原则具有普适性,特别是对于微服务划分有一定指导意义。

在这个原则的指导下,对一个应用系统进行微服务拆分应该在两个层面做出决定:

(1)是否可拆分?

(2)有没有必要拆分?

如果把需求分为功能性需求和非功能需求,则第一个问题的答案取决于功能性需求,此时重点考虑如下要素:

业务独立性

数据独立性

技术独立性

第二个问题的答案取决于非功能需求,此时重点考虑如下几项要素:

可用性:功能完备性、可维护性、可改进性

性能

稳定性

先进性

第一个层面的基础上给出了一个潜在的微服务候选者列表,第二个方面的基础上对候选者进行过滤,给出了真正的微服务列表。

微服务能够划分到什么程度取决于业务需求,比如互联网应用的业务性质决定了应用之间比较独立,那么这种应用切分就比较彻底,适宜于切分成比较小的微服务,传统企业应用由于业务模块之间有着千丝万缕的联系,很难切分出比较小的微服务,即功能性需求决定了一个应用是否可以拆分。

微服务应该划分到什么程度取决于非功能需求,如果某次拆分对改进系统的非功能需求没有贡献,就没有必要拆分,也即非功能需求决定了有没有必要拆分,说到底是非功能需求决定了一个应用系统会拆分出什么样的微服务、拆分出多少微服务。

实施微服务化时很自然地做法是看到一个应用可以拆分就会继续分下去,直到拆无可拆,这种做法是有害的。在操刀之前必须问自己:难道能拆就必须拆吗?否!并不是具备拆分条件的就必须把它拆分出来。在进行遗留系统的微服务化时,要坚持非功能需求优先的原则,尽管有时业务的性质决定了其可以继续拆分成更小粒度的微服务,但是如果这次拆分对改进系统的非功能需求没有贡献,就没有必要拆分,继续拆分不但无益,反而会引入更多的复杂性,如更多的分布式事务、更多的远程调用、更多的故障点、更多的运行维护困难。毕竟管理几千个微服务和管理几十个微服务其复杂性不在一个数量级,此时一定要保持清醒头脑,时刻记得我们引入微服务架构的目的是什么,一般我们引入微服务架构并不是因为其先进,而是因为其能够解决某些问题。

E系统的业务中可以识别出很多相对独立的业务,这些业务在功能上、数据上都相对独立,具备设立微服务的基本条件,但是只能说是潜在的微服务,是否必须设立为微服务?个人认为还是从业务发展需要、可维护性、可扩展性角度考虑,可拆可不拆的尽量不拆分。假如在设计阶段不对复杂性进行控制,则我们可能得到了一个架构更加先进的E系统,但是它更加难以维护,系统的综合使用效果会大打折扣。

5 三得:微服务大小和个数是伪命题

微服务的“微”容易使人迷惑,很多团队在争论到底要切分到什么层次、到底有多微才是“對的”等等问题。在项目组内部、在专家研讨会上,就遇到不止一次就“到底要多大”“到底切分到什么程度”等问题发生争论,每当此时我都会感慨起名字很重要,如果我们认识到微服务实际上仅仅是一种新的解耦方式,是一种组件,只不过在开发态、运行态都有一定独立性,是一种解耦比较彻底的多实体架构,那么我们就会知道“到底要多大(才是对的)?”,“到底多少个(才算是微服务架构)?”等问题都是伪命题,颗粒度、数量都不是微服务架构的关键特征,微服务的大小、数量不应是微服务架构关心的,这些特征不应该作为判定一个架构是否是微服务架构的标准、只要实现了“彻底的解耦”,即使拆分出的微服务很大、包含非常多的业务功能也是微服务架构,为何不是呢?

可以采取反证法来说明这个问题:假设我们手上有一组很大的微服务,我们计划要对其进一步拆分,只要保持了业务功能解耦、数据解耦,我们随时可以把它简单地进一步拆分,这样做没有引起任何技术路线、系统运行机理、运维方式上的变化,只是每个实体变得小了,那么为何仅仅因为实体变小了就成了微服务架构,而原来的不是微服务架构?

5.1 微服务不宜拆的过细

在对E系统进行拆分时,不止一次遇到这个问题,对于这个问题每次我都会回答:微服务架构并不关心某个微服务的大小。

业界有的认为微服务应该拆分到领域对象的粒度,甚至有的说要到100行代码!这都是没有坚持可用性第一的原则造成的错误观点。

(1)在对传统企业应用进行微服务划分时,划分到领域对象的做法是得不偿失的,首先如果划分到领域对象会造成非常多的微服务,比如E系统的业务非常复杂,领域对象达到1000多个,按照这个做法会有1000个微服务,尽管有很多工具支撑,开发、运维这个数量级的微服务不在话下,但是总是造成了很大的运维复杂性,请问引入这些复杂性的同时我们得到了什么好处?架构更清晰了?只要正确地按照领域驱动的设计原理去做,即使不把领域对象独立成微服务也可以做到架构很清晰。

(2)领域驱动是一种业务分析方法论,不是架构设计方法论,其没有考虑到分布式事务、数据一致性、运维监控等架构设计场景的需要。按照该方法论领域对象之间是设计上、逻辑上实现了解耦的,但是并没有考虑到一旦它们物理上(运行态)也解耦时面临的问题如何解决,故使用领域驱动方法论进行业务分析是可以的,但是把它用于架构设计领域则不适用。

在传统企业应用中,同时对多个领域对象操作的交易非常多,比如在对合同进行操作时,可能会同时对订单进行操作,按照领域对象的通常做法,仅仅是在合同对象的某个方法中调用了订单对象的某个方法,这个操作是本地调用,如果把每个领域对象作为一个微服务,则该种调用变为远程调用,这就引入如分布式事务、增加了故障点等等一系列始料未及的问题,这些问题并不是没有办法解决,但是架构设计的原则是以最小代价解决问题,能用本地调用解决的,为何用远程调用?能用简单方法做到的,为何用复杂的方法去做?endprint

归根结底是微服务划分不宜太细,把微服务划分到领域对象级别是划分的太细了。

(3)至于微服务要到100行代码的观点,不知哪个平台坚持了这个原则。

5.2 不要追求微服务个数

除了对微服务大小产生迷惑外,也有人会关心微服务个数。这个问题也偶尔也产生过争论,基本上可以把上面的回答复制下来回答这个问题:

微服务架构本质上是“一种新的解耦方式”,个数不是微服务架构的关键特征,多少个微服务更不是微服务架构关心的,只要按照规定方式实现了“彻底的解耦”,即使仅有几个微服务也是微服务架构,为何不是呢?

尽管不能因为微服务个数少就怀疑其是假的微服务架构,但是讨论“多少个微服是合适的”这个问题是有意义的。

每个微服务实例都是一组独立的运维单元,尽管微服务架构必然伴随着DevOPs,但是运维单元越多,复杂性越大,运维越困难这个事实是不争的。因此微服务的数量当然是越少越好,前提是解决了我们的问题,达到了目的。即使你有阿里那样的黄金团队,但为何非要给自己找麻烦呢?

6 四得:微服务化是组件化的一种形式

架构设计的通常做法就是“分而治之”,化复杂的问题为多个简单的小问题,再逐个击破,微服务架构是这种思想的一个生动体现,这种思想的另一个重要实践是组件化设计。

从组件化的角度来看微服务架构,可以发现微服务是一个组件集合,只不过该种组件集合是一个独立的设计、开发、测试、运维实体。组件局限在一个逻辑层内,一般不跨越层,但是微服务是跨越多个层。

组件划分一般先水平分层,再层内切分。微服务划分则在组件划分的基础上还要多做一步工作:先水平划分,再层内切分,然后再根据功能把组件组合成一个集合,该集合即为微服务,其可以跨越多个层,向外提供一组服务接口。

6.1 从逻辑分层角度认识微服务和组件的关系

E系统分为展现层、应用服务层、业务逻辑层、基础业务服务层、技术服务层、基础架构服务层,同层内部再划分为一个个组件。

E系统的组件分为技术型组件和业务型组件,同样逻辑层也分为技术性层和业务性层:展现层、应用服务层、技术服务层、基础架构服务层是技术性的层,里面分布的是技术性组件,一般不会随着业务变化而变化;业务逻辑层、基础业务服务层是业务性质的层,里面容纳的是功能组件,是领域对象,可以认为E系统的全部业务在这两个层中;理论上说,业务发生变化,不会引起技术性层中组件的变化,同样,替换技术层中的组件,也不会引起业务层发生变化。

6.1.1 没有微服务化时的逻辑分层模型

图3是简化后的没有微服务化时的E系统组件划分图。

6.1.2 微服务化后的逻辑分层模型

微服务与组件的区别在于微服务可以跨越多个逻辑层,微服务不以复用为目的,相反,为了达到高内聚低耦合的目标,微服务必须集成自己需要的各个组件,使得同一个组件在多个微服务中重复。

微服务同时容纳业务型组件和技术型组件,其容纳的业务型组件决定了其对外提供的服务,不同微服务之间的区别在于其業务逻辑层和基础业务服务层集成的业务型组件是不同的,但是其他层的技术型组件则基本相同,即同一个技术组件在不同微服务中多次被集成,业务组件则每个微服务不同,换句话说微服务之所以能够提供不同的功能,是因为其容纳了不同的业务型组件。

图4是E系统的微服务和组件关系示意图。

区别于一般互联网平台,E系统的业务是典型的企业应用,业务耦合数据耦合比较紧密,故E系统的微服务没有遵循一个微服务一个数据库的流行做法,即E系统的微服务仅包含了应用服务层、业务逻辑层、基础业务服务层,技术服务层,而没有包含基础架构服务层。

6.2 微服务、系统、子系统与组件

6.2.1 微服务与组件

微服务就是组件的集合,也可以认为是一种比较大的组件,其跨越多个逻辑层,同时包含了技术型组件和业务型组件,微服务提供的服务是业务型组件决定的,技术型组件辅助业务型组件提供了这些服务。

6.2.2 微服务与子系统

子系统仍然是传统单体应用架构下的概念,第3节中关于单体架构和微服务架构之间的区别,也描述了子系统和微服务之间的区别:子系统虽然是一种解耦,但是多个子系统之间在分析、设计、开发、测试、运维中都是在同一个实体中的,子系统之间不会作为独立的运维单元对待。而微服务则是在分析、设计、开发、测试、运行过程中可以全程保持独立,作为一个独立的单元对待。

6.2.3 微服务与系统

微服务之间会使用同一组基础架构层的组件,如分布式消息队列、分布式会话组件、分布式缓存组件等,且之间的通讯协议是比较规范的,一般提供遵循Restful风格的接口;而系统之间一般是完全独立的,不会共享组件,且之间的通讯协议是相当丰富多彩。

7 五得:微服务划分的其他原则

(1)一个微服务要实现一个比较独立的业务,具有清晰的边界,同时微服务应该足够大,尽量把业务变化包裹在自己的边界之内。

(2)尽量避免微服务之间的相互调用,避免分布式事务,一个微服务尽量提供一个完整的功能,不要把微服务之间的调用作为常态,要把其作为不得已而为之的选择。

(3)微服务要自我完备,包含自己的各种技术上的依赖和第三方包,微服务的目的不是实现代码复用,而是分而治之:把一个大的应用拆分为几个小的应用。

(4)微服务应该作为独立的设计、开发、部署、运维单元,独立演进而不影响其他微服务。

(5)不追求微服务数量,能少则少。

(6)迭代式前进,微服务化是一个迭代的过程,不断迭代,逐渐逼近最优,而不是一步到位(实际上无法确定什么是最优,只有不断实践、观察、再实践,通过这种迭代逼近最优)endprint

8 六得:中间路线是最合适的架构

E系统在微服务化过程中存在四种状态:

(1)单体应用状态,是系统的原始状态

(2)单体应用+一组非功能型微服务状态

这组微服务是按照非功能需求优先的原则从遗留系统中拆分出来的,这个单体应用自然是从遗留中拆分出微服务后剩下的没有必要(或者暂时没有必要)拆分的部分

(3)一组功能型微服务+一组非功能型微服务状态

如果是从零开始构建一个微服务架构的系统,则建议是“一个或几个大的微服务(实现了绝大多数业务,称功能型微服务)”+“一系列小的微服务(出于非功能需求而拆分出来的,称非功能型微服务)”,这样更加简单,避免了复杂性。

如果是从遗留系统进行微服务化,此时因为非功能需求已经得到满足,继续对遗留的单体应用拆分的理由可能是为了使得系统架构更加统一,简化技术路线,消灭单体应用。尽管可以对遗留系统继续拆分,但为了避免引入过多的复杂性,建议对遗留的单体进行比较粗粒度的拆分,消灭单体即可。

(4)能拆尽拆后得到的一群微服务

最纯的微服务架构状态,笔者认为没有必要追求。

第三、第四两种状态可以认为是标准的微服务架构了,实践中笔者认为对遗留系统来说,中间路线是最合适的架构,如果对一个已经存在的系統做微服务化改造,最合适的结果是第二或第三两种状态;如果是从零开始构建一个微服务架构的系统,则建议达到第三种状态即可。

实践中E系统在达到第三种状态即停止进一步切分,得出E系统中有两类微服务:

(1)功能型微服务:包含一个完整、独立的业务功能的一组微服务,比较大。

(2)非功能型微服务:出于性能、稳定性、可维护性、可扩展性等非功能需要而设立的一组微服务,如(举例):

投标文件上传微服务:在大批次招投标业务时,要求规定时间内上传5TB数据,性能要求高。

解密微服务:在2小时内完成2.4TB投标文的解密,性能要求极高。

查询开标结果微服务:在开展大批次招投标业务时瞬时流量非常大,性能要求高,需要弹性扩展。

其中第二种微服务是真正有价值、有必要存在的微服务,是这次微服务化改造的重点;对于第一种微服务,综合考虑各方因素项目组对该类微服务仅做了比较粗粒度的划分。

9 结束语

本人非常赞同“架构设计是做出一系列决策的过程”这个观点,所谓决策,就有“趋之若鹜、甘之如饴”的主动选择,也有“不得不做、两害取轻”的被动选择。在E系统的架构设计过程中,本人迫切感到需要区分这两种选择,比如选择微服务架构就属于后者,是因为作为单体应用的E1.0已经不能满足需要,使得我们不得不选择微服务架构,这是一个“不得不”做出的选择,在利用其解决问题的同时,应该非常小心地避免其带来的副作用,在笔者看来其最大的副作用就是引入了过多的复杂性,因此在实施微服务化改造时要注意努力减少复杂性。网上有人谈拥抱微服务架构,我则要说:客观对待微服务架构。

微服务是一剂良药,说它是良药,就意味着它不是佳肴美味,不能当饭吃,有病才吃无病远之,谨记关于分布式架构的第一个原则:能不采用分布式的就不采用分布式。

参考文献:

[1]李楠.计算机安全技术在电子商务中的应用[J].科技创新与应用,2015(06):55.

[2]宋大为,侯婷婷,顾松敏,等.数据挖掘技术在电子商务领域的应用研究[J].科技创新与应用,2016(05):87.

[3]尹绍捷.移动互联网技术与电子商务[J].科技创新与应用,2015(30):89.endprint