微服务和 DDD 总结
1、微服务
巨无霸应用系统带来的问题
1)编译、部署困难。
2)代码分支管理困难,merge冲突,发布的时候问题互相纠缠,顾此失彼,每次发布都要半夜三更。
3)数据库连接耗尽。
4)新增业务困难。都是雷区,老人忙得要死,新人一帮忙就容易添乱。
解决方案就是拆分,将模块独立部署,降低系统藕合性
纵向拆分:将一个大应用拆分为多个小应用,如果新增业务较为独立,那么就直接将其设计部署为一个独立的Web应用系统。
横向拆分:将复用的业务拆分出来,独立部署为微服务,新增业务只需要调用这些微服务即可快速搭建一个应用系统。
微服务框架的需求
对于大型互联网系统,除了Web Service所规范的服务注册与发现,服务调用等标准功能,还需要微服务框架能够支持:
失效转移(Fail Over):
对于大型网站的微服务而言,即使是很少访问的简单服务,也需要集群部署,同时微服务框架还需要支持服务提供者的失效转移机制,以实现服务高可用。
负载均衡:
对于集群部署的服务提供者,服务请求者可以使用加权轮询等手段访问,使服务提供者集群实现负载均衡。
高效的远程通信:
对于大型网站,核心服务每天的调用次数会达到数以亿计,如果没有高效的远程通信手段,服务调用可能会成为整个系统性能的瓶颈。
对应用最少侵入:
网站技术是为业务服务的,是否使用微服务需要根据业务发展规划,微服务也需要渐进式的演化,甚至会出现反复,即使用了微服务后又退回到集中式部署,微服务框架需要支持这种渐进式演化和反复。当然服务模块本身需要支持可集中式部署,也可分布式部署。
版本管理:
为了应对快速变化的需求,服务版本升级不可避免,如果仅仅是服务实现升级,那么这种升级对服务请求者而言是透明的,无需关注。但是如果服务的访问接口发生变化,就需要服务请求者和服务提供者同时升级才不会导致服务调用失败。企业应用系统可以申请停机维护,同时升级接口,而网站服务不可能中断,需要服务提供者先升级接口,并同时提供历史版本的服务供请求者调用,当请求者访问接口升级后才可以关闭历史版本服务。
微服务框架Dubbo架构
微服务架构落地要求
业务先行,先理顺业务边界和依赖,技术是手段而不是目的。
先有独立的模块,后有分布式的服务。
业务藕合严重,逻辑复杂多变的系统进行微服务重构要谨慎。
要搞清楚实施微服务的目的是什么,业务复用?开发边界清晰?分布式集群提升性能?
2、DDD
很多项目的实际情况
用户或者产品经理的需求零零散散,不断变更。
工程师在各处代码中寻找可以实现这些需求变更的代码,修修补补。
软件只有需求分析,并没有真正的设计,系统没有一个统一的领域模型维持其内在的逻辑一致性。
功能特性并不是按照领域模型内在的逻辑设计,而是按照各色人等自己的主观想象设计。
项目时间一长,各种困难重重,需求不断延期,线上bug不断,管理者考虑是不是要推倒重来,而程序员则考虑是不是要跑路。
贫血模型VS充血模型
由于事务脚本模式中用时传递的数值对象Service, Dao这些对象只有方法,没有数值成员变量,而方法调比如Contract,没有方法(或者只有一些getter, setter方法),因此事务脚本又被称作贫血模型。
领域模型的对象则包含了对象的数据和计算逻辑,比如合同对象,既包含合同数据,也包含合同相关的计算。因此从面向对象的角度看,领域模型才是真正的面向对象。收入确认是和合同强相关的,是合同对象的一个职责,那么合同对象就应该提供一个calculateRecognition方法计算收入。
领域模型是合并了行为和数据的领域的对象模型。通过领域模型对象的交互完成业务逻辑的实现,也就是说,设计好了领域模型对象,也就设计好了业务逻辑实现。和事务脚本被称作贫血模型相对应的,领域模型也被称为充血模型。
领域是一个组织所做的事情以及其包含的一切,通俗地说,就是组织的业务范围和做事方式,也是软件开发的目标范围。
领域驱动设计就是从领域出发,分析领域内模型及其关系,进而设计软件系统的方法
领域(系统)、子域(子系统)、界限上下文(组件、模块、微服务)、上下文映射图(交互)
实体(唯一标识不会变化、属性和方法)、值对象(不变性,一个值对象创建以后就不变化)、聚合(一个关联对象的集合)
DDD的战略设计和战术设计
领域、子域、界限上下文、上下文映射图,这些是DDD的战略设计。
实体、值对象、聚合、CARS、事件溯源,这些是DDD战术设计。
通过战略设计,划分模块和服务的边界及依赖关系,对微服务架构的设计至关重要。
最重要的需求
软件系统过程:需求中找价值去实现,设计成一些模型,按照一些原则进行实践。
评论