1.摘要
本文阐述了一种将分层设计和DDD领域设计应用于微服务体系架构的方案实践,也是个人的最佳实践。对于互联网公司来说,我们主张将其Web服务架构分为五层:基础设施层、领域服务层、应用服务层、网关层和用户界面层(表示层)。领域服务层和应用服务层均可以采用微服务设计进行拆分,其中领域服务层将按照DDD领域建模进行领域划分,设计为一个个领域模块微服务,每个微服务高度内聚,仅关注自己的业务,领域服务间通过接口调用进行松耦合。这种设计方案可以大大简化大系统,并且在后期的维护中优势会日渐凸显,然而把大系统分而治之拆成微服务同时也对架构师和开发人员提出了更高的要求。第2部分介绍了相关背景,接着第3部分探讨了分层设计以及每一层的功能,第4部分结合微服务和DDD对领域服务层层进行服务模块划分和设计。最后一部分则就分层设计和DDD建模中常见的问题进行了整理。
2.背景介绍
想写这样一篇文章很久了,虽然本科学的是软件工程,但碍于自己能力有限,从08年写代码以来一直断断续续的思考,始终对项目代码结构设计(分包、分层)没有一个可以让自己觉得满意且无纠结点的答案,假设了某个设计,很快在实践中又会发现其存在着一些问题。直到2014年毕业工作了解了DDD领域驱动设计后,才有了相对清晰的方向。实际上早在2004年,Eric Envas的《领域驱动设计:软件核心复杂性应对之道》就出版了,毕竟软件开发自计算机普及以来已经存在很长一段时间了,早期国外程序员对软件开发理论的研究也十分兴盛,如今成熟后反而研究的相对少了,基本上依葫芦画瓢即可。DDD领域驱动设计对软件设计各个环节的人员都有较高的要求,用《领域驱动设计》一书的话来说它需要一个“领域驱动团队”[1],它要求从分析阶段,产品经理、项目经理、架构师以及开发工程师就使用统一的模型语言(Ubiquitous Language)来进行沟通,并且他们都懂一些代码、产品和建模相关的知识,事实上这在国内很难实施,国内的产品经理约等于需求整理工,对其计算机基础的要求是少之又少,在我所从事的公司里,也曾发生过产品经理直接指导开发,以至于后面双方理解的同一个词有着不同含义的情况。近年来,随着分布式的发展,传统中小型机集中式服务器已经不在流行,所以微服务体系也成为了各大互联网公司主流的选择。直观的感受下微服务和DDD两者,似乎一个是微系统,另一个则是大系统的设计方法,似乎两者天生互斥,微服务化的小系统也用不着DDD,其实并不是,DDD是针对整个复杂的软件解决方案的一种科学设计方法,微服务化也是把复杂的大系统拆分为小系统,方便维护和管理,所以两者都有一个特点——为复杂的大系统服务。下面咱们就来探讨下,如何把DDD的领域设计和其主张的分层设计应用到微服务体系架构中。需要说明的是本文主要是个人多年来的一点总结,未必适合所有场景,有更好通用性更为广泛的方案请不吝赐教。
3.分层设计
准确的说分层设计(Layered Architecture)跟DDD没有必然的联系,我最早接触分层设计是在携程网,当时内部使用的应该只是简单的业务层(Biz)和表示层,数据库访问之类的也是放在各自的业务包下的。后来接触和学习了《领域驱动设计:软件核心复杂性应对之道》,书的第4章“分离领域”中说到了四层分层设计,即:基础设施层、领域层、应用层和用户界面层(表示层)。DDD产生的年代微服务还未流行,当时甚至基于浏览器的Web应用都比较少,更多的是PC软件和EJB等网络应用,所以作者更多的是想表达对复杂系统的逻辑分层,并不在意每个领域是单独的系统还是一个软件系统内不同的模块。所以为了跟其做区分,我们建议的四层为在其基础上引入“服务”两个字,即:基础设施层、领域服务层、应用服务层和用户界面层。这样做的意图是让开发人员立刻可以了解到——每个领域模块即一个微服务(一个领域可以对应一个微服务,也可以对应多个同域的)。摘要中提到我们主张的分层体系中还有一个层,即网关层,这又是什么鬼呢。刚刚提到的DDD的时代背景,PC软件系统或者企业内部使用的网络应用系统是根本没有网关层(有也是网络网关设备)这一说的,而现如今互联网公司产品的输出形式无外乎Web应用(网站、或者网络服务),并且为了更好的适配PC站和App,一般会采用前后端分离的应用设计方案,这时候会产生一个需求——内部网络应用系统如何把自己的服务输出到互联网上,供外部系统或者浏览器网页访问。最直接的方式就是把应用层直接暴露在公网上,但我们不建议这么做,应用层服务更多的是关注业务应用,对网络级的系统安全性(防DDOS、钓鱼、跨域等)、请求监控等缺乏考虑,这些工作交给网关层统一管理会轻松很多(比如淘宝的TOP平台)。
这时候我们在Web应用系统中引入网关层用于衔接表示层和应用层,因为这样可以更好的划分各层的职能。网关层也可以看作是应用服务层的对外包装层