在微服务的落地中,第一步就需要进行微服务的拆分,服务的拆分很困难也很重要,本文就讲讲怎么进行服务的拆分。
技术发展到现在,还没有一个具体的,设计完善的标准方法来完成服务的拆分,服务的拆分是一门技术更是一门艺术。
对于服务的拆分,有两种情况 :
1、从零开始开发新的产品,采用微服务架构,进行服务拆分;
2、将现有的单体架构的产品重构成微服务架构,进行服务拆分。
如果做的是 ToB 业务,最终在企业内部私有化部署落地,那么在大多数的场景下,微服务拆分后系统的复杂度和引发的新问题会大于带来的好处。
随着业务的发展,产品需要进行 SaaS 化改造,团队也引入多种技术栈,进行微服务的拆分应该就是势在必行了。所以下面介绍的是怎样将现有单体架构拆分成微服务。
服务的拆分不是看代码量或是工程的大小,而是要根据当前业务的情况、团队的情况综合考虑,还是拿零代码平台作为例子。
零代码平台中有菜单、流程、表单、页面等模型,这些模型各自都能独立成一个服务,但前期为了快速交付,可以都放到一个工程中,但在代码组织和架构层面,为了后续的拆分,可以在逻辑和上进行隔离,物理文件可以用目录来区分,整体还是在一个大的工程中,如下图:
服务的拆分的一个最大的作用就是解耦,但并不是说一定要拆开才是解耦,在一个工程中,合理地使用面向对象的一些原则,比如依赖倒置、接口隔离等,也能做到解耦。
平台的功能在不断地迭代,现在需要添加 BI 模块,整个架构也调整为支持多租户模式,同时也需要开发应用商城,将零代码平台推上互联网,构建一个应用生态,用户可以直接安装应用或者将自己的应用发布到应用商城中。这里添加的 BI 和应用商城就可以作为一个单独的服务,而原来的整个零代码平台可以先作为一个大的服务存在,修改后的架构图如下:
上面的例子是从全局的维度来考虑应该怎样去拆分,不一定对,但以我目前的认知和现有的场景来看,我认为是适合的。
具体到一个特定的服务,最基本的要求是具有能访问的 API , 并且可以独立部署,至于数据库是独立还是跟其他服务共用,也是需要具体问题具体分析,如果存在较多的跨服务的查询操作,建议多服务共用一个数据库。
服务与服务之间需要做到高内聚低耦合,如果因为其他服务的变更导致需要频繁更新你的服务,或者说你的服务的一个小的改动会导致很多其他的服务要进行同步修改,那么说明服务之间的耦合性太高,拆分了享受不到微服务带来的好处,反倒是将缺点无限放大了。所以在拆分服务时要遵循两个原则:
1、通用功能,使用共享库,比如工具类,提取成 NuGet 包或者 Maven 包,在服务中进行引用;
2、业务相关的公共部分,使用单独的服务,提供 API 的方式供其他服务调用。
每个服务都可以使用不同的架构和技术栈来实现,有一种推荐的做法就是使用六边形架构,六边形架构在一些 DDD 的书籍和微服务的书籍中都有提到,下面是一张六边形架构的架构图:
六边形架构也称为端口适配器架构,可以替代传统的三层,解决三层架构的一些弊端。端口和适配器都分为入站和出站。
- 入站适配器:通常就是对外的 RestAPI,通过调用入站端口来处理外部的请求,也可以是消息队列的消费者,进行一些事件的监听,来处理异步业务,当接收到消息时也是调用入站端口来进行处理;
- 入站端口:业务服务对外暴露的公有方法;
- 出站适配器:出站适配器实现出站接口,调用外部的服务来实现一个完整的业务逻辑,出站适配器也可以是消息队列的生产者;
- 出站端口:出站端口是一组方法的接口定义,提供一种规范,供出站适配器来实现。
举一个例子:在零代码平台中,表单上拖一个控件保存后,最后的效果是列表上也会有这一列了,而表单和列表属于两个独立的服务,按照六边形架构,调用关系如下图:
六边形架构一个最大的好处就是将业务逻辑和适配器中包含的展示层和数据访问层的逻辑分离开,实现了解耦。
学习微服务,我觉得有必要同时学习领域驱动开发(DDD),微服务是一种架构风格,DDD 是具体的架构设计方法,互相配合能够更好地落地,因为:
1、DDD 中子域和限界上下文的概念可以对应到微服务中的服务;
2、微服务中一个服务可以由一个团队进行开发,DDD 的一个领域模型也是建议由一个独立的团队负责。
进行服务拆分后,之前在一个进程内就能完成的事情,现在需要在进程间进行通信了,有关进程间通信后面再继续分享。
零代码现在越来越火热,通过高度的抽象,将基础设施、重复性的工作作为平台本身的能力提供,让用户只用关注业务,这其实也是另一个层面的解耦和拆分。