DDD和微服务能打通,关键就在BoundedContext。分布式系统的定义在谈论这个之前,我们需要先就什么是分布式系统达成共识。在我看来,判断一个系统是否分布式的标准就是看系统中是否存在跨进程通信。正是进程决定了协作和通信的方式,从而导致了两种具有本质区别的编程模型:进程内编程模型和跨进程编程模型,它们的区别在于组件之间的调用方式。进程内组件调用非常简单。就Java而言,驻留在同一个JVM中的所有对象和变量都放在堆内存或栈内存中。对象调用(包括方法调用)是一种内存寻址。Java语言通过new关键字创建实例,从而获得指向实例的指针,从而调用实例的属性和方法。跨进程组件之间的调用方式与进程内调用本质上是一样的。尽管跨进程通信机制有多种实现方式,但它们必须考虑的因素是相同的。他们需要考虑:如何在进程间通信协议中解决消息的序列化和反序列化问题此外,在资源管理、事务一致性和部署方面都因为跨进程通信而产生巨大差异。显然,跨进程通信固有的复杂性带来了编程模型的变化,但它可以更有效地利用硬件资源,这才是分布式系统的主要目标。因此,在当前IT发展的历史背景下,我们以进程为边界来定义分布式系统是非常有意义的。解释:不同的语言平台在进程的概念上有细微的差别,自然通信机制也不同。Java进程相当于操作系统的进程,但是Erlang和Go的进程概念不同,更加轻量级。跨进程组件之间的调用方式实际上是对通信机制的一种抽象,它实际上包括:进程间通信机制(如共享内存、管道、Socket)结构化通信机制(如RPC)中间件通信机制(分布式对象)如CORBA,EJB等组件中间件,消息中间件,面向服务和REST)容器讨论C4模型的SimonBrown提出了自己的C4模型,如下图所示:我们可以将流程划分为Container的一个划分边界,我认为是“物理边界”。因此,Container除了在架构中作为逻辑视图的一个组成部分,也可以看作是物理视图的一部分。巧合的是,AlistairCockburn提出的六边形架构(也称为port-adapter模式)在边界意义上与Container相呼应。下图中外六边形的边界是物理边界。根据前面的分析,我们可以把它看成是一个进程边界。微服务和限界上下文微服务作为一种可以独立部署的微型服务,本质上是一种物理隔离的自治服务。从物理的角度来看,一个微服务就是C4模型中的Container,也就是六边形架构中的六边形。如果我们把六边形架构对应到DDD的BoundedContext,那么我们就可以引入DDD的策略设计来划分服务边界,从而帮助我们设计微服务。一个典型的限界上下文可以有自己的域模型,访问专有数据库,并且可以引入“依赖注入”以满足UncleBob所谓的CleanArchitecture思想。下图所示的BoundedContext的架构不就是一个微服务吗?微服务的ContextMap解读思考DDD中的BoundedContext,可以关注以下两点:可以从业务架构层面进行设计。用例、通用语言或者其他方式都可以帮助我们识别BoundedContext,进而得到一个相对合理的服务边界。判断微服务的设计是否合理,可以通过DDD的ContextMap进一步验证和区分BoundedContext的划分,理清它们之间的关系。EricEvans在DDD一书中列出了九种ContextMaps,基本上可以归类为:团队之间的协作方式进程之间的集成方式为什么BoundedContext之间的关系可以理解为团队之间的关系协作呢?基本原理来自康威定律,它说:任何设计系统(这里是更广泛的系统,而不仅仅是信息系统)的组织都必然会产生一个结构,该结构是该组织通信结构设计的副本。一个BoundedContext可能映射到一个开发团队,所以讨论BoundedContext之间的关系也可以看作是讨论团队之间的关系。至于进程间的集成方式,无论是引入ACL(防腐层)还是OHS(OpenHostService),其目的都是为了在实现进程间通信的同时,实现限界上下文之间更好的松耦合。从微服务的角度来看,需要满足服务边界足够的自治。因此,当DDD遇上微服务,其实有很多神秘的相似之处值得研究。他们之间或许会擦出爱的火花,但却不得而知。【本文为专栏作家“张艺”原创稿件,转载请联系原作者】点此阅读更多该作者好文
