

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 分解单体的模式
<a name="decomposing-patterns"></a>

决定分解应用程序组合中的一个单体之后，您应该选择适当的分解模式并将其引入您的组织。

**注意**  
您可以使用多种模式来分解一个单体。例如，您可以按[业务能力](decompose-business-capability.md)分解单体，然后使用[子域模式](decompose-subdomain.md)对其进行更多分解。

**Topics**
+ [按业务能力分解](decompose-business-capability.md)
+ [按子域分解](decompose-subdomain.md)
+ [按交易分解](decompose-transactions.md)
+ [按团队提供的服务模式](service-per-team.md)
+ [Strangler fig 模式](strangler-fig.md)
+ [按抽象模式分支](branch-by-abstraction.md)

# 按业务能力分解
<a name="decompose-business-capability"></a>

您可以利用组织的业务流程或能力来分解一个单体。*业务能力*是指企业如何创造价值（例如，销售、客户服务或营销）。通常，一个组织具有多种业务能力，这些能力因部门或行业而异。如果您的团队对组织的业务部门有足够的洞察力，并且每个业务部门都有主题专家 (SMEs)，则使用此模式。下表说明了使用此模式的优势和劣势。


****  

| 优点 | 缺点 | 
| --- | --- | 
|  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/modernization-decomposing-monoliths/decompose-business-capability.html) |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/modernization-decomposing-monoliths/decompose-business-capability.html) | 

在下图中，保险单体根据业务能力分解为四个微服务。

![\[通过业务能力分解单体\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/modernization-decomposing-monoliths/images/decompose-by-business-capability.png)


# 按子域分解
<a name="decompose-subdomain"></a>

这种模式使用[域驱动设计 (DDD)](https://en.wikipedia.org/wiki/Domain-driven_design)子域来分解单体。这种方法将组织的域模型分解为单独的子域，这些子域被标记为*核心*（业务的关键差异化因素）、*支持*（可能与业务相关但与差异化因素无关）或*通用*（不是特定于业务）。这种模式适用于现有的单体系统，这些系统在子域相关模块之间具有明确定义的边界。这意味着您可以通过将现有模块重新打包为微服务来分解整体结构，而无需大量重写现有代码。每个子域都有一个模型，该模型的范围称为有*界限上下文*。微服务是围绕这种界限上下文开发的。下表说明了使用此模式的优势和劣势。


****  

| 优点 | 缺点 | 
| --- | --- | 
|  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/modernization-decomposing-monoliths/decompose-subdomain.html) | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/modernization-decomposing-monoliths/decompose-subdomain.html) | 

下图显示了保险单体在按业务能力分解后如何将其分解为子域。

![\[按子域分解单体\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/modernization-decomposing-monoliths/images/decompose-by-subdomain.png)


该插图显示，*销售*和*营销*服务被分解为较小的微服务。*采购*和*索赔*模型是*销售*的重要业务差异化因素，它们分为两个独立的微服务。通过使用*活动*、*分析*和*报告*等辅助业务功能来分解*营销*。

# 按交易分解
<a name="decompose-transactions"></a>

在分布式系统中，应用程序通常必须调用多个微服务才能完成一项业务事务。为避免延迟问题或两阶段提交问题，您可以根据事务对微服务进行分组。如果您认为响应时间很重要，并且不同的模块在打包后不会形成整体结构，则这种模式是合适的。下表说明了使用此模式的优势和劣势。


****  

| 优点 | 缺点 | 
| --- | --- | 
|  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/modernization-decomposing-monoliths/decompose-transactions.html) |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/modernization-decomposing-monoliths/decompose-transactions.html)  | 

在下图中，保险单体根据交易分解为多个微服务。

![\[通过交易分解单体\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/modernization-decomposing-monoliths/images/decompose-by-transaction.png)


在保险系统中，索赔申请通常在提交后标记给客户。这意味着，如果没有*客户*微服务，理赔服务就不可能存在。*销售*和*客户*打包在一个微服务包中，业务交易需要与两者进行协调。

# 按团队提供的服务模式
<a name="service-per-team"></a>

每个团队的服务模式不是按业务能力或服务分解单体，而是将其分解为由各个团队管理的微服务。每个团队都对一项业务能力负责，并拥有该能力的代码库。该团队独立开发、测试、部署或扩展其服务，主要与其他团队互动以进行协商。 APIs我们建议您将每项微服务分配给一个团队。但是，如果团队足够大，则多个子团队可以在同一个团队结构中拥有单独的微服务。下表说明了使用此模式的优势和劣势。


****  

| 优点 | 缺点 | 
| --- | --- | 
|  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/modernization-decomposing-monoliths/service-per-team.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/modernization-decomposing-monoliths/service-per-team.html)  | 

下图显示了如何将单体拆分为由各个团队管理、维护和交付的微服务。

![\[由团队将单体分解为微服务\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/modernization-decomposing-monoliths/images/service-per-team.png)


# Strangler fig 模式
<a name="strangler-fig"></a>

本指南中到目前为止讨论的设计模式适用于在全新环境中开发的项目的分解应用程序。那么涉及大型单体式应用程序、在遗留系统中开发的项目呢？ 将以前的设计模式应用于它们会很困难，因为在积极使用它们的同时将它们分解成较小的部分是一项艰巨的任务。

[Strangler fig 模式](https://martinfowler.com/bliki/StranglerFigApplication.html)是一种流行的设计模式，由 Martin Fowler 推出，他的灵感来自于某种类型的无花果，它在树的上部分支上自己播种。现有的树最初成为新无花果的支撑结构。然后无花果将其根送到地面，逐渐包裹原树，只留下新的，自我支撑的无花果。

这种模式通常用于通过将特定功能替换为新服务来逐步将单体式应用程序转换为微服务。目标是让传统版本和新的现代化版本共存。新系统最初由现有系统支持并覆盖现有系统。这种支持使新系统有时间进行扩展，并有可能完全取代旧系统。

通过实现 strangler fig 模式从单体应用程序过渡到微服务的过程包括三个步骤：转换、共存和消除：
+ *转换*：通过移植或与旧版应用程序并行重写来识别和创建现代化组件。
+ *共存*：保留单体式应用程序以进行回滚。通过在单体外围加入 HTTP 代理（例如 [Amazon API Gateway](https://docs.aws.amazon.com/apigateway/latest/developerguide/welcome.html)）来拦截外部系统调用，并将流量重定向到现代化版本。这可以帮助您逐步实现功能。
+ *消除*：当流量从传统单体重定向到现代化服务时，旧功能将在单体结构中停用。

下表说明了使用 strangler fig 模式的优势和劣势。


****  

| 优点 | 缺点 | 
| --- | --- | 
|  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/modernization-decomposing-monoliths/strangler-fig.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/modernization-decomposing-monoliths/strangler-fig.html)  | 

下图显示了如何通过将 strangler fig 模式应用于应用程序架构来将单体拆分为微服务。两个系统并行运行，但是您将开始将功能移到单体代码库之外，并使用新功能对其进行增强。这些新功能使您有机会以最适合自己需求的方式架构微服务。在全部被微服务取代之前，您将继续从单体上剥离这些功能。此时，您可以取消单体应用程序。这里要注意的关键点是，单体和微服务将在一段时间内共同存在。

![\[使用 strangler fig 模式将单体分解为微服务\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/modernization-decomposing-monoliths/images/strangler-fig.png)


# 按抽象模式分支
<a name="branch-by-abstraction"></a>

当您能在单体周边拦截调用时，Strangler fig 模式效果很好。但是，如果您想对存在于遗留应用程序堆栈中更深层次且具有上游依赖关系的组件进行现代化改造，我们建议按抽象模式分支。这种模式使您能够对现有代码库进行更改，以允许现代化版本与旧版本安全共存，而不会造成中断。

要成功使用抽象分支模式，请按照以下过程操作：

1. 识别具有上游依赖关系的单体组件。

1. 创建一个抽象层，用于表示待现代化的代码与其客户端之间的交互。

1. 抽象到位后，将现有客户端更改为使用新的抽象。

1. 在单体结构之外使用经过重新设计的功能，创建新的抽象实现。

1. 准备就绪后，将抽象切换到新的实现。

1. 当新的实现为用户提供了所有必需功能并且不再使用单体架构时，请清理旧的实现。

抽象分支模式经常与[功能切换](http://martinfowler.com/bliki/FeatureToggle.html)混淆，后者还允许您逐步更改系统。不同之处在于，功能切换旨在允许开发新功能，并在系统运行时保持这些功能对用户不可见。因此，在部署时或运行时系统使用功能切换来选择特定功能或一组功能在应用程序中是否可见。抽象分支是一种开发技术，可以与功能切换结合使用，以便在新旧抽象之间切换。

下表说明了按抽象模式使用分支的优势和劣势。


****  

| 优点 | 缺点 | 
| --- | --- | 
|  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/modernization-decomposing-monoliths/branch-by-abstraction.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/modernization-decomposing-monoliths/branch-by-abstraction.html)  | 

下图显示了保险单体中*通知*组件的分支抽象模式。它首先为通知功能创建摘要或接口。以较小的增量更改现有客户端，以使用新的抽象。这可能需要在代码库中搜索与*通知*组件 APIs 相关的调用。您可以将通知功能的新实现作为单体架构之外的微服务进行创建，并将其托管在现代化的架构中。在您的单体中，您新创建的抽象接口充当代理并调用新的实现。您可以将通知功能移植到新的实现中，在经过全面测试并准备就绪之前，新实现将保持非活动状态。当新的实现准备就绪时，您可以切换抽象来使用它。您需要使用一种可以轻松切换的切换机制（例如功能切换），这样在遇到任何问题时可以轻松切换回旧功能。当新的实现开始向用户提供所有通知功能并且不再使用单体时，您可以清理较旧的实现并删除可能已实现的任何切换功能标志

![\[通过抽象模式使用分支将单体分解为微服务\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/modernization-decomposing-monoliths/images/branch-by-abstraction.png)
