WEBKT

单体应用解耦后,通用模块何去何从:保留旧项目还是构建共享服务?

33 0 0 0

当单体应用逐渐走向历史,甚至被“绞杀殆尽”时,那些曾经依附于其上的通用模块,如鉴权(Authentication)、授权(Authorization)、日志(Logging)、配置管理(Configuration Management)、消息通知(Notification)等,它们的未来何去何从,是很多团队都会面临的棘手问题。是让它们继续残存在旧项目中,还是将其“升华”为独立的公共服务,这是一个需要深思熟虑的架构决策。

作为一名在技术领域摸爬滚打多年的老兵,我深知这其中的权衡与挑战。下面我将从不同角度为大家剖析这一问题。

选项一:保留在旧项目或遗留模块中

优点:

  1. 迁移成本低: 在短期内,这是最省力的方式,无需投入额外资源进行服务拆分和部署。
  2. 代码改动小: 核心业务逻辑不需要大规模调整,风险相对较低。
  3. 依赖简单: 无需处理跨服务调用、网络延迟、服务发现等分布式系统带来的复杂性。

缺点:

  1. 重复建设与维护: 如果有多个新服务需要这些通用功能,每个服务都可能复制一份,导致代码冗余,维护成本激增。
  2. 技术栈绑定: 遗留项目的技术栈可能过时,通用模块也会被绑定,难以更新和演进。
  3. 扩展性差: 无法独立扩展,性能瓶颈可能出现在任何一个使用这些模块的服务上。
  4. 职责不清: 随着时间推移,这些通用模块可能会被不同的团队魔改,导致功能混乱和行为不一致。

适用场景:

  • 仅作为临时的过渡方案,有明确的后续重构计划。
  • 通用模块与特定遗留业务逻辑耦合极深,短期内难以剥离,且预期不会有其他服务复用。
  • 新项目数量极少,且对通用功能的需求非常简单,复用价值不高。

选项二:抽取为独立的公共服务(共享服务)

优点:

  1. 高复用性: 一旦抽取为独立服务,可供所有新旧服务调用,实现“一次开发,多处使用”。
  2. 职责单一: 每个独立服务只关注自身核心功能,边界清晰,易于理解和维护。
  3. 独立演进: 可以独立于业务服务进行版本升级、技术栈更新和性能优化,互不影响。
  4. 解耦与灵活性: 降低了服务间的耦合度,促进了微服务架构的实施,增强了整个系统的弹性。
  5. 专业化管理: 可以由专门的团队负责维护,提供SLA(服务等级协议)保障。

缺点:

  1. 引入分布式系统复杂性: 需要考虑服务注册与发现、负载均衡、熔断降级、API网关、网络通信、数据一致性等问题。
  2. 部署与运维成本增加: 额外的服务意味着更多的部署单元、监控指标和运维工作量。
  3. 学习曲线: 团队需要掌握分布式系统开发和运维的技能。
  4. 网络延迟: 跨服务调用会带来一定的网络延迟,可能影响性能,需要优化通信协议。

适用场景:

  • 正在向微服务架构转型,或有多个新服务需要使用这些通用功能。
  • 通用模块功能稳定、边界清晰,且具有较高的业务无关性(如鉴权、日志、文件存储、短信/邮件服务)。
  • 团队具备开发和维护分布式系统的能力。
  • 对系统的可扩展性、可用性和维护性有较高要求。

混合与过渡策略

在实际操作中,我们往往会采取混合或分阶段的过渡策略:

  1. 内部共享库(Internal Shared Libraries): 对于一些通用性强,但对性能和实时性要求较高,且无需独立部署的模块(如某些工具类、通用DTO),可以先抽离成内部共享库(如Maven Artifact、NuGet Package),供各服务引用。但这仍存在版本管理和依赖地狱的风险。
  2. 渐进式抽取: 优先抽取那些复用价值最高、依赖最少、边界最清晰的通用模块。例如,鉴权服务往往是第一个被抽离的,因为它通常与所有需要安全访问的服务都相关。
  3. API 网关的利用: 通过API网关将部分通用能力(如认证、限流、日志记录)下沉到网关层,作为所有请求的统一入口,减少对业务服务的侵入。

关键考虑因素

在做出决策时,请务必考虑以下几点:

  • 业务领域边界: 模块是否真正“通用”?如果它与某个特定业务领域耦合紧密,则不适合作为公共服务。
  • 团队能力与资源: 团队是否具备开发、部署和运维独立服务的能力和资源?
  • 数据隔离: 如果通用模块涉及数据存储,如何确保数据的隔离性和安全性?
  • 可观测性: 独立的公共服务需要完善的日志、监控、链路追踪机制。
  • 服务治理: 服务的版本控制、发布、灰度、回滚机制等都需要提前规划。

总结

在我看来,将具有通用性的模块抽取为独立的公共服务,是面向未来、拥抱微服务架构的必然选择。它虽然增加了初期的复杂性,但从长远来看,能显著提升系统的可维护性、可扩展性和团队的开发效率。

当然,这并非一蹴而就的过程,需要根据实际情况、团队能力和业务需求,制定详细的迁移计划和路线图。切勿盲目追求“微服务化”,而应以业务价值和解决实际问题为导向,循序渐进地进行架构演进。将每一次“绞杀”单体应用的机会,都视为通用模块“涅槃重生”的契机。

架构老兵 微服务架构重构共享服务

评论点评