如何建模服务
本章围绕着如何定义服务,以及如何划分服务上下文与边界展开
衡量一个服务是否是好服务的两个标准
- 松耦合: 独立修改及部署单个服务而不需要修改系统的其他部分,需要尽可能少的知道与之协作的那些服务的信息。要尽可能的知道与之协作的那些服务的信息,限制两个服务之间不同调用形式的数量,因为除了潜在的性能问题之外,过度的通信可能会导致紧耦合
- 高内聚:实现高内聚为了避免发布修改时需要同时发布多个微服务,另外,找到问题域的边界就可以确保相关的行为能放在同一个地方,并且他们会和其他边界以尽量松耦合的形式进行通信
《领域驱动设计》Eric Evans: 任何一个给定的领域都包含多个限界上下文,每个限界上下文中的模型分成两部分,一部分不需要与外部通信,另一部分则需要,每个上下文都有明确的接口,该接口决定了他会暴露哪些模型给其他上下文
”细胞之所以会存在,是因为细胞膜定义了什么在细胞内,什么在细胞外,并且确定了什么物质可以通过细胞膜“ (绝了😹)
做到服务边界与领域限界上下文保持一致,使用微服务可以很好地表示这些限界上下文
文中提到如果无法清晰的划分服务与模型,那么最好先使用单体架构,过早的将一个系统划分为错误的微服务结构代价很高
但是即使分得再明确,也存在一些共享模型,拿书中的例子就是,仓库部分的库存信息,财务部门是需要知道的,这里的处理就是仅暴露模型的部分,对于模型来说分成内部和外部表示方法。不仅如此,这些共享模型在不同的领域之间往往代表着不同的名字。在思考这些上下文时,不应该从共享数据的角度来考虑,而是从这些上下文能够提供的功能来考虑
通过共享特定的模型而不是整个内部表示,可以避免潜在的紧耦合
划分上下文边界时,首先考虑比较大的,粗粒度的上下文,当发现合适的缝隙后,再进一步划分出那些嵌套的上下文
如果把系统分解成为限界上下文来表示领域的话,那么对于某个功能需要做的修改,就更倾向于局限在一个单独的微服务边界之内,这样就可以减小修改的范围,更快速的部署。
集成
1、无论如何避免数据库集成 2、理解REST和RPC之间的取舍,但总是使用REST作为请求/响应模式的起点 3、相比编排,优先选择协同 4、避免破坏性修改,理解Postel法则(鲁棒性原则: 系统中每个模块都要宽进严出,对自己发送的东西要严格,对接收的东西要宽容)
好的集成可以使得微服务保持自治性,能够独立地修改和发布它们
好的通信协议的要求
- 避免破坏性修改,例如发送方添加了一个字段,接收方要做到不受影响(当然修改除外😹)
- 技术无关性
- 消费端要易于接入
- 隐藏内部实现细节,否则一个消费方依赖这个细节会导致耦合度增加
选择服务之间的设计模式有两种,编排和协作
编排模式,容器出现承担太多工作的上帝服务,而其他的变成了贫血的CRUD服务
协作模式, 异步非方式,服务自己订阅事件并处理响应的事件,不需要中间节点进行编排调度,好处是能够解耦合,但是还是需要相匹配的监控系统才能保证服务确实可靠的执行完成
使用rpc时不要过度抽象,不要隐藏网络因素造成的问题