服务拆分的几种处理思路
场景说明
目标是需要拆分出内部服务 Y 为独立的系统,且暂时不改变系统 A 的被依赖关系,拆分前的情况如下图。
这里假定两个接口层处理模块只会调用只会调用内部服务 Y,并且其中存在着业务逻辑,也许你会疑惑接口层为什么会有业务逻辑,事实上你大多数情况下会遇到。更具体的说,接口层的业务接口 1 中包含业务逻辑,于是会产生对内部服务 Y 的两个及以上接口的调用。
处理思路
那么你会遇到以下几种情况需要处理。
针对 case 1 的 RPC 接口逻辑两种处理方式:
- 左图:拷贝 rpc 协议在系统 B 实现逻辑搬迁,系统 A 只有接口层,且只有对象转换,无任何逻辑。
- 右图:基于内部服务 Y 接口定义,迁移服务层逻辑到系统 B ,实现基于 BizDto 定义的 rpc 接口,系统 A 在接口层保留业务逻辑,只需要增加 BizDto 到 BizThriftVo2 对象的转换。
针对 case2 的 HTTP 接口逻辑也有两种处理方式:
- 左图:同样,基于内部服务 Y 接口定义,迁移服务层逻辑到系统 B ,实现基于 BizDto 定义的 rpc 接口,系统 A 在接口层保留业务逻辑,只需要增加 BizDto 到 BizThriftVo2 对象的转换。
- 右图:拷贝 http 协议在系统 B 实现逻辑搬迁,BizThriftVo3 基于 BizHttpVo 定义,系统 A 只有接口层,且只有对象转换,无任何逻辑。
针对 case 3 的内部服务调用:
对于内部服务调用,基于内部服务 Y 接口定义,迁移服务层逻辑到系统 B ,实现基于 BizDto 定义的 rpc 接口,系统 A 只需要增加 BizDto 到 BizThriftVo2 对象的转换。
对 内部服务 X 调 Y 的场景下,需要注意其中是否包含事务型依赖关系。因为如果从本地调用改为远程调用可能会破坏整个事务的完整性,产生数据不一致。
更优解
如果我们要拆分内部服务 Y,从上游的依赖来看,有系统 A 和手机客户端的依赖关系(通过虚线表示)。
如果我们不考虑上下游依赖关系,就会和上面说的几种情况一样处理,这时候系统 B 的 RPC 接口层就只是一层很薄的代理,存在的问题是资源的浪费和服务稳定性的打折扣,而且你还要写比较多的胶水代码。而更优的一种方式是消除这种传递依赖,使系统 A 和系统 B 解耦,使系统 C 的功能更内聚,每个系统只负责自己对象和 BizThriftVo 对象的转换。