什么样的服务才是好的服务?
高内聚、松耦合的服务才是好的服务。简而言之,就是把相关性强的放在一起,相关性不强的分开,物以类聚,人以群分,服务的划分也是这样。这就需要确定什么要放在一起,什么是要分开的,这个寻找的过程就是确定服务边界的过程。
限界上下文
限界上下文确定了这个边界内它所承担的职责。
Evans在《领域驱动设计》中作喻:细胞之所以会存在,是因为细胞膜定义了什么在细胞内,什么在细胞外,并且确定了什么物质可以通过细胞。这是限界上下文的绝好比喻。
任何一个给定的领域都包含多个限界上下文。限界上下文中包含了一些内容(或者叫模型),它们的相关性较高,一部分需要与外部通信,一部分不需要与外部通信,每个限界上下文都有明确的接口,该接口决定了它会暴露哪些模型给其他的上下文。外部想与限界上下文通信,需要使用模型和它的显式限界(接口)进行通信。这样做可以得到高内聚,从而很好地形成组合限界。
限界与限界之间,也会存在共享模型,如下所示,仓库和财务都需要库存信息,但不能把仓库所有的库存信息都给财务,因为有些信息对于财务是并没有用的,同时也不能让财务伸到仓库内部去取数据,这样有可能会破坏限界上下文的完整性,因此,我们提供了一个共享模型——库存项。
这些模块限界就可以成为绝佳的微服务候选,一般来说,微服务应清晰地和限界上下文保持一致。
如何确定限界上下文
1.推荐使用领域来表分解限界上下文
如果把系统分解成为限界上下文来表示领域的话,那么对于某个功能所做的修改,就更倾向于在一个单独的微服务限界之内。另外,服务之间应该共享相同的术语,也应该反映到服务的接口上。
2.应从限界上下文提供的功能来考虑,而不是数据
只考虑数据和模型,不考虑上下文的功能,很容易导致“贫血”,所以要先问“这个上下文是做什么用的“,再考虑它”需要什么样的数据“。
3.不要过早划分上下文
对于一个新系统而言,可以先使用一段时间的单块系统,因为如果服务之间的限界搞错了,后面修复的代价就会很大,所以最好能够等到系统稳定下来之后,再确定把哪些东西作为一个服务划分出去。
4.不要排斥嵌套上下文
一开始,你会识别一些粗粒度的限界上下文,而这些限界上下文可能又包含一些嵌套的限界上下文。如下所示:使用这些嵌套的上下文不直接对外可见,对于外界来说,它们用的还是仓库的功能,但发出的请求其实被透明地映射到了两个或更多有服务上。
当然,根据每个团队的情况不同,我们也可以将仓库的内的上下文再隔离出来,如下所示:
5.谨慎根据技术边界来确定上下文
一般而言,我们建议按照业务的垂直划分来建立上下文,而不是按照技术的分层来确定上下文,比如,你如果将DAO、BLL、UI层分成3个不同的服务,那么当你需要变更业务的时候,你需要频繁地同时修改两个服务,这样显然是不合理的。但也不是说这样划分总是不合理,如果一个组织想达到某个性能目标,这样划分反而更合理。
参考
《微服务设计》(Sam Newman 著 / 崔力强 张骏 译)