第十周作业
1. 画出Dubbo进行一次微服务调用的时序图
2. 关于微服务架构,你有什么样的思考和认知?
中台 = 适应各种场景的通用服务;
例如:每个平台的开发都需要用户,鉴权等服务,这些特别通用的服务,可以经过完善,让所有系统都依赖该服务。有了中台服务,可以快速搭建起其它系统,基础的服务都有了,调用就行。
微服务与中台最重要的就是服务如何拆分。以下为微服务拆分方法以及DDD。
微服务拆分方法/维度
基于性能拆分
对性能要求过高的功能可以组成一个服务,单独拆分出来,多部署几份,可以解决以web容器为性能瓶颈的问题。
基于业务变化频率
对经常变化的业务组成一个服务,单独拆分出来,与原有稳定的功能不互相影响。
基于业务拆分
将不同的业务放在不同的模块,每个模块作为单独的微服务,可以使用DDD设计微服务。
微服务与DDD的关系
DDD是一种架构设计方法,微服务则是一种架构风格。
DDD关注从业务视角,划分领域边界,使用通用语言高效沟通。
微服务关注服务进程通信、容错、故障隔离、构建/部署、开发、测试、中心化服务治理。
使用DDD可以更科学的划分领域边界,从而实现微服务的拆分。
DDD能解决那些问题
使用DDD设计方法可以合理的将不同的功能划分到不同的上下文边界内。
一个边界上下文也可以被认为一个组件或者一个模块,在DDD中被叫做一个子领域。
可以让系统模块化、组件化的进行开发。
DDD战略设计
战略设计从业务视角出发,建立业务领域模型,划分领域边界,上下文边界内建立通用语言,上下文边界可以作为微服务拆分参考(抄过来的说法)。
个人理解
划分:
将业务分成不同的块,将不同的业务块放到不同的模块中。
将完整的业务分成了很多个模块,模块也可以说是上下文边界。
按照学习面向对象的方法来说就是将不同的功能/方法放到不同的类中去,也就是说将关联性较强,内聚的功能放到一个类中去,这样才可以达类高内聚低耦合的目的。
面向对象与业务拆分的关系也只是粒度不同,上下文边界的拆分粒度要稍大些,可以将相同概念,多个符合单一职责的块放在一起形成一个上下文边界。
通用语言:
将业务人员与开发人员描述事物的语言进行统一,每个人都使用这个通用语言沟通。
沟通时,需要在一个上下文边界内进行沟通。
边界上下文:
就是一个环境,例如 一件事情你做的很好,别人说你厉害;一件事你做的很烂,别人还是说你厉害;
事情做的好不好就是一个环境,在不同的环境同样的词语,意义是不一样的。
所以需要在一个环境/上下文边界内,说通用语言,才能确定这个通用语言所表达的具体含义。
DDD战术设计
将划分好的多个上下文边界进行代码设计实现,DDD提倡使用充血模型,有一些常见的架构,例如六边形啊等等。
DDD与微服务总结
DDD可以用于微服务的拆分,也可以用于单体应用的模块拆分;
微服务只是一种部署形式,如果本身项目就没有经过战略设计进行模块化的划分,拆成微服务只会让项目的问题进一步被放大。
战略设计非常重要,可以不使用战术设计进行贫血模型进行开发,至少要使用战略设计让你的系统看上去是一块一块的,像积木一样,而不应该是一坨一坨的。
DDD思想很贴近面向对象,像是我们自己给自己提出一个简单的需求,例如将文件的数据读取出来解析为实体对象。
我们从面向对象角度来分析,以上需求有以下操作 ,读取数据、将数据解析为实体对象。
读取数据和解析对象就是两个操作,放到两个不同的类中。
从DDD角度分析也是这样,不过DDD提供了更加完善的整套解决方案。
像是DDD领域事件,本质上就是观察者模式。
个人认为DDD就是面向对象是互补关系,面向对象提供一些设计原则,模式等等,偏重设计。
而DDD偏重与业务人员沟通,它们有一个共同点就是将不同的东西放分到不同的类/上下文边界中。
微服务可以解决的问题
1. 编译部署困难
巨无霸应用通常编译就需要消耗一定的时间,可能修改了一行代码或者一个模块就需要重新编译打包并且部署,编译成本十分高。微服务只需要编译修改的服务,独立部署即可,一个服务的代码并不会特别多,比起整个应用肯定会少很多。
2. 新增业务困难
想要在一个乱如麻的系统中新增业务,维护旧功能,难度很大。
个人感想:
我没有经历过特别大的系统,但是经历过那些业务逻辑复杂,经过很多人改过的一个系统,一个类就有几千行代码,简直不敢直视。
要说添加一个新功能,我可以了解数据库表后,就可以开干,能不复用原有代码就不复用原有代码,全不自己写,开发效率还能高点,这样做之后代码只会越来越多,工程越来越庞大,重复的功能也越来越多。包也会越来越多,当时为了不跟他们的类搅在一块自己新建包后进行开发。
要说维护那是真的很恶心,哪块代码出了bug,哪块功能需要微调,代码根本不敢动,动了这一块可能这个功能好了,但是其它的功能莫名其妙的出了问题。
如果代码耦合严重,系统乱如麻,微服务并没有办法解决这样的问题,只会让问题更明显,更严重。
3. 数据库连接耗尽
所有业务都在一个应用中,连接一个数据库,大量的访问直接会耗尽数据库连接,而数据库连接是有限的,就会导致大量的请求在等待导致请求超时。微服务不同的服务有不同的数据库进行支撑,不同的服务有单独的数据库连接池。
4. 技术栈受限
不同的语言会有不同语言的优势,根据当时团队的情况也可能会出现多种语言进行开发,微服务可以支持多种语言开发,只要提供服务即可。单体应用只支持单种语言。
5. 功能复用
可以单独拆出通用的模块供很多项目进行使用,可以独立部署这些通用的模块。单体应用只能整个部署,数据库也需要进行配套,导致很多不相关的功能和不想管的数据库表,就像类设计违反了接口隔离原则。
6. 按需伸缩
需要高性能标准的服务可以多部署几份,将不是特别重要的模块部署一份,当然为了高可用最少还是部署两份。
7. 故障隔离
单体应用因为OOM导致应用的所有功能都不可用,微服务将应用拆成了多个块,彼此之间并不影响,例如用户服务OOM,并不会影响到订单服务。
充血模型与贫血模型
充血模型与贫血模型本质就是面向过程与面向对象。
面向对象以类为思考对象。在进行面向对象编程时的时候,我们并不是一上来就去思考如何将复杂的流程拆解为一个一个方法。先去思考如何给业务建模,如何将需求翻译为类,如何给类之间建立交互关系,而完成这些工作完全不用考虑错综复杂的处理流程。当我们有了类的设计之后,然后再像搭积木一样,按照处理流程,将类组装起来形成整个程序。
面向对象更加能够应对大规模复杂程序的开发。
DDD本身就是用来应对高度复杂的系统,所以战术设计提倡充血模型。
贫血模型Demo
充血模型Demo
总结
以上代码逻辑很简单,当遇到特别复杂的逻辑时,Service代码会特别多,查找某段逻辑也会略显困难,看起来也不直观。
而充血模型所有的方法都在Order中,看起来非常直观。
贫血模型的功能无法复用,一个Service方法中那么多代码,如果懂得封装,打折啊等等操作使用策略模式设计以下还好,如果全堆在Service中,就很麻烦了。
贫血模型是面向过程的,自然不符合面向对象设计原则。
面向过程也不全面向过程,例如加入打折功能也可以使用策略模式进行打折策略封装。
使用哪种方式需要考虑当前项目属性以及团队属性。
评论