业务系统的微服务化改造方案.docx
《业务系统的微服务化改造方案.docx》由会员分享,可在线阅读,更多相关《业务系统的微服务化改造方案.docx(14页珍藏版)》请在冰豆网上搜索。
业务系统的微服务化改造方案
业务系统的微服务化改造方案
目录
1.篇首语3
2.微服务化改造5
2.1技术选型决策6
2.1.1选择微服务化方式6
2.1.2微服务化框架和治理模型11
2.2架构设计规划14
2.2.1整体架构设计15
2.2.2业务领域抽象建模17
2.2.3服务规划与层次划分18
2.3落地实施应用20
3.篇后语21
1.篇首语
业务系统是任何一个用户产品的必须组成,充当着一个门面的角色,用户的输入就是这个系统需要维护的,数据存取是整个系统的核心。
例如,广告业务系统的输入是广告主的投放约束、定向条件,微博业务系统的输入是短文字、图片等。
在应用发展初期或者规模不大的情况下,有非常简单的实现方案,LNMP、JSP、PyWeb都是你能随口说出来的词,如果用某种架构方式来描述,那就可以称做单体模式(Monolithic,MartinFlower大神所提出的,后面还会介绍),而这些技术都是单体模式的成熟解决方案,它们可以使你工作在“应用层”的最顶端,各种中间件、框架能让你省心地干好业务,开发人员可以通过“模块化”的手段来管理业务系统的复杂度,使他们之间解耦、复用。
简单来说,这个单体就是如下这种层次划分。
表示层前端(HTML+CSS+JS)
||
逻辑层业务系统(PHP、Java、Python是常用的语言)
||
数据层数据库(MySQL)
看起来很简单,对吧。
诚然,业务系统在这里面还需要做很多,比如缓存、SQL优化、数据分区、系统安全工作,当然还有对于代码的维护和重构。
这种工作方式可以很好的工作几年、甚至十年,但是如果业务发展非常快,在系统复杂度、业务规模、参与人数、代码腐化程度都不断上升的情况下,你会发现整个项目正陷于泥潭,PM/RD/QA/OP经常抱怨:
"改个小功能,怎么要拉这么多模块?
"
"拉模块也就罢了,改的地方多,编译太慢了。
"
"慢也就算了,关键不知道怎么改,这代码太丑陋了,算了,为了满足PM的排期需要,凑合来吧。
"
"凑合来了,QA发现bug,返工再返工,延期再延期。
"
"上线了,ohmygod,报case了,性能有问题,原来是依赖的模块访问数据库用了for循环select。
"
透过现象看本质,我总结了来看就这三点问题:
1、业务逻辑复杂耦合,开发维护成本高。
系统复杂度、规模、参与人数都和腐化程度成正比,单纯的靠模块化,后期来看会存在个别模块成为”大怪物“,臃肿不堪,粒度过粗,难以复用。
2、交付效率和质量低。
在敏捷和持续集成方法论、实践大行其道的现今,迭代的按期交付率、单测覆盖率都不尽如人意,线上问题频发。
3、非功能需求不达标。
非功能需求指标特指性能、可用性、可扩展性等方面,代码的腐化和缺少维护、重构,以及没有代码洁癖的人污染下,必然导致性能逐渐下降,甚至出现不同资源竞争的短板效应,造成整个系统crash,同时一个大怪物的伸缩性较差,不能随意横向扩展某个细分功能点。
我想任何人做架构都需要秉承“业务需求决定技术演化路线”的思路,那么这些暴露出来的现状和问题都驱动系统去转型,在系统和人之间找到一种最佳的合作模式,匹配已有的生产力和生成关系。
正如软件开发学泰斗KentBeck所说的:
“Designistheretoenableyoutokeepchangingthesoftwareeasilyinthelongterm” ,即“变化发生时设计被破坏的程度”
放眼业界,面对复杂的、大规模的、多人协作完成的业务系统,如何管理好这个复杂度,有很多方法,模块化、OSGI、传统服务化SOA等等,当今最佳实践的趋势还是服务化,而微服务是最近火热起来的概念,有些人肯定觉得这不就是炒作嘛,但是不管黑猫白猫能抓耗子就是好猫,所以解决问题是重点,不要刻意去批评一些名字,那么本文要重点介绍的就是——如何做微服务化转型和改造。
在接下来讲之前,要重点声明,本文并不是推崇服务化,不鼓励单体模式,相反而是相当肯定和支持单体模式,它模块依赖简单、一个发布包、部署于一个容器都使得构建应用非常的简单,在体量还不大的情况下,首先应该解决的是搭建好一套绝对稳定的基于模块化的平台,待体量逐渐长大,再去根据实际需要进行拆分,团队也随之变化(facebook的单体持续了非常长的时间,一是人员素质高,二就是基础平台建设的非常好)。
再下个阶段体量大到饱受单体模式之苦,也应该先建设平台化服务,建设好之后,先按照大的粒度进行拆分,逐步再微服务化,否则,直接上服务化、甚至下面要说的微服务都是非常危险的,鲜有成功案例。
2.微服务化改造
做改造一般要经历三个步骤:
第一、技术选型决策
第二、架构设计规划
第三、落地实施应用。
下面依次展开三个部分,重点介绍前两个步骤,有了这两个,落地应用也就顺水推舟的好做了。
2.1技术选型决策
2.1.1选择微服务化方式
选择服务化,众所周知就是SOA嘛,这是一种架构风格,重点在原则、理念、方法论等高思维层次上,对于工具、框架、解决方案没有做强制限制,ESB、websercie(基于WSDL和SOAP/BPEL)这两种是企业中流行的,也是过去一直引领SOA的技术领头羊,但是随着互联网应用的发展,在敏捷快速迭代、高可用、高性能、高并发等方面要求越来越高,传统的SOA并不适合这种场景。
那么,现在的互联网流行的实现方式是什么呢?
一种最佳的实践方式就是微服务化(MicroService)。
[配图1]
微服务就是一种SOA的实现方式而已,更加侧重于在服务的细分演化,是指引服务的具体落地方案层面的一种实践方式。
过去很多互联网公司在实践,你可以把淘宝的dubbo、HSF,navi-rpc服务化框架看做比传统SOA更适用、更贴近微服务化实现的服务化框架,依赖这些框架可以方便的做服务化。
这个趋势被MartinFlower大神所发现,并且提出了,你们这些不都是在做“微服务”嘛。
Martin对微服务这个术语(terminology)的解释是:
Inshort,themicroservicearchitecturalstyleisanapproachtodevelopingasingleapplicationasasuiteofsmallservices,eachrunninginitsownprocessandcommunicatingwithlightweightmechanisms,oftenanHTTPresourceAPI.Theseservicesarebuiltaroundbusinesscapabilitiesandindependentlydeployablebyfullyautomateddeploymentmachinery.Thereisabareminimumofcentralizedmanagementoftheseservices,whichmaybewrittenindifferentprogramminglanguagesandusedifferentdatastoragetechnologies.
简而言之,微服务化就是以一系列小的服务来开发支撑一个应用的方法论,服务独立在自己的进程中,通过轻量级通信机制交互(通常是走HTTP协议)。
这些服务是围绕着业务上的组织结构来构建的,全自动的、独立部署。
几乎看不到中心化的服务管理基础设施,可以使用不同的编程语言和数据存储技术来实现不同的服务。
在简单的一种理解来自于一本书《BuildingMicroservices》(SamNewman,O’ReillyMedia),Microservicesaresmall,autonomousservicesthatworktogether.微服务化就是一堆小而自治的服务,让他们一起工作起来。
相比于传统的SOA,Martin的总结特点可以参考他的博客还有视频(Youtube链接),一共是9个特点,这里不想赘述,而是说说我个人的理解,微服务化的特点在于:
1、模块即服务
微服务中的组件在逻辑或者物理层次更趋于细分,这个细分不是极致的,而是一种粒度适中的选择,通常这些组件在前期可以是一些模块,但是当需要时,例如业务上需要拆分独立,或者非功能需求上需要扩容等,都可以灵活的拆解出来。
这个特点非常重要,因为业务系统中模块化实践,随着软件规模的变大,很容易绕过障碍而使得不同模块耦合、依赖关系复杂,这种纪律性很难保证,从而削弱模块化的结构、降低了团队的生产力(敏捷开发和持续交付越来越难做,部署起来太庞大了大家的开发士气不高,而且痛苦),很快的这个模块就会变成一个大杂烩,而服务可以做到天然的壁垒,仅仅通过交换契约(通常是API或者proto)来做交互,这是一个演化的过程,不仅有利于分而治之,到达复用的目的,同时老系统也可以灰度的改造剥离。
2、独立自治
这意味着服务是独立开发,独立测试,独立发布,独立部署,独立运维的,某个细分团队负责整个生命周期管理,这就是”康威定律(Conway’slaw)”的通俗解释,官方解释是“一个组织的设计成果,其结构往往对应于这个组织中的沟通结构”,服务的规划不就是多人、跨团队协作的沟通模式嘛。
好处在于摒弃原来的火车模型(所有模块一起发布部署),拥抱独立快跑,这也更好的支持了敏捷和持续集成的方法实践。
同时去除了牵一发而动全身的问题,单一职责的来进行修改需求或者重构一个点,开发和构建方便,不影响整个产品的功能,一个bug不会crash掉整个产品,针对不同的类型,区分计算密集型还是I/O密集型,区分业务上更好使用关系型还是NoSQL,区分2/8原则、即80%经常修改的服务独立出来自成一家,区分短板功能、针对瓶颈可以做水平扩展、避免资源竞争,甚至可以区分技术栈、突破语言限制。
最后,这也是和第一点遥相呼应的,独立的服务可以实现非常大程度上的复用,服务之间依赖轻量级的接口,而不是模块。
3、去中心化的数据管理
在单体模式中,一个应用面对一套数据库,数据库可以按照物理拆分,进行shard分区,或者按照逻辑库隔离,不同的业务路由到不同的库,同时做一主多从等结构上的设计,这些原则在微服务中仍然适用,只不过微服务在服务拆分的同时,也需要将数据库分离,独立的服务维护独立的数据库,这对数据库也是减负,同时技术选型、SLA保证都会区分开来,把精力留给那些重要的业务数据库,进行分级的对待,而不能像以前一样一视同仁,一个不重要的逻辑库的badSQL慢查询,阻塞了其他正常的查询,这是完全可以避免的。
4、轻量级的通信协议
传统的SOA使用ESB或者Webservice这种重量级的解决方案,微服务推荐使用一些更轻的解决方案,要通用性,可以用Restful架构,走HTTP通道,支持Json序列化协议;要高性能,可以考虑一些高性能的I/O模型,例如epoll、Actor等,可以直接走tcp通道,使用protobuf序列化协议,同时保持长连接(这里有一个例子Navi-pbrpc就是一个这样的具体落地框架);要异步,用可靠持久的RabbitMQ或者高性能的ZeroMQ来做P2P、Pub/Sub、广播broadcast消息通信。
而这种轻量级还需要体现在代码调用中,模块化直接通过函数、方法调用即可,服务化后能不能在API层面做到无侵入,无缝的切换、简单配置,这些都是服务化框架要支持的。
5、为失败设计
服务化调用从进程内in-process的调用,转变为跨进程的分布式调用,这种由分布式特性引起的天然不可靠性,需要变为相对可控。
也就是服务间的通信要假设不会成功,为失败处理。
异常的传递,能否透过RPC,在调用方本地还原,就像函数、方法调用一样?
一个点、或者服务的处理错误率到了一个阈值,为了不影响整个产品,要做错误隔离,可以考虑熔断(circutbreak)、舱壁隔离模式、限流、回退等手段,最后还有一个幂等性问题,重试的调用会不会对业务造成影响,这个要具体问题具体分析了。
6、基础交付设施自动化
这个特点是整个微服务中的最大亮点,包括持续集成CI、持续交付CD和PaaS平台的结合。
微服务在细分的背景下,在project结构,物理结构上都提高了一个复杂度,如果还要做到提高软件交付链路的整体效率,就需要在基础交付上做一个大的转变,因此DevOps文化,让每个人都参与交付,在规范的流程和标准的交付(例如,标准的容器)下,同时在PaaS服务提供商的帮助下,完成一个服务的自动部署发布。
任何事情都是两面的,有好的优点,当然会存在弊端,微服务的缺点我的理解如下:
1、分布式调用造成的性能、延迟问题。
(可以采取的措施包括粒度适中、批量、高性能RPC、异步通信等)
2、可靠性不好保证。
(刚才提到的为失败设计可以解决)
3、数据一致性难以保证。
(看各自的业务,确保最终一致性即可,实际上大多数互联网产品很少不用事务;但是我目前所工作的商业产品领域,是需要事务的,除了不推荐的两段式提交,还可以引入仲裁者、补偿措施来解决分布式事务问题,问题可以单独开一篇文章介绍了,这里就不展开了)
4、整体复杂度提升。
服务多、依赖多、调用多、契约如何管理、监控如何做,调用链上怎么确定哪个点有问题,服务的SLA保障、性能、错误率、告警、这么多服务如何集成测试、交付容器如何上线等等问题。
(通过服务治理可以有效降低微服务化复杂造成的低效,转为推动工程生产力的高效进化,同时基础交付设施的自动化可以加速研发效率,选择了微服务就等于选择了成本优先战略,投入的成本都是为了未来业务的更好发展,避免J-curve曲线式的研发模式,只有在体量大,基础设施包括服务化框架、治理能力完善的基础上,加上流程、规范以及工具和技能的辅助下,才可以真正发挥服务化的威力,否则只有自讨苦吃)
2.1.2微服务化框架和治理模型
架构方式、原则达成了共识,你再往下看。
虚的说完了来点干货,来介绍下我所在team实践的微服务化,最核心的就是微服务化框架,业界流行的阿里的框架dubbo以及淘宝内部的HSF,Navi-rpc都可以看做微服务化框架的雏形,加上服务治理中心的管理、基础交付设施的保障就可以构成完整的一套微服务框架。
我们的框架(暂时仅内部使用)整体架构如下图,他由服务发布者、调用者和治理中心三者组成,属于标准的协调者模式。
[配图2]
生产者中服务逻辑在Spring或者Guice等IoC框架的bean中,由IoC容器托管,为了符合模块即服务的思想,在框架层级实现了一套可插拔组件的引擎,去实现组件的扫描,需要暴露服务的发布出来,依赖别的服务的,通过字节码技术生成Rpc调用代理Stub,形成了一个基于组件的容器,通过JSR315这个规范的SPI实现对接到J2EE容器,下面的消费者结构相同。
在服务启动后,首先会第一步注册自己到服务治理中心,上传自己的契约、版本上去,治理中心如果通过检查就发布出去,之后和治理中心通过长连接协议(我们采用websocket,因为现成、简单)做一个订阅发布的通道,可以供收集状态,推送服务Endpint的变更;服务消费者可以去治理中心或者Maven仓库获取契约、SDK,治理中心推送Endpoint下来,供路由进行Rpc调用,通过消费者也通过长连接协议来进行状态和统计信息的上报,供治理中心进行分析决策和反馈。
服务治理中心为了保证高可用性,通常使用Zookeeper这个流行的开源的基于Paxos的方案,当然最近渐渐流行起来的kebernetes的etcd是基于Raft的集群共享数据、也可以做服务的发现的解决方案。
随着这种分布式调用越来越频繁,就需要服务治理能力越来越强,否则就是一张混乱的、无序的Rpc调用的网,无法管理复杂度。
这里建立了服务治理的模型,在下图中的服务治理中心来实现,模型从这样几个角度来考虑如何治理服务,包括通信、契约、版本、监控、安全、交付等角度,依托服务治理中心,有了这套基础设施保驾护航,服务化就可以真正做到提高研发效率、提供优雅的开发体验。
[配图3]
在基础交付设施自动化上,如下图所示,体现在自动化、容器化交付这个流程中,在平台化的背景下把团队思维转换为DevOps式的,依托Docker和k8s完成了PaaS平台的对接,同时和QA一起协作完成持续交付流程的建立。
[配图4]
2.2架构设计规划
这里所指的架构,特指组织、服务的架构设计,非部署和代码架构。
下面我要介绍的,都是扣题,是已有系统的服务化改造,是一个已经存在的、复杂的、体量大的业务系统。
做架构设计规划,主要分为步骤:
#1整体架构设计
#2业务领域抽象、建模
#3服务规划与层次划分
#4服务内流程、数据、契约(接口)定义和技术选型。
这里主要介绍前三个步骤,第四个偏向于个例,同时需要强结合业务需求、特点分析解决,这里不做详细展开。
2.2.1整体架构设计
还记得文章开说所说的单体模型吗?
在一个复杂的、规模大的业务系统中,使用微服务化方式实现,就需要从上到下的来做整体架构,下面这张图是我所在的商业产品的业务端到检索端的架构图。
[配图5]
共分为5个层次。
第一层,模块化组装,是各个投放产品的门面,各个投放产品可以通过搭积木式的方式,组装下层服务,就可以完成一个面向用户的功能,最常见的SpringMVC技术、Java设计模式中的facade模式就属于应用到这一层的一些点。
第二层,计算服务层,服务化也就是在这个层次上展开的,每一个小圆圈都是一个微服务,这是整个服务化的核心,各个服务圈出来的都是一个个服务簇,比如投放管理一个簇,报告报表一个簇。
第三层,数据存储层,会针对各个业务拆分,按照物理库或者逻辑库进行隔离。
第四层,广告传输层,将多shard的MySQL写入的广告增量实时传输到检索端,形成一条增量流(incrementaldatastream),我们通过模拟为MySQL的一个从库来捕获解析binlog实现,将binlog增量映射为语言级别的抽象类型,供下游使用,下面一层就是一个数据接收方,其他的还包括一些MQ订阅方(如导入kafka、RMQ、ZeorMQ等),HDFS存储等,这样就形成了业务系统的数据快速、高效、实时传输的目的。
第五层,检索端。
是广告投放系统的核心,根据媒体环境、用户特征匹配最佳的广告,进行创意的投放,你所看到了图片、H5、flash广告都是这套系统响应的,可以做到千人前面,最佳化广告主ROI与用户体验的折衷。
2.2.2业务领域抽象建模
技术是为业务服务的,没有了业务,纯粹的讲技术都是纸上谈兵,解决问题是所有技术的出发点,微服务化也不例外。
服务于业务,就需要对业务有深刻的理解,技术才能形成良好的输出。
有了前一步的整体架构规划,下一步就是计算服务层中的微服务如何规划的问题,这部分最为复杂,需要深入到产品业务中。
拍脑袋规划当然可以,这叫做经验直觉主义,我认为经验主义缺少规范化的表达和标准化的设计,面对未来的修改需求,其架构的生命力不会很强。
所应该站在更高的视角上尝试解决,首先就是要规范化需求表达,下图就是一个投放实施的表达,使用巴克斯范式(BNF范式)表达,将投放实施分为受众、媒体、场景等定向的选择,每种定向又分为多个约束条件,逐层深入,这个规范是所有已有产品的萃取,在新产品的打造中需要遵守的,一般会和产品经理一起打造。
[配图6]
然后各个投放产品进行的功能矩阵划分的标准化设计,以这些为基础,就可以有理有据的进行服务规划,抽象分解出来的服务域高内聚,职责非常清晰,服务内的实体也是建模的,如下图所示,每个包都是一个微服务。
[配图7]
2.2.3服务规划与层次划分
基于对业务的抽象分解,在计算服务层内部,就可以进行更加细分的层次规划,先是垂直拆分为展现层、计算层、数据资源3大纵层,核心的计算层又细分为3个层次,包括业务流程处理层,通过组装下层服务完成功能;业务逻辑组件是自包含,跨产品线、高度复用的组件;下面公共服务组件是一些通用服务。
然后水平划分为多个服务簇。
如下图所示。
[配图8]
按照之前的服务规划,将各个微服务安置其中,最上层的web-ui和api服务负责和前端js以及客户端(安卓或者iOS)API打交道,中间例如推广管理作为一个业务流程处理组件的workflow,可以调用下面的微服务进行组织,完成一个投放流程的业务场景。
所有这些服务都是通过分布式服务化框架来进行通信、治理的。
2.3落地实施应用
下面是一个已有产品改造的案例,比如一个报表服务簇,过去是一个大单体,现在按照服务化的架构,进行拆分,最为核心的就是中间这个sync-report服务,它从olapengine中查询数据,然后通过merge字面数据,提供排序,过滤,分页功能。
围绕sync-report抽取了多个不同维度的缓存,保证了核心报表服务的高性能,同时上层,不管是web-ui还是api,都复用sync-report,这样上层就会很薄,不用再管那些复杂的查询逻辑,sync-report作为标准、规范的技术解决方案,做到了统一复用与专职专用,加速了研发效率和交付。
[配图9]
3.篇后语
本文所提倡的微服务,是结合作者所在team自身业务特点来说的,适合自身的场景,是建立在团队人员素质到了,有成熟的基础设施和框架、中间件辅助,流程也规范,包括CI、敏捷等,团队都做好了准确去做这个转变,有足够的能力来实施,微服务化也就是水到渠成的事了。
相反,小团队在前期或者野蛮生长时期,不宜选择微服务,不但影响效率还带来额外的复杂度。
成长型或者大公司,有成熟的流程、规范、基础设施、平台等,要想在整条交付链路上加速,就需要投入更多的资源保障微服务化,一切自动化了,能治理了,回头看来这一切就都是值得的,远期收益非常可观。
最后要说的是,架构只是标准、骨骼,对微服务的讨论不应该让我们忘记了更重要的问题,驱动软件项目成功和失败的重要因素。
软因素如团队中人的素质,以及他们如何彼此合作、沟通,这都会对是否使用微服务有很大的影响。
在纯技术层面上来讲,应该把重点放在干净的代码、完善到位的测试,并持续关注架构的演化进步,这才是一个软件工程师的根本职责。