转摘-谈谈后端业务系统的微服务化改造

谈谈后端业务系统的微服务化改造

做者 张旭 发布于 2016年4月29日 | 1 讨论html

1. 篇首语

业务系统是任何一个用户产品的必须组成,充当着一个门面的角色,用户的输入就是这个系统须要维护的,数据存取是整个系统的核心。例如,广告业务系统的输入是广告主的投放约束、定向条件,微博业务系统的输入是短文字、图片等。前端

在应用发展初期或者规模不大的状况下,有很是简单的实现方案,LNMP、JSP、PyWeb都是你能随口说出来的词,若是用某种架构方式来描述,那就能够称作单体模式(Monolithic,Martin Flower大神所提出的,后面还会介绍),而这些技术都是单体模式的成熟解决方案,它们可使你工做在“应用层”的最顶端,各类中间件、框架能让你省心地干好业务,开发人员能够经过“模块化”的手段来管理业务系统的复杂度,使他们之间解耦、复用。简单来讲,这个单体就是以下这种层次划分。git

表示层       前端(HTML+CSS+JS)                        
  |             |
逻辑层     业务系统(PHP、Java、Python是经常使用的语言)         
  |             |                               
数据层      数据库(MySQL)    

看起来很简单,对吧。诚然,业务系统在这里面还须要作不少,好比缓存、SQL优化、数据分区、系统安全工做,固然还有对于代码的维护和重构。这种工做方式能够很好的工做几年、甚至十年,可是若是业务发展很是快,在系统复杂度、业务规模、参与人数、代码腐化程度都不断上升的状况下,你会发现整个项目正陷于泥潭,PM/RD/QA/OP常常抱怨:github

"改个小功能,怎么要拉这么多模块?"web

"拉模块也就罢了,改的地方多,编译太慢了。"数据库

"慢也就算了,关键不知道怎么改,这代码太丑陋了,算了,为了知足PM的排期须要,凑合来吧。"编程

"凑合来了,QA发现bug,返工再返工,延期再延期。"canvas

"上线了,oh my god,报case了,性能有问题,原来是依赖的模块访问数据库用了for循环select。"后端

透过现象看本质,我总结了来看就这三点问题:设计模式

一、业务逻辑复杂耦合,开发维护成本高。

系统复杂度、规模、参与人数都和腐化程度成正比,单纯的靠模块化,后期来看会存在个别模块成为”大怪物“,臃肿不堪,粒度过粗,难以复用。

二、交付效率和质量低。

在敏捷和持续集成方法论、实践大行其道的现今,迭代的定期交付率、单测覆盖率都不尽如人意,线上问题频发。

三、非功能需求不达标。

非功能需求指标特指性能、可用性、可扩展性等方面,代码的腐化和缺乏维护、重构,以及没有代码洁癖的人污染下,必然致使性能逐渐降低,甚至出现不一样资源竞争的短板效应,形成整个系统crash,同时一个大怪物的伸缩性较差,不能随意横向扩展某个细分功能点。

我想任何人作架构都须要秉承“业务需求决定技术演化路线”的思路,那么这些暴露出来的现状和问题都驱动系统去转型,在系统和人之间找到一种最佳的合做模式,匹配已有的生产力和生成关系。正如软件开发学泰斗Kent Beck所说的:

“Design is there to enable you to keep changing the software easily in the long term” ,即“变化发生时设计被破坏的程度”

 

放眼业界,面对复杂的、大规模的、多人协做完成的业务系统,如何管理好这个复杂度,有不少方法,模块化、OSGI、传统服务化SOA等等,当今最佳实践的趋势仍是服务化,而微服务是最近火热起来的概念,有些人确定以为这不就是炒做嘛,可是无论黑猫白猫能抓耗子就是好猫,因此解决问题是重点,不要刻意去批评一些名字,那么本文要重点介绍的就是——如何作微服务化转型和改造。

在接下来说以前,要重点声明,本文并非推崇服务化,不鼓励单体模式,相反而是至关确定和支持单体模式,它模块依赖简单、一个发布包、部署于一个容器都使得构建应用很是的简单,在体量还不大的状况下,首先应该解决的是搭建好一套绝对稳定的基于模块化的平台,待体量逐渐长大,再去根据实际须要进行拆分,团队也随之变化(facebook的单体持续了很是长的时间,一是人员素质高,二就是基础平台建设的很是好)。再下个阶段体量大到饱受单体模式之苦,也应该先建设平台化服务,建设好以后,先按照大的粒度进行拆分,逐步再微服务化,不然,直接上服务化、甚至下面要说的微服务都是很是危险的,鲜有成功案例。

2. 微服务化改造

作改造通常要经历三个步骤:

第1、技术选型决策

第2、架构设计规划

第3、落地实施应用。

下面依次展开三个部分,重点介绍前两个步骤,有了这两个,落地应用也就顺水推舟的好作了。

2.1 技术选型决策

2.1.1 选择微服务化方式

选择服务化,众所周知就是SOA嘛,这是一种架构风格,重点在原则、理念、方法论等高思惟层次上,对于工具、框架、解决方案没有作强制限制,ESB、websercie(基于WSDL和SOAP/BPEL)这两种是企业中流行的,也是过去一直引领SOA的技术领头羊,可是随着互联网应用的发展,在敏捷快速迭代、高可用、高性能、高并发等方面要求愈来愈高,传统的SOA并不适合这种场景。那么,如今的互联网流行的实现方式是什么呢?一种最佳的实践方式就是微服务化(Micro Service)。

[配图1]

微服务就是一种SOA的实现方式而已,更加侧重于在服务的细分演化,是指引服务的具体落地方案层面的一种实践方式。过去不少互联网公司在实践,你能够把淘宝的dubbo、HSF,navi-rpc服务化框架看作比传统SOA更适用、更贴近微服务化实现的服务化框架,依赖这些框架能够方便的作服务化。这个趋势被Martin Flower大神所发现,而且提出了,大家这些不都是在作“微服务”嘛。

Martin对微服务这个术语(terminology)的解释是:

In short, the microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.

简而言之,微服务化就是以一系列小的服务来开发支撑一个应用的方法论,服务独立在本身的进程中,经过轻量级通讯机制交互(一般是走HTTP协议)。这些服务是围绕着业务上的组织结构来构建的,全自动的、独立部署。几乎看不到中心化的服务管理基础设施,可使用不一样的编程语言和数据存储技术来实现不一样的服务。

在简单的一种理解来自于一本书《Building Microservices》(Sam Newman, O’Reilly Media),Microservices are small, autonomous services that work together. 微服务化就是一堆小而自治的服务,让他们一块儿工做起来。

相比于传统的SOA,Martin的总结特色能够参考他的博客还有视频(Youtube连接),一共是9个特色,这里不想赘述,而是说说我我的的理解,微服务化的特色在于:

一、模块即服务

微服务中的组件在逻辑或者物理层次更趋于细分,这个细分不是极致的,而是一种粒度适中的选择,一般这些组件在前期能够是一些模块,可是当须要时,例如业务上须要拆分独立,或者非功能需求上须要扩容等,均可以灵活的拆解出来。这个特色很是重要,由于业务系统中模块化实践,随着软件规模的变大,很容易绕过障碍而使得不一样模块耦合、依赖关系复杂,这种纪律性很难保证,从而削弱模块化的结构、下降了团队的生产力(敏捷开发和持续交付愈来愈难作,部署起来太庞大了你们的开发士气不高,并且痛苦),很快的这个模块就会变成一个大杂烩,而服务能够作到自然的壁垒,仅仅经过交换契约(一般是API或者proto)来作交互,这是一个演化的过程,不只有利于分而治之,到达复用的目的,同时老系统也能够灰度的改造剥离。

二、独立自治

这意味着服务是独立开发,独立测试,独立发布,独立部署,独立运维的,某个细分团队负责整个生命周期管理,这就是”康威定律(Conway’s law)”的通俗解释,官方解释是“一个组织的设计成果,其结构每每对应于这个组织中的沟通结构”,服务的规划不就是多人、跨团队协做的沟通模式嘛。好处在于摒弃原来的火车模型(全部模块一块儿发布部署),拥抱独立快跑,这也更好的支持了敏捷和持续集成的方法实践。同时去除了牵一发而动全身的问题,单一职责的来进行修改需求或者重构一个点,开发和构建方便,不影响整个产品的功能,一个bug不会crash掉整个产品,针对不一样的类型,区分计算密集型仍是I/O密集型,区分业务上更好使用关系型仍是NoSQL,区分2/8原则、即80%常常修改的服务独立出来自成一家,区分短板功能、针对瓶颈能够作水平扩展、避免资源竞争,甚至能够区分技术栈、突破语言限制。最后,这也是和第一点遥相呼应的,独立的服务能够实现很是大程度上的复用,服务之间依赖轻量级的接口,而不是模块。

三、去中心化的数据管理

在单体模式中,一个应用面对一套数据库,数据库能够按照物理拆分,进行shard分区,或者按照逻辑库隔离,不一样的业务路由到不一样的库,同时作一主多从等结构上的设计,这些原则在微服务中仍然适用,只不过微服务在服务拆分的同时,也须要将数据库分离,独立的服务维护独立的数据库,这对数据库也是减负,同时技术选型、SLA保证都会区分开来,把精力留给那些重要的业务数据库,进行分级的对待,而不能像之前同样一视同仁,一个不重要的逻辑库的bad SQL慢查询,阻塞了其余正常的查询,这是彻底能够避免的。

四、轻量级的通讯协议

传统的SOA使用ESB或者Webservice这种重量级的解决方案,微服务推荐使用一些更轻的解决方案,要通用性,能够用Restful架构,走HTTP通道,支持Json序列化协议;要高性能,能够考虑一些高性能的I/O模型,例如epoll、Actor等,能够直接走tcp通道,使用protobuf序列化协议,同时保持长链接(这里有一个例子Navi-pbrpc就是一个这样的具体落地框架);要异步,用可靠持久的RabbitMQ或者高性能的ZeroMQ来作P2P、Pub/Sub、广播broadcast消息通讯。而这种轻量级还须要体如今代码调用中,模块化直接经过函数、方法调用便可,服务化后能不能在API层面作到无侵入,无缝的切换、简单配置,这些都是服务化框架要支持的。

五、为失败设计

服务化调用从进程内in-process的调用,转变为跨进程的分布式调用,这种由分布式特性引发的自然不可靠性,须要变为相对可控。也就是服务间的通讯要假设不会成功,为失败处理。异常的传递,可否透过RPC,在调用方本地还原,就像函数、方法调用同样?一个点、或者服务的处理错误率到了一个阈值,为了避免影响整个产品,要作错误隔离,能够考虑熔断(circut break)、舱壁隔离模式、限流、回退等手段,最后还有一个幂等性问题,重试的调用会不会对业务形成影响,这个要具体问题具体分析了。

六、基础交付设施自动化

这个特色是整个微服务中的最大亮点,包括持续集成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写入的广告增量实时传输到检索端,造成一条增量流(incremental data stream),咱们经过模拟为MySQL的一个从库来捕获解析binlog实现,将binlog增量映射为语言级别的抽象类型,供下游使用,下面一层就是一个数据接收方,其余的还包括一些MQ订阅方(如导入kafka、RMQ、ZeorMQ等),HDFS存储等,这样就造成了业务系统的数据快速、高效、实时传输的目的。

第五层,检索端。是广告投放系统的核心,根据媒体环境、用户特征匹配最佳的广告,进行创意的投放,你所看到了图片、H五、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服务,它从olap engine中查询数据,而后经过merge字面数据,提供排序,过滤,分页功能。围绕sync-report抽取了多个不一样维度的缓存,保证了核心报表服务的高性能,同时上层,无论是web-ui仍是api,都复用sync-report,这样上层就会很薄,不用再管那些复杂的查询逻辑,sync-report做为标准、规范的技术解决方案,作到了统一复用与专职专用,加速了研发效率和交付。

[配图9]

(点击放大图像)

3. 篇后语

本文所提倡的微服务,是结合做者所在team自身业务特色来讲的,适合自身的场景,是创建在团队人员素质到了,有成熟的基础设施和框架、中间件辅助,流程也规范,包括CI、敏捷等,团队都作好了准确去作这个转变,有足够的能力来实施,微服务化也就是水到渠成的事了。相反,小团队在前期或者野蛮生长时期,不宜选择微服务,不但影响效率还带来额外的复杂度。成长型或者大公司,有成熟的流程、规范、基础设施、平台等,要想在整条交付链路上加速,就须要投入更多的资源保障微服务化,一切自动化了,能治理了,回头看来这一切就都是值得的,远期收益很是可观。

最后要说的是,架构只是标准、骨骼,对微服务的讨论不该该让咱们忘记了更重要的问题,驱动软件项目成功和失败的重要因素。软因素如团队中人的素质,以及他们如何彼此合做、沟通,这都会对是否使用微服务有很大的影响。在纯技术层面上来说,应该把重点放在干净的代码、完善到位的测试,并持续关注架构的演化进步,这才是一个软件工程师的根本职责。

相关文章
相关标签/搜索