六边形架构
DDD关键点是关注业务架构,而不是技术架构,所以这一章开头一句就是“它并不需要使用特定的架构。由于核心域位于限界上下文中,我们可以在整个系统中使用多种风格的架构。
虽然没有要求哪种架构,但哪种架构更合适呢?书中明显推荐是六边形架构,为什么呢?从外观看,六边形是不是跟一个限界上下文的图示是不是比较像?有一个明显的边界线,然后跟外界打交道通过端口适配器或OHS|ACL。
CQRS
然后当业务复杂了,领域模型多了,为了大前端的展示和交互需求,直接从资源库(db)查询数据或直接的属性过滤,已经无法满足了,这时候CQRS就派上用场了,命令查询职责分离,简单理解就是读写分离,要满足多样化的查询需求,一种数据模型或存储介质存储结构肯定是满足不了,但在命令操作(修改操作)中同步去写多种存储介质也是不现实的,这时就要借助领域事件(实现中经常使用异步事件,技术上以消息或存储事件为主)来通知更新查询模型。下面是我曾经在一个项目从实现的架构,当时以流行的称呼数据异构,现在来看就是不折不扣的CQRS实践了,可以看看下图:

对其它架构也有不少收获:
分层架构
比如经典分层架构,从上到下划分为用户接口层,应用层,领域层和基础设施层。之前的架构实践,也思考过分层架构,当时为了解决团队内服务之间依赖混乱,环形依赖的问题,也作了下述规定:
设计原则:
从上到下分为:终端展示层、请求处理层、业务逻辑层、数据持久层
服务是单向依赖的, 上层依赖下层,可以跨层, 同一层次少依赖。
请求处理层和开放接口放在同一层次或者是同一个微服务实现,是后端与前端的边界
业务逻辑层和数据持久层(DAO)建议在一个微服务里实现。其它层次各为一个微服务。
当时的困惑是:单向依赖的要求和同层是否允许调用的问题困扰很久,如果严格单向依赖,同层不允许互调,那需要划分很多层次,服务需要拆分得很细,还有很多问题,比如db的变化通过databus(基于binlog)通知应用服务算符合规范吗?
这些困惑,这次得到解答了:
1.P105分层 “事实上,较低层也是可以和较高层发生耦合的,但这只局限于采用观察者(Observer)模式或调停者(Mediator)模式的情况”。这就基本解答了我的困惑了
2.P107依赖倒置原则,“高层模块不应该依赖于底层模块,两者都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象”,即各层都应该依赖接口,但接口在哪层实现都是ok了,然后使用依赖注入或服务工厂来实现实例的问题。既然各层实现都可以,事实上已经不存在分层的概念和需要了。P109“无论是高层还是低层,它们都只依赖于抽象,就好像把整个分层架构给推平一样。如果我们把分层架构推平,再向其中加入一些对称性会变得如何呢?”,其实就是六边形架构了。
但六边形架构,这种多边依赖的情况,在实际的运维过程中也碰到一些问题,因为运维需要划分核心服务核心路径(核心服务依赖的服务肯定也是核心服务),并给予更多的关注,而六边形这种扁平的多边依赖关系不利于核心路径的划分,导致依赖扩大化,所以实际实践中,并不会全面的使用六边形架构。
REST
再就是REST(Representational State Transfer)以及restfull,这真是被滥用的架构流行语。特别是在前端人员写的文章里。restfull,不是用json,用url拼参数,用put、delete方法就是restfull,rest的关键特征是:
1、资源的概念,“通常来说,每种资源都拥有一个URI,更重要的是,每个URI都需要指向某个资源”,即用uri来定位资源
2、无状态通信,“我们不能依靠请求本身来创建一个隐式的上下文环境(对话)。无状态通信保证了不同请求之间的相互独立性,这在很大程序上提高了系统的可伸缩性”,即一个http请求携带了完成请求的所有信息,而不是靠服务端来关联上下文。这非常有利于服务端的可扩展性。但对客户端开发来说,会增加一些难度。因为对一个会话来说,是有一些状态会要维护的,比如登陆状态及一些操作上下文信息,然后每次http请求都携带完整的所有信息,那这些信息在哪存储呢,就只能在请求发起者,也就是客户端存了,虽然这是合理的,但也需要与客户端取得共识。
3、对象的方法抽象为固定的几种,即http方法:GET、PUT、POST、DELETE,这是大家最熟知的。其中GET、PUT、DELETE是幂等的。
其它
事件驱动架构,现在一般使用消息队列实现了,对其中“聚合”的概念,还不太理解
至于数据网织和分布式计算,最终一致性,异步复制,数据多副本的做法,基本都是老生常谈了
网友评论