@gaoxiaoyunwei2017
2019-06-18T11:21:35.000000Z
字数 7216
阅读 505
白凡
分享:和坚
编辑:白凡
感谢大家,今天给大家分享的这个主题叫做过早拆分微服务是万恶之源,我们公司中文名翻译的确实我不喜欢,大家如果知道的话,肯定知道我们公司背后的背景了,如果不知道的话也可以了解一下。今天的过早拆分微服务是万恶之源主题,其实这个思想思路来自我最近翻译的一本书,这本书是写微服务,作者认为过早拆分系万恶之源,这几年我一直包括像招行、华为从微服务划分、规划到服务的实施和落地相关的工地,包括也给平安、广发企业做微服务的咨询,真的是有比较深刻的体会,我觉得这个话是当时点到我了,确实不能过早拆分。
刚开始先简单介绍一下我自己,前面这段话我就不多介绍了,最近比较好玩的事情,因为到年底了,我们参加的分享也相对比较多一点,这两个月大概参加3场分享,在朋友圈做了自我宣传,最近两个月我要做3场分享,其中每场主题都跟微服务有关,好多同事、朋友干这行的就纷纷说这个事怎么做的,也很有兴趣,我朋友圈有一些我的邻居,有一个邻居比我大1-2岁,他们在深圳南油做服装工厂的,据我了解他们工厂肯定不会用软件系统、系统架构的东西,也不能有软件开发人员,他说能不能来听听,我说行,没有问你想来就来,微服务是,您知道吗?他说知道,现在卖服装不好卖,动不动就搞微商,他说微服务就是给电商做服务的。我们是做基础设施,我们每天加班,我比较喜欢这句话“结硬寨打呆仗”,我觉得至少给我们在辛苦做的工程师们一些掌声鼓励吧。
今天大概分享分三块东西,简单介绍一下,第一先谈一下微服务的历史,这个概念提出以及哲学思路究竟怎么来的。第二块扣今天的主题,为什么我们说不要过早拆分微服务,里面有一些逻辑的,第三块如果不要过早拆分微服务,我们在做微服务系统和架构的时候,我们的正确姿势应该是什么?最后我们做简单总结,主要是三块东西。
首先看一下微服务的简史,我们知道我们所做的无论在微服务之前包括以后微服务都会遇到的问题,就是软件系统孵化的问题,刚开始我们在做一个系统的时候,很简单一张表写点DAO这些东西,界面应用就出现了,然后四五张表,后面加更多的表、更多的业务,我们的业务需求每天都在增加,再往后加就变成了最后的头发丝,系统五年以上,大家看每个系统都有这种感觉,纷乱复杂,毫无头绪,为什么会这样呢?本质原因,我认为它是符合来自于物理学的定义叫做熵,这是必然的现象。
我们应对软件系统孵化的问题的时候,我们采用的方式是什么呢?我们看一下非软件系统怎么做的?人类应对这些复杂系统是怎么处理的?最复杂的就是人类组织结构,比如公司组织结构,刚开始3-5个人,人多一点就多了各种部门,里面组织是怎么进行管理以及运作的,他们是怎么运营处理的,他们采用分而制止,就拆小了之后,我至少不要求有一个人对所有组织都清楚,但是对一个管理者来说下面有几个大部门,这几个大部门对我负责,大部门有几个小部门。我们工程师借鉴这种思想,我们刚开始是大写的单体机,这是上世纪60、70年代产生的东西,一个机器比一个房间还大,开始的时候有服务端、客户端分离,其实这个时代的过程我觉得系必然性,原因就是我们尝试在用我们人类已有的一些经验,尝试应用到软件系统领域,解决我们面对的一些复杂性问题,解决复杂性问题,人类现在最好的方式,我们能干的事情就是降低复杂度,那就是拆。
原来单体架构会出现一些优点和问题,最好的好处是很快,再往后随着我的时间越来越长,我的系统复杂度开始出现增加,这块前几天跟一个朋友在聊这个东西,我说你系统好复杂,你说我的系统更复杂,怎么衡量哪个更复杂呢,这个没有量化标准,最近我打算针对这个问题做深入研究,看看有没有合适算法解决这个事情,我觉得系统复杂度是系统之间模块也好或者其他的一些单元也好他们之间的关联关系,关联关系越多,意味着这个系统越复杂,所以所这系统的发展,复杂度也越来高,代码量也越来越高,最后导致结果就是项目演进速度越来越慢,原来三五天做一个功能很快,到后面说业务人员要新增加一个功能,然后你说要需要一个月,然后人家说你开玩笑吧,因为一个属性一个字段好多代码都会受到影响,这是我们很多复杂性,经常会面临这样的问题。
针对单体架构的问题,我们是怎么进行解决的呢?说到微服务的哲学原理,微服务的架构提出是随着这批软件架构师一起核心思想一起演进而来的,并不是凭空出来的方案,这本书大家有没有看过?我以前碰过一个大师跟我聊,如果打算以后干工程师程序员的话,最好买一本,看了之后确实很好,讲了底层软件设计思路和设计思想针对程序员来说有核心的关系,就是DO ONE THING WELL。做一件事情就要把这件事情做好。
微服务有这些好处,但它并不是免费的,实施微服务有难点,整个难点会出现的问题,首先第一点服务划分怎么做,原来一个单体挺好的,我不需要考虑部署几个服务,那么服务怎么划分,第二个难点怎么部署,这么多服务一起上线,怎么搞,第三个难点怎么做测试,我一个服务的话,可能我在一个API跑暴露出请求的话,后面要调用3-5个请求,这些其实都是微服务的难点。
我们对微服务来说业界存在误解,我们经常包括我在跟华为、招行同行开发者架构师聊的时候,他们说他们很熟悉微服务,他们关注的点都是我们用API Gateway、Spring Boot等,会用工具不代表理解微服务架构的精神和意图,微服务架构不仅仅把一些工具拿出来,如果说把这些工具拿出来就不会有阿里中台的概念,这些跟原来的没有本质区别,只是一个工具,更重要的是怎么用这些工具帮助我们做软件开发,进行软件工程,也是微服务要干的事情。
微服务具有哪些特征呢?微服务正式提出来是哪年?2013年,他们提出来这个概念,虽然说两个人是大牛,有时候我说他们说话就是滴水不露,他们说微服务是软件架构风格,这种现在架构风格使用一组服务构建软件应用,虽然没有给出一个精确的微服务定义,但是有如下特征,我就不告诉你微服务是什么,但是我告诉你微服务做出来有哪些特征,你只告诉结果,不告诉我怎么做,这就是大师的特点,在接下来的特征里面有如下的一些,包括跟今天主题有关的,DevOps、去中心化的治理、去中心化的管理、容错、演进式设计,最核心的一点微服务解决的问题是你的微服务应该要围绕着你的业务能力进行建设,就是你的微服务要对应你的业务,甚至更深一步,我们预测随着微服务这波技术浪潮的兴起,将来有一天会导致的结果这波技术反过来会影响组织结构,阿里提出的中台战略已经在影响组织结构了,康威定律就是讲一个组织做出来的系统肯定跟这个组织的组织结构有关系的,我们提出反康威定律,我们认为一些技术会影响这个组织的组织结构,而微服务就是这样的一种技术。未来会感受越来所有你组织内部要进行一些事情,承担的职责和能力都会以微服务作为单元进行建设,我们把它加快一体化团队,从产品设计、开发、上线、运营都是独立完成的。
为什么不要过早拆分?我们觉得先不要着急,因为在拆的时候会有几个问题,首先一个系统在拆的时候第一件事情很难界定服务的边界,我最常见的是什么?我反正不知道你们有过什么样的经验我见过很多经验,5年系统进去让我最头疼的是大宽表,一个表四五百个字段,我至少见过的大部分字段都是这样,你存在的职责过多了,为什么会有大宽表,简单来说好用,但是不知道怎么去查。
我们现在在电商领域有一个产品,这是一个产品的概念,现在市场销售进来的话,要给产品定价格,产品是不是要加一个价格属性,供应商进来的话,要给我去进行供货,我是不是要加产品供货路径或者供货价格,产品要物流的话,是不是要加物流的信息,这张宽表就逐渐膨胀起来了,这个问题不是这么解的,我们需要考虑到产品这个概念应该是要划分到不同的业务领域里面是不同的上下文,我们需要有一个边界,而在每个边界里面都要有独立产品概念,大家可能会共享一部分数据,但是每个人在操作的时候都应该操作自己和产品相关的属性,别人的属性跟你无关,我物流是不关心你产品价值的。
第二个原因是我们去发现这是实际因为这几年,因为我知道的在市场来说,像我们公司做的广发、招行、华为都在做微服务,行业内像平安、中信、华润都来找我们说要做微服务,我们在实践工作中发现一个问题,有时候着急的时候微服务是拆,结果拆完了发现这两个服务当时好像不应该拆,要把它合掉,合的时候发现麻烦大了,同一个模块,本来功能比较类似,拆出去各自有这样的东西,合在一起发现两个对象,两边的属性是冲突的,部署的时候也是,原来可能是已经设计好我的部署流水线了,现在是一个,现在要调多少代码,要把流水线要调多少代码,API之间调用关系,我们现在软件系统会有一个问题,一旦设计完成之后,我们倾向于尽可能少的改动,一旦发生架构级别的大调,像合并、拆分就会非常痛苦,这几年大家敢于做拆分调整,大家就是觉得这样是可行的,所以大家愿意做这件事情。未来我们发现拆的不合适,发现合的时候比拆的成本还高的时候,这个时候跟业务主管或公司老板说,还要合起来,还需要2个月时间,到时候老板肯定会不高兴的。
第三个我们在现实世界中会经常发现一件事情,前段时间我去华为做微服务的咨询,他们说赶紧帮我们看看我们拆了30个微服务,这够微了吧?我当时想你做拆多少个跟你做不做微服务没有关系。另外,现在还是遇到一个情况,我相信业界大部分人心里没底,这样拆合不合理,未来如果发现不合理的话,改进的话,改进的成本比较高,我比较担心我这样做合不合理,还有一个情况有人发现现在我就是做这个业务,两个服务之间相互调用了20次API请求,这个例子比较特殊,常见的我会见到两个服务连续掉了四五次API。这个在拆的时候会出现一些问题。
还有一种情况再我们往后发展,在未来往下一步走的时候,说微服务系统拆好了,现在系统迭代速度比较快,演进速度比原来好,性能也好了,过了一左右,业务说现在提出一个小需求,你现在告诉我你们两个月才能弄出来,市场跟不上,这个时候你可以直接告诉他,你要需求的话,我要改5个微服务,那业务也受不了,我们想这件事情的时候我们发现了一个问题,这是我们很多服务过的客户在做微服务拆分的时候,大家的关注点其实或者说使用的方式是有点点问题的,因为我们之前习惯了做小单体。
所以说在拆微服务的时候,我们想当然的认为我用做单体的方式把原来单体功能模块一个个拆分出来做成一个个微服务,这就叫微服务了,我们用单体的方式做微服务,这样并没有达到微服务的精髓,而我刚才介绍微服务定义特征最和新的是围绕业务组织建设,如果做不到跟业务之间的耦合和绑定来说的话,我觉得这个微服务其实只是技术部门在玩的工具而已,业务部门还是不懂,还是不知道你在干什么。
什么是真正的微服务呢?过早拆分有这么多问题,也简单的分析了原因,这些原因是在微服务设计的时候面临一些挑战,这些挑战,我们认为其实把微服务换成软件开发同样适用,我们在做软件系统的时候怎么做到低耦合高内聚,经常说的词,怎么样做到系统职责是清晰的,以及怎么控制系统复杂度。
怎么做呢?今天不是专门讲DDD,所以我就简单给大家算是带一个简介的方式给大家介绍这样的工具,大家有知道领域驱动设计的吗?还不错,有一半人都知道。领域驱动设计是在2003年就提出来了,那个时候我们在做软件系统的时候,这不是中国的难题,在欧美都有面临这样的问题,技术部门需要把业务部门的需求翻译过来设计成自己的系统,当业务部门提出需求或变更的时候,要么他很难把现有设计原翻译回给业务部门,要么就是业务需求很难在现有基础上很难实现,这个时候他们就琢磨有没有办法把软件系统架构直接和业务系统有关联关系,两者之间有绑定关系。顺着这个思路形成了一整套完整框架,分战略设计和战术层面,这是一个简单针对与领域驱动设计的情况。
在社区内,包括我们的友商,我们做微服务的咨询,但凡出去讲微服务都会把DDD拿出来。现在在社区内DDD确实已经是微服务的最佳实践了,根据我个人实践,我了解过友商的模型,有叫微模型的,在了解过了之后进行对比的时候,发现DDD确实会有更大的优势,尤其是在系统演进方面会更容易进行维护。
DDD核心诉求是什么呢?我刚才提到一个词“绑定”,我在业务上有一个产品,你在技术呈现里面也应该有一个产品,对你来说你很容易知道给哪个模型增加哪个属性,比如说一个保险产品,我计算价格的时候,肯定要有计算价格的方法,我说给产品计算价格方法,我需要知道怎么找到产品对应实体增加计算方法的行为,就是让我的业务架构和系统架构之间其实是对等的。
DDD要实现这点来说肯定要有基本的原则,有哪几养呢?第一聚焦核心域,在战略设计里面会有领域的组概念,在领域下面会有子域,而在这个里面我们用车的例子进行比方,核心子域就是车的发动机,像轮胎是支撑整个车运行的,可能会变成我支撑的功能,所以是支撑的子域,而车窗很容易更换厂家,会服务于其他很多子域,这是通用子域,为什么要聚焦核心域呢?我们加班最多的基本上是各个IT楼下,每天晚上到下班时间,一堆的士车等着,这是什么原因呢?这里面其实是经济学的基本概念,凡是资源皆是稀缺,所以说当我们希望用稀缺资源干更多的事情来说的话,基本有两个选择,一个增加更多的人,另外让单体通过增加工作时间解决这个事情,怎么样解决这个问题呢?我们认为DDD核心提出一个概念我们要聚焦核心域,我们首先为什么把这张图放在最前面呢?我们认为首先作为一个企业或者组织你要识别出来是最关键最重要你要让你最核心的开发资源投入到这上面来。
第二个我们认为整个模型是我们一步一步探索的,传统模型设计,庞大的设计基于所有未来的假设需求。迭代探索模式,根据需求的变化不断演进。我们要让业务一起参与进来,设计模型、设计实体不是我们开发自己玩的东西,业务一起进来,我让你知道你说的需求会有什么样的实施项、会有什么样的实体,他们会有什么样的行为,你自己就知道了当我增加功能的时候,要找到哪个模型增加哪个东西,这对大家来说可能会有点困难,但这是趋势,我们需要让业务开始更熟悉开发一些模型设计概念。
当然要实现这个目的需要下面这个原则,大家要有统一语言,要定一些语法规则,我要确定业务说的东西和你技术说的东西是同样的东西,经常在开发过程中,我特别头疼害怕的一件事就是看见一个产品经理和开发争了半天,开发受不了就说我跟你解释不清楚,我给你打个比方,这个比方我就知道完了,两个人针对比方就继续争下去了。所以说在整个软件开发和模型开发过程中,双方最好有一个统一语言,能够进行沟通和协作交流。
刚才讲了这么多,简单介绍一下,其实上面都是一些基本的原则和概念,我简单介绍一下DDD和微服务怎么对应的呢?我举个例子,现在在做一个支付系统,整个支付系统可能会有支付的子域,会通过线下文做边界,在这个边界加入一个新的概念,叫做聚合,现在会有支付聚合、账户聚合、日志聚合,聚合的概念就是一堆行为、属性、逻辑都应该放在在一起,其他人要访问的话,必须通过聚合根进来,这个要求在设计阶段就开始已经要让我们开发和BA要知道的概念就是要聚合,要清楚知道这个业务是属于哪个聚合的。
最后要划分到微服务,我们通常一般建议来说是以限界上下文划分,会包含多个聚合,如果把这个范围缩小到聚合范围内,实践中也不是不可能,但是对于团队整个部署和实施的难度会加大,如果把它放大,放到支付子域,你就会发现变成一个单体,上下文刚好限定了我是在某一个情景下使用的功能。
基于这样的对应关系,如果我们做出这样的系统,可能会面临一个问题,当要进行拆分的时候会发生什么事情?现在在一个支付微服务里面,支付聚合、账户聚合、日志愈合,业务要求,当一笔支付完成之后,需要更新账户里面属性信息,我还需要把这笔交易写入日志,我这个时候在实现的时候采用什么方式呢?原本按照MVC会有一个服务去做这样的事情,但是现在来说在聚合的体系下,我们要求相互之间最好不要有强行关联,支付已提交,这个会发布给事件发布器,通知账户聚合和日志聚合,从本质来说根本不知道日志聚合,但我知道要接受一个事件,现在告诉我一个事件叫做支付已提交,我要从这个里面提取哪些数据。有一天我发现我的日志越来越大,需要把日志拆出来,拆成日志上下文,我只需要很简单的日志聚合独立出来,把我的事件发布器也独立成微服务,你们会发现移动代码和进行微服务柴分架构变化会非常容易,而它在响应业务变化的时候也会非常快,这不是给大家针对于今天分享内容专门做的例子和PPT,这是我们从实际项目中挑出来。
回到今天的主题,过早拆分微服务是万恶之源,为什么提这样的话题呢?其实我们想说,我们回归到微服务的特征,微服务的核心利益是什么?左边是我们原来没有引入聚合概念的系统,系统之间的耦合会非常复杂,而基于其中任何一个对象的修改来说可能都涉及到其他的三个对象,都有关联关系,如果引入聚合概念的话,聚合和聚合是通过聚合根访问的时候,会发生什么?关联关系会降低,引入聚合之后,关联关系会降低。这是微服务架构带来核心收益就是通过降低复杂度,通过聚合概念能够让微服务更好的拆,未来当业务发生架构演变的话,它变得更加容易和简单了。
最后我把英文的原文列出来了,Premature Splitting is the root of oll evil,我们通过微服务帮助业务系统更好更快的演进,我们关注点是怎么样才能够帮助我们的系统孵化更慢一点,怎么样能够让我们的业务演进和迭代速度更快一点。
最后是DDD彩蛋,简单介绍市面相关书籍,如果有钱的话更喜欢大家找我们斯特沃克。第一本书《Domain-Driven DESIGN》是原著,第二是《实现领域驱动设计》,第三是《领域驱动设计模式、原理与实践》,后面两本比较容易理解,有了基础之后再去看DDD原著会有更深的体会。好,今天到此。