若是花时间了解一下 DDD 的历史,就会发现 DDD 已经存在了很长时间,单单按照 Eric Evans 成书那一年算起也已经有超过 10 年的历史了。但即便在刚开始的那几年,DDD 也只能说是不温不火,只是小圈子里人们的谈资,鲜少看到分享的文章(至少国内给个人感受如此)。有意思的是大约三年前开始,DDD 从新回归大众的视野,不管是线上的文章也好,仍是线下的各个大会,DDD 成为当仁不让的主角之一。数据库
这背后的缘由错综复杂,很难找出单一的解释。不过细心的阅读近几年来的 DDD 相关文章,你会发现有个名词以很高的频率与 DDD 一同出现,它就是微服务。对于微服务的分歧其实很大,或褒或贬,双方每每走向两个极端。推崇微服务的人以为这是解决大型系统混乱,耦合的一剂良药,而反对的人以为这只是架构师没事找事,平添了许多复杂性却没有带来有价值的收益。编程
其实不少新技术,新事物都是如此。诞生之初被寄予厚望,看上去有一统宇内八荒的气势。可是随着问题的出现,就招来了更大的质疑,反而落入了低谷。直到随着时间的流逝,那些真正的实践者们筚路蓝缕,脚踏实地的解决问题,让这些技术从新回到大众的视野中。虽然最近一年多谈论微服务的少了,可是我看到的是更多微服务落地的项目,虽然并非每一个都很是完美,可是绝大部分都达到了预期目标(因此最近搞中台的同窗们没必要灰心,多作一些落地具体的方案才是回应质疑最好的方式)。服务器
之因此 DDD 与微服务经常同时出现,缘由在于 DDD 中的不少实践可以帮助微服务更好的落地,完成的质量更高。不只是对于单个的服务,对于整个微服务的架构,DDD 都可以起到很好的指导。而例如事件驱动,CQRS 这样源自 DDD 的模式,在微服务的上下文中显得更为合理,也可以真正的发挥自身的能力。微信
以前也有同窗但愿我写一些有关微服务的文章,因此我也刚好借着 DDD 的机会分享一些 DDD 与微服务结合的心得与经验,但愿可以帮到有须要的人。这是系列的第一篇,我会把重点放在微服务上,而下一篇则会分享如何结合 DDD 作好微服务的拆分。在开始以前仍是须要提醒一句,在软件架构方面并无所谓的银弹,适合个人解决方案并不必定适合你,而你如今用的挺好的技术在将来可能成为最大的瓶颈。因此在本身的实践中,要学会独立思考,不要选最流行的,而是要选最适合本身,能为本身创造最大价值的方案。毕竟就像李文秀在书中末尾处所说的,「别人硬要给你的,就算好得不得了,我不喜欢,终究是不喜欢。」。架构
微服务是一种架构风格,与之对应的是单体架构。在讨论微服务的优势以前,不妨先看看单体架构有哪些优缺点,单单知己是不够的,知彼也很重要。每一个开发者对单体架构都很熟悉,是咱们平常开发过程当中最普通,最多见的一种架构风格。说白了就是把相关功能都放在一个 codebase 下,编译,测试,发布都是以一个总体进行的。最大的优势就是简单,易操做。开发简单,你们代码库一拉,就能在上面开发新功能了。端对端的测试也简单,调用一个接口,看看数据库数据是否符合预期便可。而发布部署就更简单了,若是是 Java 项目,一个 war 包或是 jar 扔到服务器上就好了。运维
可是随着项目业务的发展,规模的变大,单体架构的缺点就凸显出来了。想象一下一个项目中存在着上万个源文件,后台数据库中有上千的表,单单编译一次可能就须要十几分钟的时间,跑一次完整的单元测试那更是万万等不起,这样还能搞敏捷,搞 DevOps 吗?诚然单体架构的系统一样经过 DDD 这样的架构模式提高可维护性,但这也是有上限的,随着代码的愈来愈多,业务逻辑的愈来愈复杂,项目的墒只会增长,最终难逃架构腐化,系统模块间紧密耦合,开发人员不敢动遗留代码的结局。分布式
解决软件复杂度的方法有不少,其中咱们最熟悉也是最熟练的就是分治。咱们将能够复用的代码放入不一样的函数中,将一系列有关的行为与数据放入类中,这是代码层面的分治。咱们将多个相关功能的类放入到模块中,造成了多个不一样的编程模块则是更高一层,在模块层面的分治。对于单体架构面临的问题,一样能够经过分治来解决,即把拆分的层次再向上移动一层,将一个大型的系统拆分红多个服务,而这也就是微服务架构了。函数
在谈及微服务时,咱们须要明确,咱们如何定义微服务呢?比较常见的误区是把注意力集中在了微字上,例如曾经看到文章说须要把每一个服务的代码限制在几百行如下,源文件不得超过多少个才算微服务。我本身以为这有照本宣科的意思,其实微服务的特色在于松耦合与完整的服务这两项上。微服务
咱们先看松耦合,这意味着服务应该是独立的,能够独立开发,独立测试,独立部署,不依赖于任何的外部系统(基础设施除外)。当其余系统发生问题时,当前的服务依然能够向外部提供部分服务,而不是向单体应用那样,若是当前系统存在相似内存泄漏这样的问题,会致使整个系统的响应时间变慢,将问题蔓延至其余模块。单元测试
同时松耦合也使得快速迭代,上线成为可能,不须要在等待其余模块开发完成,就可以独立的进入开发,生产环境。而这也会影响到你的版本管理的分治策略,你能够很方便的使用基于主干的分支管理策略,不须要担忧长期存在的 feature 合并时发生使人头疼的冲突问题。
其二是完整的服务。从业务功能的角度出发,每一个微服务都应该提供一组独立,完备的业务服务。这也是不少时候让架构师难以把握的方面,怎么样才是独立,完备,书上是找不到答案的,更多的时候这更像是一门艺术而不是技术。可是也不用过于担忧,DDD 刚好可以经过限界上下文,核心域这样的概念帮助咱们不断的完善服务划分。这也会在以后的服务拆分的篇章中详细讲解。
答案很明显,微服务不是万能的,甚至在有些场景下会放大原有团队的缺点和问题,致使系统的稳定性变的更差。天底下没有免费的午饭,在引入松耦合这些优势以后,微服务带来的是更复杂的系统架构,对于团队,基础设施,运维更高的技术要求,若是整个团队或是组织没法知足这些要求,没法妥善的处理微服务带来的反作用,那么作好的选择就是先提高内部能力再考虑架构的升级。
一个比较常见的场景是分布式事务的问题。单体架构通常都使用关系型数据库做为数据存储机制,经过关系型数据库的事务机制来保证数据的一致性。可是在引入微服务以后,对应的数据库也会进行拆分,甚至使用其余类型,例如 NoSQL 这样的数据存储,所以并无办法保证严格的数据一致性,须要引入 BASE 这样的柔性事务,达到数据的最终一致性。若是一个团队没有在前期最好足够的调研,并采起逐步替换策略,那么极可能在架构迁移的第一阶段就遇到巨大的障碍。
另外一个常见的问题则是对于基础设施和运维的挑战。在本来单体架构的场景中,运维和发布的步骤很简单,经过一些简单的脚本就能完成自动化的发布。可是在微服务架构中你须要面对的多是上百个容器的监控,几十个服务之间调用链的分析和追踪,当出现问题时须要在极短的时间内定位到问题。若是在这方面缺少积累,那么就会出现线上有问题都不知道是那个服务引发的尴尬场面。
说了这么多,关键点在于不要盲目的迷信某种技术架构,选择合适本身的最重要。若是选择了微服务,那么开始以前先了解微服务架构有哪些必要的先觉条件,评估本身是否知足这些条件以后再考虑下一步的计划。最后 DDD 中的不少模式可以帮助你理清微服务中的许多问题,提供更好的解决思路,这也是我以后文章中会详细谈及的,但愿感兴趣的不会错过吧。
欢迎关注个人微信号「且把金针度与人」,获取更多高质量文章