51、单体应用向微服务转换的实用策略与案例分析

单体应用向微服务转换的实用策略与案例分析

1. 宏服务提取

在将单体应用转换为微服务的过程中,提取组件是一个常见的策略。通常,我们会先提取高层次的组件,然后递归地将这些组件分解成更小的部分,直到达到微服务的粒度,每个部分都能独立存在并满足微服务的要求。可以把单体应用看作是一个最大的整体,运用分治法将其逐步拆解。

例如,在图 10 - 13 中,紧密耦合的组件 A 和 B 被提取为一个宏服务。任何需要访问提取功能的原始单体应用内的功能,都会被重定向到新创建的服务。比如组件 C 和 D 会被重定向到新创建的宏服务。

提取宏服务是迈向微服务的第一步。由于单体应用内的耦合性,一开始提取的服务通常较大。当这个中间解决方案稳定后,就可以将宏服务进一步拆分为更小的微服务。提取宏服务后,新的客户端就可以开始访问和使用提取服务的功能。

在提取宏服务时,可能不会过于关注使服务符合微服务的所有属性。例如,宏服务通常会执行多个业务功能,但仍然与单体应用的其他部分保持松散耦合。当存在复杂的决策逻辑,难以将其重构为独立组件时,将整个决策逻辑和背后的额外领域逻辑作为一个大组件提取出来,是向微服务重构的一个良好开端。

2. 实现问题及解决方案

一旦确定要提取的组件,就可以克隆可直接提取的代码,并将其作为微服务发布。接下来是测试和验证提取的部分。当对新发布的微服务感到满意后,就可以将必要的调用路由到它。

对于使用从单体应用迁移到微服务功能的现有客户端应用程序或组件,可以采用以下两种处理方式:
- 重写调用 :将客户端应用程序或组件重写为直接调用新的微服务。但这种方式需要时间进行重写,并且在这些组件成为微服务之前可能无法实现。
- 使用路由拦截器 :让客户端应用程序或组件保持不变,通过路由拦截器(外观组件)将调用转发到新的微服务。外观组件可以执行协议桥接和消息转换,使现有客户端组件能够与新的微服务进行交互。当存在无法更改的客户端(如第三方客户端)时,这是唯一的选择。

外观组件除了协议桥接和消息转换外,还可以充当反向代理,执行多种操作,如安全控制、动态消息路由、流量监控、断路器甚至缓存。

有时可以使用重构工具(如 IBM Mono2Micro)来提取组件。该工具可以在单体应用中找到合适的“细微裂缝”,然后将代码分区,生成包装代码以重构分区,将其提取为宏服务或微服务,并提供包装代码将单体应用的代码委托给新的微服务。

这种方法的主要优点是可以将微服务架构的优势应用于从单体应用中提取的功能。能够更快地更改、测试和部署提取的部分,而不会影响或发布整个单体应用。外观组件还能使现有客户端或单体应用内的代码与新创建的微服务无缝交互。

然而,在单体应用中找到解耦的部分可能很困难,有时也看不到提取这些部分的直接好处。对于较大的部分,团队可能没有时间或意愿将其重构为更小的微服务。提取的宏服务通常包含紧密耦合的部分,这使得添加新功能时修改代码比完全重构为微服务更困难。

3. 提取组件的示例
3.1 航空公司示例

在一个航空公司的重构示例中,最初的单体应用执行了三大类适合重构的业务功能:
- “fly”:代表“飞行日”功能,如值机、行李托运和升舱购买。
- “try”:代表航班搜索。
- “buy”:代表购买流程。

这种逻辑划分使我们能够在每个组内寻找更小的逻辑单元。通过查看单体应用各部分的代码,我们发现机票购买流程适合作为宏服务提取。该流程虽然内部紧密耦合,但提取后减少了系统中的重复代码,是向微服务重构的一个良好早期步骤。

3.2 电子商务示例

在电子商务单体应用中,分析“细微裂缝”后发现,可以轻松地从单体应用中提取结账功能。然后将提取的功能重构为两个更小的微服务:结账和购物车。在这个示例中,单体应用中的组件 Y 和 Z 被更新为调用新创建的外部服务。

下面是提取组件的流程 mermaid 图:

graph LR
    A[确定要提取的组件] --> B[克隆代码并发布为微服务]
    B --> C[测试和验证提取部分]
    C --> D[路由必要调用到微服务]
    D --> E{处理现有客户端}
    E --> F[重写客户端调用]
    E --> G[使用路由拦截器]
4. 先重构再提取

在将单体应用转换为微服务的过程中,有些区域虽然被“细微裂缝”识别出来,但由于内部存在一定程度的耦合,尤其是那些经常变化的部分,直接提取可能比较困难。因此,需要先对单体应用进行重构,再提取组件。

单体应用通常内部组件之间存在紧密耦合和许多依赖关系,使得提取现有代码变得困难。为了降低耦合度,使代码更易于提取,我们可以采取以下方法:
- 模块化重构 :将部分耦合的代码重构为具有明确定义接口的模块。首先在单体应用中找到可以重构为模块的地方,这些模块后续可以从单体应用中提取为微服务。例如,在电子商务单体应用中,功能“a”和“b”可以被重构为组件 A 和 B,然后将这些重构后的模块化部分提取为微服务。
- 使用重构工具和技术 :分析具有耦合性的功能代码,找出可以使代码更模块化的地方,从而更容易提取为微服务。对于无法直接提取的“细微裂缝”,可以在单体应用内部进行重构。代码异味工具和重构工具可以帮助找到这些地方并进行代码重构。
- 结合功能开发进行重构 :在添加新功能或修复现有功能时,单体应用中会有一些区域需要进行调整以适应变化。这时可以考虑是否有部分代码可以进行重构并提取为微服务。这通常是一个渐进的过程,例如可以使用外观模式将多个相关调用集中到一个公共点,还可以利用 Java 中的接口或 Rust 中的特性等语言特性来辅助实现。随着时间的推移,将外观模式演变为服务 API,让使用原外观模式的客户端逐渐转换为使用服务 API 的客户端,之后就更有可能成功使用提取组件的方法将服务 API 背后的代码提取出来。
- 数据拆分与数据库重构 :当代码难以理解时,“为理解而重构”是个不错的方法,它可以帮助我们更好地了解领域和当前实现,并发现可以提取的区域。在提取组件之前,拆分数据也是很有用的,特别是当使用大型共享数据库并通过数据库与其他组件进行通信时。可以结合数据库重构机制(如反规范化),并将组件重构为通过接口而不是数据库进行通信。

这种先重构再提取的方法有两个主要优点:一是部分单体应用被重构为更好的设计,更易于演进和维护;二是这些重构后的组件在需要时更容易提取为微服务。但也存在一些缺点,比如可能需要更长时间才能获得微服务带来的好处,而且在单体应用中创建新的抽象可能会增加复杂性,学习和维护这些抽象也需要花费时间和专业知识。

5. 先重构再提取的案例分析
5.1 金融服务系统

在一个金融服务系统中,开发人员为了应对扩展问题,采用了不恰当的方式,将系统中的所有对象都设计为分布式对象,导致大量的远程调用,系统性能严重下降。针对这个问题,建议采用两步走的方法:
- 第一步 :将内部(数据表示)调用重构为普通的 Java 方法调用,这一举措显著提高了系统的整体性能。
- 第二步 :将树状结构顶部的领域概念重构为具有 RESTful 接口的组件,每个组件只执行一个业务功能。这种方法的优势在于,团队在完成向微服务架构的过渡之前,就能在降低系统复杂性和提高性能方面取得显著成果。

5.2 电子商务系统

在之前的电子商务示例中,我们通过识别“细微裂缝”,重构了结账和购物车功能,并将这两个功能提取为一个服务,然后进一步将其拆分为更小的微服务。图 10 - 17 展示了如何将这两种技术结合应用于电子商务单体应用,提取结账和购物车功能。具体步骤如下:
- 首先,将结账和购物车功能识别为单体应用中的“细微裂缝”,并将其重构为独立的模块。
- 然后,将这些模块提取为一个包含结账和购物车功能的宏服务。
- 最后,将这个宏服务拆分为结账和购物车两个微服务。

下面是先重构再提取的流程 mermaid 图:

graph LR
    A[识别有耦合的区域] --> B[模块化重构]
    B --> C[使用工具辅助重构]
    C --> D[结合功能开发演进]
    D --> E[数据拆分与数据库重构]
    E --> F[提取组件为微服务]
6. 替换为微服务

在将单体应用转换为微服务的过程中,虽然已经能够通过“细微裂缝”识别出一些可以提取为微服务的区域,但仍然存在一些复杂且重要的功能部分,由于它们在单体应用中紧密耦合,难以直接提取。对于这些部分,我们可以采用替换为微服务的方法。

在单体应用中,特别是那些没有很好地模块化组织的应用,更改一个功能通常需要协调更改多个部分。对于那些经常变化的部分,用微服务替换它们可以使更改更容易,并且对单体应用的其他部分影响更小。然而,由于这些部分与内部组件之间存在许多依赖关系,很难将它们从现有代码中分离出来,而且现有的单体应用可能过于脆弱,添加新代码可能会导致副作用。

因此,我们可以采取以下步骤将这些功能替换为微服务:
1. 代码冻结 :冻结单体应用中想要替换的功能,停止对其进行开发和更改。
2. 创建新微服务 :重新实现(重写)该功能作为一个新的微服务。
3. 金丝雀发布 :在仔细测试的同时,采用金丝雀发布的方式逐步引入新的微服务,观察其对系统的影响。
4. 更改接口 :更改单体应用中该功能的原始实现接口,使其调用新创建的微服务。

例如,对于单体应用中的组件 X,将其功能锁定后,重写为微服务 X’。新的微服务 X’经过测试和验证后,新的客户端组件就可以开始使用其功能。当新的微服务成为新系统的一部分并开始演进时,单体应用内的其他组件可能需要访问该微服务的新功能,此时有两种访问方式:
- 直接重写调用 :将单体应用中的客户端组件重写为直接调用新的微服务,如组件 Y 被更新为直接调用 X’。
- 使用代理 :创建一个代理,将单体应用中原始组件的调用委托给新的微服务,如组件 Z 和 W 仍然调用 X,但会被委托给 X’以获取更新的功能。

下面是替换为微服务的步骤表格:
| 步骤 | 操作 |
| ---- | ---- |
| 1 | 代码冻结单体应用中要替换的功能 |
| 2 | 创建实现该功能的新微服务 |
| 3 | 金丝雀发布新微服务并仔细测试 |
| 4 | 更改单体应用中该功能的接口以调用新微服务 |

综上所述,将单体应用转换为微服务是一个复杂的过程,需要根据不同的情况选择合适的策略。提取宏服务、先重构再提取以及替换为微服务等方法都有各自的适用场景和优缺点。通过实际案例的分析,我们可以更好地理解这些方法的应用,从而在实际项目中做出更明智的决策。

单体应用向微服务转换的实用策略与案例分析

7. 策略对比分析

为了更清晰地了解提取宏服务、先重构再提取以及替换为微服务这三种策略的特点,我们可以通过以下表格进行对比:
| 策略 | 适用场景 | 优点 | 缺点 |
| ---- | ---- | ---- | ---- |
| 提取宏服务 | 单体应用中存在相对独立但内部耦合较紧密的功能块,难以直接拆分为小的微服务 | 是迈向微服务的第一步,可减少系统中的重复代码;能让新客户端快速访问提取的功能;可利用微服务架构优势,且不影响单体应用整体发布 | 难以找到解耦部分,可能看不到直接好处;团队可能缺乏时间和意愿将大的部分重构为小的微服务;提取的宏服务内部耦合,添加新功能时修改代码较困难 |
| 先重构再提取 | 单体应用内部组件存在一定耦合,尤其是经常变化的部分,直接提取困难 | 部分单体应用被重构为更好的设计,易于演进和维护;重构后的组件更易提取为微服务 | 需要较长时间才能获得微服务好处;在单体应用中创建新抽象会增加复杂性,学习和维护成本高 |
| 替换为微服务 | 单体应用中复杂且重要的功能部分紧密耦合,难以直接提取,且该部分经常变化 | 使经常变化的部分更改更容易,对单体应用其他部分影响小;新微服务可独立演进 | 代码冻结可能影响部分业务;重新实现功能需要投入较多资源;金丝雀发布和测试过程需谨慎操作 |

通过这个对比表格,我们可以根据单体应用的具体情况和项目需求,更准确地选择合适的转换策略。

8. 实施注意事项

在实施上述策略将单体应用转换为微服务时,还需要注意以下几个方面:
- 团队协作 :不同的策略可能需要不同的技能和知识,团队成员之间需要密切协作。例如,在使用重构工具时,需要有熟悉工具操作的人员;在重写代码时,需要开发人员具备相应的技术能力。同时,团队成员之间的沟通也非常重要,确保每个人都清楚项目的目标和进度。
- 测试与验证 :无论是提取宏服务、重构组件还是替换为微服务,都需要进行充分的测试和验证。在新的微服务发布前,要进行单元测试、集成测试等,确保其功能的正确性和稳定性。金丝雀发布时,要密切观察系统的运行情况,及时发现并解决问题。
- 数据管理 :在转换过程中,数据的管理至关重要。如果涉及到数据库的拆分和重构,要确保数据的一致性和完整性。可以采用数据迁移工具和技术,在迁移过程中进行数据验证和清理。同时,要考虑微服务之间的数据交互方式,避免出现数据冲突和不一致的情况。
- 监控与维护 :转换为微服务后,系统的监控和维护变得更加复杂。需要建立完善的监控体系,实时监测微服务的运行状态、性能指标等。对于出现的问题,要能够及时定位和解决。同时,要定期对微服务进行维护和优化,确保其持续稳定运行。

9. 未来趋势展望

随着技术的不断发展,单体应用向微服务转换的策略也会不断演进。未来可能会出现以下趋势:
- 自动化工具的发展 :目前已经有一些重构工具可以辅助我们进行组件提取和代码重构,但未来的工具可能会更加智能化和自动化。例如,能够自动识别单体应用中的“细微裂缝”,并根据不同的策略自动完成转换过程。
- 云原生技术的融合 :云原生技术如容器、编排工具等将与微服务更加紧密地结合。通过容器化部署微服务,可以提高资源利用率和部署效率。编排工具可以实现微服务的自动化管理和调度,进一步提升系统的灵活性和可扩展性。
- 人工智能的应用 :人工智能技术可能会应用于微服务的性能优化和故障预测。例如,通过机器学习算法分析微服务的运行数据,预测可能出现的故障,并提前采取措施进行预防。同时,人工智能还可以帮助优化微服务的资源分配,提高系统的整体性能。

10. 总结

将单体应用转换为微服务是一个复杂而又具有挑战性的过程,但通过合理选择提取宏服务、先重构再提取以及替换为微服务等策略,并注意实施过程中的团队协作、测试验证、数据管理和监控维护等方面,我们可以成功地实现这一转换。同时,关注未来的技术趋势,不断学习和应用新的技术,将有助于我们更好地应对微服务架构带来的机遇和挑战。

下面是一个总结整个转换过程的 mermaid 流程图:

graph LR
    A[单体应用] --> B{选择策略}
    B --> C[提取宏服务]
    B --> D[先重构再提取]
    B --> E[替换为微服务]
    C --> F[测试与验证]
    D --> F
    E --> F
    F --> G[部署与上线]
    G --> H[监控与维护]
    H --> I[持续优化]

希望通过本文的介绍,能帮助大家更好地理解单体应用向微服务转换的实用策略和方法,在实际项目中做出更明智的决策。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值