上一篇介绍了在项目启动阶段,战略设计前,需要通过一些步骤和用户达成共识,确定项目的业务期望与边界。
此篇将整体介绍一下战略设计这个阶段的主要作用,常用方法或步骤,后续再针对每种方法或步骤进行详细介绍。
主要作用
- 细化问题域
- 根据业务边界和业务期望,对整个业务问题域进行初步的拆分,并根据拆分后的子问题域对业务期望的重要程度,识别为核心子域,支撑子域和通用子域
- 针对每一个子域,结合史诗级的业务流程,梳理细化业务流程
- 针对每一个子域梳理细化后的业务流程,分为不同的限界上下文
- 针对识别出来的限界上下文,确定限界上下文的映射关系和调用关系,不能出现循环调用,必要时可返回上一步重新调整限界上下文的划分
- 确立基本架构
- 确定服务治理的方案
- 确定服务调用的方案,是直接调用还是通过事件异步通知
- 确定日志记录方案
- 确定链路跟踪方案
- 确定部署方案
常用方法步骤
细化问题域
问题域拆分
比如针对捷信达面临的旅游和养老行业信息化建设问题域,会直接按产品线拆分为酒店,餐饮,水疗,景区,养老等各个子问题域
根据公司目前面临的市场和业务期望,酒店和养老会认为是核心子域,其他的是支撑子域。将来随着行业的变化或公司业务期望的调整,核心子域也会相应变化和调整细化子域业务流程
针对每一个拆分出来的子域,可使用用例图方法或事件风暴法来梳理子域的业务流程识别限界上下文
针对识别出来的业务流程,根据业务相关度,划分不同的限界上下文。
划分时需要注意,每个限界上下文是必须有一个核心业务价值的完整实现,注意边界保护。需要把与要实现的核心价值无关的功能阻挡在限界上下文之外,需要把与要实现的核心价值密切相关的功能纳入到限界上下文之内,并且进行边界保护,以实现完整的业务规则。映射限界上下文
由于每个限界上下文只实现一个核心业务价值,但真实的用户场景中的一个功能,可能都是需要好多核心业务价值功能配合才能完成一个场景,所以需要考虑各核心业务价值之间的上下游调用关系,以及是采用直接调用还是异步事件通知方式。
在此过程中需要保证,标识下来的各限界上下文之间不能出现循环调用的问题。如果出现的话,需要分析原因,提出一些公共的放到单独限界上下文中,来解除循环调用问题。确立基本架构
确定服务治理方案
由于进行了业务拆分,会存在很多限界上下文,并且各限界上下文之间是需要互相协作才能完成业务场景的,所以首先遇到的问题就是各限界上下文之间如何知道对方运行时地址,以便调用接口进行协作。
传统的方法是先部署本限界上下文需要调用的限界上下文,并且获取到部署后的地址后,直接填入本限界上下文的配置文件中,这样本限界上下文调用时就知道地址了。这种方法有一个问题,就是如果目标限界上下文由于一些原因重新部署后,则需要相应的修改所有要调用此目标限界上下文的配置文件,以便更新新的调用地址。
在基于微服务的方案中,一般是会选择一些服务治理的方案来解决此问题,其原理如下 :
常用的服务治理组件有consul,zookeeper,k8s自带的dns服务等。我们本次选择的是直接使用dapr,其服务治理方案是内置的,在selfhost模式下运行时,dapr会启动一个dns服务来进行服务治理,如果是在k8s环境下,则会直接使用k8s的dns服务确定服务调用方案
在考虑完如何知道要调用的目标服务的地址后,还需要考虑调用方式,是通过rest api直接调用,还是通过grpc调用,或者通过异步的事件通知方式来发送通知进行触发后续业务,需要根据具体的业务场景进行相应选择。
大部分的还是通过rest api直接调用方式来实现。确定日志记录方案
由于拆分后的服务众多,每个服务可能都需要记录日志,需要考虑日志的记录和查看方案。
日志分为两种日志,业务日志和运行日志。业务日志是指对用户业务操作产生的各种日志,这些日志需要直接保存到服务数据库中,用户需要查看这些日志。运行日志是用户不关心的,但我们开发和运维关心的,当出现某些问题后,会需要根据这些日志来分析原因,这些日志一般情况下不直接记录到服务数据库中,而是记录到统一的日志中心。方便开发和运维可以从统一日志中心查看。
为了减少记录运行日志对程序代码的影响,一般也不会要求日志记录必须调用一个远程组件来直接把日志写到统一日志中心,因为远程网络调用对性能影响比较大,所以一般是异步的将日志直接写入到本地硬盘上,然后有日志采集组件来定期将文件中的日志采集后,传输到统一日志中心中确定链路跟踪方案
此方案前期可选,但长远来说,此方案也是必须的
前面提到了一个业务场景的实现,需要由多个服务来共同协作才能完成,此时如果业务场景反应操作缓慢,那么到底是哪个服务的问题呢?需要有一个量化的工具来度量和分析慢的原因。链路跟踪就是解决此问题的。
它会跟踪一个业务场景的请求进来后,经过的每一个服务调用,以及每一个服务调用的开始和结束时间,调用顺序等,可以直观的看出有哪些服务是并行执行的,哪些是串行执行的,哪些服务执行耗时最长。针对观察到的结果再来针对性的优化就可以了。
现在我们使用的是dapr内部集成的链路跟踪方案,他会自动的生成一些度量值,并且把这些跟踪数据传递给到zipkin里面。确定部署方案
还需要确定部署方案,不同的部署方案对开发过程和后期的CICD都是有影响的。
我们本次确定部署方案是部署到k8s里面,所有的服务都是直接运行在docker容器里面,所以大概的部署流程是:程序本地发布》打包成docker镜像》上传到镜像仓库》通知k8s更新程序》k8s滚动更新》拉取新的程序镜像》启动docker容器运行
注:这里确定的基本架构,可以理解为是针对所有服务的,和我们以前理解的三层架构等是有差异的,三层架构可以理解为实现层的架构方式,在领域设计是,是在战术阶段进行实施的,针对每一个不同的限界上下文,可以根据业务复杂度,选择不同的架构方式。比如传统的三层架构,事务脚本方式以及针对业务复杂的菱形架构等。
本篇把战略设计进行了一个大概的介绍,而要进行战略设计,第一步就是需要理解问题域,提炼业务知识,下一篇将介绍通过领域场景分析来提炼业务领域知识的方法。