微服务架构中为何不建议共享REST Client库?
这问题问得特别实在——我刚接触微服务的时候也跟你一样困惑:明明复制粘贴相同代码既低效又容易出bug,把这些通用的POJO和Client抽成共享库明明是软件工程的基本操作,为啥在微服务里就不推荐了?其实核心原因是微服务的核心诉求是「独立自治」,而共享API相关的库会悄悄破坏这种独立性,下面我掰碎了给你讲:
1. 会造成服务间的强耦合,牵一发而动全身
如果所有服务都依赖同一个共享库,只要其中一个服务修改了库中的POJO(比如给User对象加了个nickname字段,或者改了某个字段的类型),所有依赖这个库的服务都必须同步升级版本,否则就会出现序列化失败、字段不匹配的报错。
举个真实例子:之前我们团队的订单服务改了共享库中的Order对象,加了一个discountAmount字段,结果库存服务没及时升级库,调用订单服务接口的时候直接抛出了JsonProcessingException,导致整个库存服务的下单流程崩溃。而如果是复制粘贴的POJO,库存服务的Order对象是独立的,完全可以忽略这个新增字段,直到自己业务需要的时候再去更新,不会被上游服务的变更强制“绑架”。
2. 锁定发布节奏,阻碍独立迭代
微服务的优势之一就是每个服务可以独立发布、快速迭代,但共享库会把所有服务的发布节奏绑在一起。比如你给共享库加了一个新的REST Client方法,所有要用到这个方法的服务都得跟着升级库、测试、发布,哪怕这些服务本来没计划在这个时间点发布上线。
而复制粘贴代码的话,每个服务可以自己决定什么时候更新这段代码——比如用户服务可以先更新Client调用新的支付接口,而商品服务可以等下个月迭代的时候再处理,彼此完全不影响。
3. 模糊了服务契约的边界,弱化API的契约意识
微服务之间的通信应该基于API契约(比如接口文档、OpenAPI定义),而不是代码实现。共享库本质上是把API契约硬编码成了代码依赖,团队很容易慢慢依赖库中的代码实现,而忽略了API本身的定义。
比如如果共享库的Client里封装了某个接口的调用逻辑,大家会直接用这个Client,而不会去看API文档;一旦API有变更但库没及时更新,就会出现调用失败的问题。而复制POJO和Client的过程,其实是每个服务自己对API契约的“实现”,能强制大家去关注API的定义,保持服务间的通信是基于契约而非代码。
4. 限制技术栈的演进空间
微服务的另一个优势是允许不同服务用不同的技术栈适配业务场景。如果所有服务都依赖同一个Java共享库,那以后某个服务想换成Quarkus、Go甚至Python,这个共享库就完全没法用了,迁移成本会非常高。
而复制的代码是每个服务自己维护的,换成新技术栈的时候只需要用新语言重新实现对应的POJO和Client即可,不会被绑定在Java Spring的技术栈里。
那有没有替代方案?
当然有!我们既不想复制粘贴,又不想破坏服务独立性,可以用代码生成工具:
- 先定义统一的API契约(比如用OpenAPI规范)
- 每个服务根据这个契约自动生成对应的POJO和REST Client代码(比如用OpenAPI Generator)
这样每个服务的代码都是独立生成的,既避免了复制粘贴的低效,又保持了服务的自治性,完美解决你的痛点。
内容的提问来源于stack exchange,提问作者hmojica

