修改错句和标准化术语

This commit is contained in:
Oopsguy 2019-06-29 09:10:00 +08:00
parent 0380318b34
commit 4661e95bff
5 changed files with 110 additions and 90 deletions

View File

@ -80,7 +80,7 @@
![图 1-5、打车应用的数据库架构][image-5] ![图 1-5、打车应用的数据库架构][image-5]
从表面上看,微服务架构模式类似于 SOA。微服务是由一组服务组成。然而换另一种方式去思考微服务架构模式它是没有商业化的 SOA没有集成 [Web 服务规范][18]WS-\*和企业服务总线Enterprise Service BusESB。基于微服务的应用支持更简单的轻量级协议例如REST而不是 WS-\*。它们也尽量避免使用 ESB而是实现微服务本身有类似 ESB 的功能。微服务架构也拒绝了 SOA 的其他部分,例如,数据访问[规范模式][19]概念。 从表面上看,微服务架构模式类似于 SOA。微服务是由一组服务组成。然而换另一种方式去思考微服务架构模式它是没有商业化的 SOA没有集成 [Web 服务规范][18]WS-\*和企业服务总线Enterprise Service BusESB。基于微服务的应用支持更简单的轻量级协议例如REST而不是 WS-\*。它们也尽量避免使用 ESB而是实现微服务本身有类似 ESB 的功能。微服务架构也拒绝了 SOA 的其他部分,例如,数据访问[规范模式][19]概念。
<a id="the-benefits-of-microservices"></a> <a id="the-benefits-of-microservices"></a>
@ -130,11 +130,11 @@
By Floyd Smith By Floyd Smith
[10000 个网站中有超过 50%][26] 使用 NGINX这主要是因为它有作为反向代理服务器的能力。你可以把 NGINX 放在当前应用甚至是数据库服务器之前以获取各种功能 —— 更高的性能、更高的安全性、可扩展性、灵活性等。你现有的应用只需要配置代码和作出极少的改变,甚至无需改变。然而,对于存在性能压力或者预计未来存在高负荷的站点,使用 NGINX 的效果看起来可能没那么神奇。 [10000 个网站中有超过 50%][26] 使用 NGINX这主要是因为它有作为反向代理服务器的能力。你可以把 NGINX 放在当前应用甚至是数据库服务器之前以获取各种功能 —— 更高的性能、更高的安全性、可扩展性、灵活性等。你现有的应用只需要配置代码和作出极少的改变,甚至无需改变。然而,对于存在性能压力或者预计未来存在高负荷的站点,使用 NGINX 的效果看起来可能没那么神奇。
那么这与微服务有什么关系呢?实现一个反向代理服务器,并使用 NGINX 的其他功能来为你提供架构灵活性反向代理服务器、静态和应用文件缓存、SSL/TLS 和 HTTP/2 这些功能都将从你的应用中剔除。让应用只做它该做的事NGINX 还可以作为负载均衡器这是微服务实施过程中的一个关键角色。NGINX Plus 的功能包含了复杂的负载均衡算法、多种方式的会话持久和管理监控这些对微服务尤其有用NGINX 最近还增加了使用 DNS SRV 记录的服务发现支持这是一个顶尖的功能。而且如本章所述NGINX 可以自动化部署微服务。 那么这与微服务有什么关系呢?实现一个反向代理服务器,并使用 NGINX 的其他功能来为你提供架构灵活性反向代理服务器、静态和应用文件缓存、SSL/TLS 和 HTTP/2 这些功能都将从你的应用中剔除。让应用只做它该做的事NGINX 还可以作为负载均衡器这是微服务实施过程中的一个关键角色。NGINX Plus 的功能包含了复杂的负载均衡算法、多种方式的会话持久和管理监控这些对微服务尤其有用NGINX 最近还增加了使用 DNS SRV 记录的服务发现支持这是一个顶尖的功能。而且如本章所述NGINX 可以自动化部署微服务。
此外NGINX 还提供了必要的功能来支撑 [NGINX 微服务参考架构][27]中的三大模型。代理模型使用 NGINX 作为 API 网关;路由网格模型使用一个额外的 NGINX 作为进程间通信中枢Fabric 模型中的每个微服务使用一个 NGINX 来控制 HTTP 流量,在微服务之间实现 SSL/TLS这非常有突破性。 此外NGINX 还提供了必要的功能来支撑 [NGINX 微服务参考架构][27]中的三大模型。代理模型使用 NGINX 作为 API 网关;路由网格模型使用一个额外的 NGINX 作为进程间通信中枢Fabric 模型中的每个微服务使用一个 NGINX 来控制 HTTP 流量,在微服务之间实现 SSL/TLS这非常有突破性。
[1]: http://www.gartner.com/technology/research/methodologies/hype-cycle.jsp [1]: http://www.gartner.com/technology/research/methodologies/hype-cycle.jsp
[2]: http://microservices.io/patterns/monolithic.html [2]: http://microservices.io/patterns/monolithic.html

View File

@ -155,7 +155,7 @@ API 网关需要知道与其通信的每个微服务的位置IP 地址和端
by Floyd Smith by Floyd Smith
本章讨论了如何将 API 网关作为系统的单入口点。它可以处理诸如负载均衡、缓存、监控和协议转换等其他功能 —— 当 NGINX 充当反向代理服务器时,其可以作为系统的单入口点,并且支持所有提到的一个 API 网关有的附加功能。因此使用 NGINX 作为 API 网关的主机可以很好地工作。 本章讨论了如何将 API 网关作为系统的单入口点。它可以处理诸如负载均衡、缓存、监控和协议转换等其他功能 —— 当 NGINX 充当反向代理服务器时,其可以作为系统的单入口点,并且支持所有提到的一个 API 网关有的附加功能。因此使用 NGINX 作为 API 网关的主机可以很好地工作。
将 NGINX 作为 API 网关并不是本书最开始的想法。[NGINX Plus](https://www.nginx.com/products/) 是一个用于管理和保护基于 HTTP 的 API 流量的领先平台。你可以实现自己的 API 网关或使用现有的 API 管理平台,其中许多使用了 NGINX。 将 NGINX 作为 API 网关并不是本书最开始的想法。[NGINX Plus](https://www.nginx.com/products/) 是一个用于管理和保护基于 HTTP 的 API 流量的领先平台。你可以实现自己的 API 网关或使用现有的 API 管理平台,其中许多使用了 NGINX。

View File

@ -243,7 +243,7 @@ Leonard Richardson 定义了一个非常有用的 [REST 成熟度模型](https:/
- 因为客户端和服务直接通信(没有一个中间者来缓冲消息),所以它们必须在交换期间都运行着。 - 因为客户端和服务直接通信(没有一个中间者来缓冲消息),所以它们必须在交换期间都运行着。
- 客户端必须知道每个服务实例的位置(即 URL。如[第二章](2-using-an-api-gateway.md)关于 API 网关所述,这是现代应用面临的一个复杂问题。客户端必须使用服务发现机制来定位服务实例。 - 客户端必须知道每个服务实例的位置(即 URL。如[第二章](2-using-an-api-gateway.md)关于 API 网关所述,这是现代应用面临的一个复杂问题。客户端必须使用服务发现机制来定位服务实例。
开发人员社区最近重新发现了 RESTful API 接口定义语言的价值。有几个可以选择,包括 [RAML](https://raml.org/) 和 [Swagger](http://swagger.io/)。一些 IDL如 Swagger允许你定义请求和响应消息的格式。其他如 RAML需要你使用一个单独的规范如 [JSON 模式](http://json-schema.org/)。除了用于描述 API 之外IDL 通常还有可从接口定义生成客户端 stub 和服务器 skeleton 的工具。 开发人员社区最近重新发现了 RESTful API 接口定义语言的价值。有几个可以选择,包括 [RAML](https://raml.org/) 和 [Swagger](http://swagger.io/)。一些 IDL如 Swagger允许你定义请求和响应消息的格式。其他如 RAML需要你使用一个单独的规范如 [JSON 模式](http://json-schema.org/)。除了用于描述 API 之外IDL 通常还有可从接口定义生成客户端 stub 和服务器 skeleton 的工具。
<a id="thrift"></a> <a id="thrift"></a>
@ -287,7 +287,7 @@ NGINX 使你能够实现各种伸缩和镜像操作,使你的应用更加灵
我们在 NGINX 方面建议你在实现基于微服务的应用时考虑使用四层架构。Forrester 在这方面有详细的报告,你可以从 NGINX 上免费下载。这些层代表客户端(包括台式机或笔记本电脑、移动、可穿戴或 IoT 客户端)、交付、聚合(包括数据存储)和服务,其中包括应用功能和特定服务,而不是共享数据存储。 我们在 NGINX 方面建议你在实现基于微服务的应用时考虑使用四层架构。Forrester 在这方面有详细的报告,你可以从 NGINX 上免费下载。这些层代表客户端(包括台式机或笔记本电脑、移动、可穿戴或 IoT 客户端)、交付、聚合(包括数据存储)和服务,其中包括应用功能和特定服务,而不是共享数据存储。
四层架构比以前的三层架构更加灵活,有可扩展、响应灵敏、移动友好,并且内在支持基于微服务的应用开发和交付等优点。像 Netflix 和 Uber 这样的行业引领者通过使用这种架构来实现用户所需的性能水平。 四层架构比以前的三层架构更加灵活,有可扩展、响应灵敏、移动友好,并且内在支持基于微服务的应用开发和交付等优点。像 Netflix 和 Uber 这样的行业引领者通过使用这种架构来实现用户所需的性能水平。
NGINX 本质上非常适合四层架构,从客户端层的媒体流,到交付层的负载均衡与缓存、聚合层的高性能和安全的基于 API 的通信的工具,以及服务层中支持灵活管理的短暂服务实例。 NGINX 本质上非常适合四层架构,从客户端层的媒体流,到交付层的负载均衡与缓存、聚合层的高性能和安全的基于 API 的通信的工具,以及服务层中支持灵活管理的短暂服务实例。

View File

@ -1,111 +1,118 @@
# 6、选择部署策略 # 6、选择部署策略
本书主要介绍关于如何使用微服务构建应用程序,这是本书的第六章。第一章介绍了[微服务架构模式](http://microservices.io/patterns/microservices.html),讨论了使用微服务的优点与缺点。之后的章节讨论了微服务架构的方方面面:[使用 API 网关](2-using-an-api-gateway.md)、[进程间通信](3-inter-process-communication.md)、[服务发现](4-service-discovery.md)和[事件驱动数据管理](5-event-driven-data-management-for-microservices.md)。在本章中,我们将介绍部署微服务的策略。
本书主要介绍关于如何使用微服务构建应用,这是本书的第六章。第一章介绍了[微服务架构模式](http://microservices.io/patterns/microservices.html),讨论了使用微服务的优点与缺点。之后的章节讨论了微服务架构的方方面面:[使用 API 网关](2-using-an-api-gateway.md)、[进程间通信](3-inter-process-communication.md)、[服务发现](4-service-discovery.md)和[事件驱动数据管理](5-event-driven-data-management-for-microservices.md)。在本章中,我们将介绍部署微服务的策略。
<a id="motivations"></a> <a id="motivations"></a>
## 6.1、动机 ## 6.1、动机
部署[单体应用](http://microservices.io/patterns/monolithic.html)程序意味着运行一个或多个相同副本的单个较大的应用程序。您通常会配置 N 个服务器(物理或虚拟),每台服务器上会运行 M 个应用程序实例。单体应用程序的部署并不总是非常简单,但它比部署微服务应用程序要简单得多。
[微服务应用程序](http://microservices.io/patterns/microservices.html)由数十甚至上百个服务组成。服务以不同的语言和框架编写。每个都是一个迷你的应用程序,具有自己特定的部署、资源、扩展和监视要求。例如,您需要根据该服务的需求运行每个服务的一定数量的实例。此外,必须为每个服务实例提供相应的 CPU、内存和 I/O 资源。更具挑战性的是尽管如此复杂,部署服务也必须快速、可靠和具有成本效益。 部署[单体应用](http://microservices.io/patterns/monolithic.html)意味着运行一个或多个来自单个较大应用的相同副本。你通常会配置 N 个服务器(物理或虚拟),每台服务器上会运行 M 个应用实例。单体应用的部署并不总是那么简单,但它比部署微服务应用要简单得多。
[微服务应用](http://microservices.io/patterns/microservices.html)由数十甚至上百个服务组成。服务使用不同的语言和框架编写。每个服务都是一个迷你应用,有自己特定的部署、资源、扩展和监视要求。例如,你需要根据服务的需求为每个服务运行一定数量的实例。此外,必须为每个服务实例提供相应的 CPU、内存和 I/O 资源。更有挑战性的是尽管这些如此复杂,部署服务也必须要快速、可靠和具有成本效益。
有几种不同的微服务部署模式。我们首先看看单主机多服务实例模式。 有几种不同的微服务部署模式。我们首先看看单主机多服务实例模式。
<a id="multiple-service-instances-per-host-pattern"></a> <a id="multiple-service-instances-per-host-pattern"></a>
## 6.2、单主机多服务实例模式 ## 6.2、单主机多服务实例模式
部署微服务的一种方式是使用[单主机多服务实例](http://microservices.io/patterns/deployment/multiple-services-per-host.html)Multiple Service Instances per Host模式。当使用此模式时您可以提供一个或多个物理主机或虚拟主机并在每个上运行多个服务实例。从多方面来讲这是应用程序部署的传统方式。每个服务实例在一个或多个主机的标准端口上运行。主机通常被[当作宠物对待](https://www.nginx.com/blog/microservices-at-netflix-architectural-best-practices/#stateless-servers)。
一种微服务的部署方式是使用[单主机多服务实例](http://microservices.io/patterns/deployment/multiple-services-per-host.html)Multiple Service Instances per Host模式。当使用此模式时你可以提供一台或多个台物理主机或虚拟主机并在每台主机上运行多个服务实例。从多方面来讲这是传统的应用部署方式。每个服务实例在一台或多台主机的标准端口上运行。你需要[像照顾宠物一样照顾这些主机](https://www.nginx.com/blog/microservices-at-netflix-architectural-best-practices/#stateless-servers)。
图 6-1 展示了该模式的结构: 图 6-1 展示了该模式的结构:
![图 6-1、主机可支持多个服务实例](resources/6-1.png) ![图 6-1、主机可支持多个服务实例](resources/6-1.png)
这种模式有几个变体。一个变体是每个服务实例都是一个进程或进程组。例如,您可以在 [Apache Tomcat](http://tomcat.apache.org/) 服务器上将 Java 服务实例部署为 Web 应用程序。一个 [Node.js](https://nodejs.org/) 服务实例可能包含一个父进程和一个或多个子进程。 这种模式扩展出了多个变体。一个变体是每个服务实例都是一个进程或进程组。你可以将一个 Java 服务实例部署到 [Apache Tomcat](http://tomcat.apache.org/) 服务器作为一个 web 应用。一个 [Node.js](https://nodejs.org/) 服务实例可能包含一个父进程和一个或多个子进程。
此模式的另一个变体是在同一进程或进程组中运行多个服务实例。例如,您可以在同一个 Apache Tomcat 服务器上部署多个 Java Web 应用程序,或在同一 OSGI 容器中运行多个 OSGI 软件包。 此模式的另一个变体是在同一进程或进程组中运行多个服务实例。可以在同一个 Apache Tomcat 服务器上部署多个 Java Web 应用,或在同一 OSGI 容器中运行多个 OSGI 软件包。
单主机多服务实例模式有优点也有缺点。主要优点是资源使用率相对较高。多个服务实例共享服务器及操作系统。如果进程或进程组运行了多个服务实例(例如,共享相同的 Apache Tomcat 服务器和 JVM 的多个 Web 应用程序),则效率更高。 单主机多服务实例模式有优点也有缺点。主要优点是它的资源使用率相对较高。多个服务实例共享服务器及操作系统。如果进程或进程组运行了多个服务实例(例如,多个 Web 应用共享相同的 Apache Tomcat 服务器和 JVM则效率更高。
这种模式的另一个优点是部署服务实例相对较快。只需将服务复制到主机并启动它。如果服务是使用 Java 编写,则可以复制 JAR 或 WAR 文件。对于其他语言,例如 Node.js 或 Ruby您可以直接复制源代码。在任一情况下,通过网络复制的字节数都是相对较小的 这种模式的另一个优点是部署服务实例相对较快。只需将服务复制到主机并启动它。如果服务是使用 Java 编写,则可以复制 JAR 或 WAR 文件。对于其他语言,例如 Node.js 或 Ruby你可以直接复制源代码
另外,由于缺乏开销,通常启动一个服务是非常快的。如果该服务是自己的进程,你只需要启动它即可。如果服务是同一容器进程或进程组中运行的几个实例之一,则可以将其动态部署到容器中或者重新启动容器。 另外,由于开销较小,启动一个服务是非常快的。如果服务有自己的进程,你只需要启动它即可。如果服务是同一容器进程或进程组中运行的几个实例之一,则可以将其动态部署到容器中或者重新启动容器。
尽管这很有吸引力,但单主机多服务实例模式有一些明显的缺点。一个主要的缺点是服务实例很少或没有隔离,除非每个服务实例是一个单独的进程。虽然您可以准确地监视每个服务实例的资源利用率,但是您不能限制每个实例使用的资源。一个行为不当的服务实例可能会占用掉主机的所有内存或 CPU。 尽管这很有吸引力,但单主机多服务实例模式有一些明显的缺点。一个主要的缺点是服务实例很少隔离或没有隔离,除非每个服务实例是一个单独的进程。虽然你可以准确地监控每个服务实例的资源利用率,但你不能限制每个实例使用的资源占比。一个行为不当的服务实例可能会占用掉主机的所有内存或 CPU。
如果多个服务实例在同一进程中运行,那么将毫无隔离可言。例如,所有实例可能共享相同的 JVM 堆。行为不当的服务实例可能会轻易地破坏在同一进程中运行的其他服务。此外,无法监控每个服务实例使用的资源。 如果多个服务实例在同一进程中运行,那么将毫无隔离可言。例如,所有实例可能共享相同的 JVM 堆。行为不当的服务实例可能会轻易地破坏在同一进程中运行的其他服务。此外,无法监控每个服务实例使用的资源。
这种方式的另一个重要问题是部署服务的运维团队必须了解部署的具体细节。服务可以用多种语言和框架编写,因此开发团队必须与运维交代许多细节。这种复杂性无疑加大了部署过程中的错误风险。 这种方式的另一个重要问题是部署服务的运维团队必须了解部署的具体细节。服务可以是用不同的语言和框架编写,因此开发团队必须与运维交代许多细节。这种复杂性无疑加大了部署过程中的错误风险。
正如您所见,尽管这种方式简单,但单主机多服务实例模式确实存在一些明显的缺点。现在让我们来看看可以绕过这些问题部署微服务的其他方式。 正如你所见,尽管这种方式很简单,但单主机多服务实例模式确实存在一些明显的缺点。现在让我们来看看可以绕过这些问题的其他部署方式。
<a id="service-instance-per-host-pattern"></a> <a id="service-instance-per-host-pattern"></a>
## 6.3、每个主机一个服务实例模式 ## 6.3、每个主机一个服务实例模式
部署微服务的另一种方式是使用[每个主机一个服务实例](http://microservices.io/patterns/deployment/single-service-per-host.html)Service Instance per Host模式。当使用此模式时您可以在主机上单独运行每个服务实例。这种模式有两种不同形式每个虚拟机一个服务实例模式和每个容器一个服务实例模式。
部署微服务的另一种方式是使用[每个主机一个服务实例](http://microservices.io/patterns/deployment/single-service-per-host.html)Service Instance per Host模式。当使用此模式时你可以在主机上单独运行一个服务实例。这种模式有两种不同形式每个虚拟机一个服务实例模式和每个容器一个服务实例模式。
<a id="service-instance-per-virtual-machine-pattern"></a> <a id="service-instance-per-virtual-machine-pattern"></a>
### 6.3.1、每个虚拟机一个服务实例模式 ### 6.3.1、每个虚拟机一个服务实例模式
当您使用[每个虚拟机一个服务实例](http://microservices.io/patterns/deployment/service-per-vm.html)模式时将每个服务打包成一个虚拟机VM镜像如 [Amazon EC2 AMI](https://aws.amazon.com/cn/ec2/))。每个服务实例都是一个使用该 VM 镜像启动的 VM例如一个 EC2 实例)。
当你使用[每个虚拟机一个服务实例](http://microservices.io/patterns/deployment/service-per-vm.html)模式时将每个服务打包成一个虚拟机VM镜像如 [Amazon EC2 AMI](https://aws.amazon.com/cn/ec2/))。每个服务实例都是一个使用该 VM 镜像启动的 VM例如一个 EC2 实例)。
图 6-2 展示了该模式的结构: 图 6-2 展示了该模式的结构:
![图 6-2、服务可以各自运行在自己的虚拟机中](resources/6-2.png) ![图 6-2、服务可以各自运行在自己的虚拟机中](resources/6-2.png)
这是 Netflix 部署其视频流服务的主要方式。Netflix 使用 [Aminator](https://github.com/Netflix/aminator) 将每个服务打包 EC2 AMI。每个运行的服务实例都是一个 EC2 实例。 这是 Netflix 部署其视频流服务的主要方式。Netflix 使用 [Aminator](https://github.com/Netflix/aminator) 将每个服务打包 EC2 AMI。每个运行的服务实例都是一个 EC2 实例。
您可以使用多种工具来构建自己的虚拟机。您可以配置您的持续集成CI服务器比如 [Jenkins](https://jenkins.io/index.html))来调用 Aminator 将服务打包为一个 EC2 AMI。[Packer](https://www.packer.io/) 自动化虚拟机镜像创建的另一个选择。与 Aminator 不同,它支持各种虚拟化技术,包括 EC2、DigitalOcean、VirtualBox 和 VMware。 你可以使用多种工具来构建自己的虚拟机。你可以配置你的持续集成CI服务器比如 [Jenkins](https://jenkins.io/index.html))来调用 Aminator 将服务打包为一个 EC2 AMI。另一个选择是使用 [Packer](https://www.packer.io/) 自动化创建虚拟机镜像。与 Aminator 不同,它支持各种虚拟化技术,包括 EC2、DigitalOcean、VirtualBox 和 VMware。
[Boxfuse](https://boxfuse.com/) 公司有一种非常棒的方式用来构建虚拟机镜像其克服了我将在下面描述的虚拟机的缺点。Boxfuse 将您的 Java 应用程序打包成一个最小化的 VM 镜像。这些镜像可被快速构建、快速启动且更加安全,因为它们暴露了一个有限的攻击面 [Boxfuse](https://boxfuse.com/) 公司有一种非常好的方式用来构建虚拟机镜像其克服了我将在下面提到的虚拟机的缺点。Boxfuse 将 Java 应用打包成一个最小化的 VM 镜像。这些镜像可被快速构建、快速启动且更加安全,因为它们只暴露一个有限的攻击范围
[CloudNative](https://cloudnative.io/) 公司拥有 Bakery这是一种用于创建 EC2 AMI 的 SaaS 产品。您可以配置您的 CI 服务器,在微服务通过测试后调用 Bakery。之后 Bakery 将您的服务打包成一个 AMI。使用一个如 Bakery 的 SaaS 产品意味着您不必浪费宝贵的时间来设置 AMI 创建基础架构。 [CloudNative](https://cloudnative.io/) 公司拥有 Bakery这是一个用于创建 EC2 AMI 的 SaaS 产品。你可以配置你的 CI 服务器,在微服务通过测试后调用 Bakery。之后 Bakery 将你的服务打包成一个 AMI。使用一个如 Bakery 的 SaaS 产品意味着你不必浪费宝贵的时间来设置 AMI 创建基础架构。
每个虚拟机一个服务实例模式有许多优点。VM 的主要优点是每个服务实例运行是完全隔离的。它有固定数量的 CPU 和内存,且不能从其他服务窃取资源。 每个虚拟机一个服务实例模式有许多优点。VM 的主要优点是每个服务实例运行是完全隔离的。它有固定数量的 CPU 和内存,且不能从其他服务窃取资源。
将微服务部署为虚拟机的另一个优点是可以利用成熟的云基础架构。如 AWS 之类的云提供了很多有用的功能,如负载平衡和自动扩缩。 将微服务部署为虚拟机的另一个优点是可以利用成熟的云基础架构。如 AWS 之类的云提供了很多有用的功能,如负载平衡和自动扩缩。
将服务部署为虚拟机的另一个好处是它封装了服务的实现技术。一旦服务被打包成一个虚拟机它就成为一个黑匣子。VM 的管理 API 成为部署服务的 API。部署变得更加简单、可靠。 将服务部署为虚拟机的另一个好处是它封装了服务的实现技术。一旦服务被打包成一个虚拟机它就成为一个黑匣子。VM 的管理 API 成为部署服务的 API。部署变得更加简单、可靠。
然而,每个虚拟机一个服务实例模式也有一些缺点。一个缺点是资源利用率较低。每个服务实例都有一整个 VM 开销,包括操作系统。此外,在一个典型的公共 IaaS 中VM 有固定大小,并且 VM 可能未被充分利用。 然而,每个虚拟机一个服务实例模式也有一些缺点。一个缺点是资源利用率较低。每个服务实例都有一整个 VM 开销,包括操作系统部分。此外,在一个典型的公共 IaaS 中VM 有固定大小,并且可能未被充分利用。
此外,公共 IaaS 中的 VM 通常是收费的,无论它们是处于繁忙还是空闲。如 AWS 之类的 IaaS 虽然提供了自动扩缩功能,但[很难快速响应需求变化](http://techblog.netflix.com/2013/11/scryer-netflixs-predictive-auto-scaling.html)。因此,经常需要过度配置 VM从而增加部署成本。 此外,公共 IaaS 中的 VM 通常是收费的,无论它们是处于繁忙还是空闲状态。如 AWS 之类的 IaaS 虽然提供了自动扩缩功能,但[很难快速响应需求变化](http://techblog.netflix.com/2013/11/scryer-netflixs-predictive-auto-scaling.html)。因此,经常需要过度配置 VM从而增加部署成本。
这种方法的另一缺点是部署新版本的服务时通常很慢。由于大小原因,通常 VM 镜像构建很慢。此外VM 实例化也很慢,同样是因为它们的大小。而且,操作系统也需要一些时间来启动。但请注意,这并不普遍,因为已经存在由 Boxfuse 构建的轻量级 VM。 这种方法的另一缺点是部署新版本的服务时很慢。由于大小原因,通常 VM 镜像构建很慢。此外VM 实例化也很慢,同样是因为大小原因。而且,操作系统也需要一些时间来启动。但请注意,这并不常见,因为已经存在由 Boxfuse 构建的轻量级 VM。
每个虚拟机一个服务实例模式的另一个缺点是通常您(或组织中的其他人)要对很多未划分的重担负责。除非您使用 Boxfuse 这样的工具来处理构建和管理虚拟机的开销,否则这将是您的责任。这个必要而又耗时的活动会分散您的核心业务。 每个虚拟机一个服务实例模式的另一个缺点是你(或组织中的其他人)要对很多未划分的重担负责。除非你使用 Boxfuse 这类的工具来处理构建和管理虚拟机的开销,否则这将是你的责任。这个必要而又耗时的活动会分散你的核心业务。
接下来让我们看看另一种部署更轻量级微服务的替代方式,它也有许多与虚拟机一样的优势。 接下来让我们看看另一种更轻量级的微服务部署方式,它也有许多与虚拟机一样的优势。
<a id="service-instance-per-container-pattern"></a> <a id="service-instance-per-container-pattern"></a>
### 6.3.2、每个容器一个服务实例模式 ### 6.3.2、每个容器一个服务实例模式
当您使用[每个容器一个服务实例模式](http://microservices.io/patterns/deployment/service-per-container.html)Service Instance per Container模式时每个服务实例都在其自己的容器中运行。容器是一个[操作系统级虚拟化机制](https://en.wikipedia.org/wiki/Operating-system-level_virtualization)。一个容器是由一个或多个运行在沙箱中的进程组成。从进程的角度来看,它们有自己的端口命名空间和根文件系统。您可以限制容器的内存和 CPU 资源。一些容器实现也具有 I/O 速率限制。容器技术的相关例子有 [Docker](https://www.docker.com/) 和 [Solaris Zones](https://en.wikipedia.org/wiki/Solaris_Containers)。
当你使用[每个容器一个服务实例模式](http://microservices.io/patterns/deployment/service-per-container.html)Service Instance per Container模式时每个服务实例都在自己的容器中运行。容器是一个[操作系统级虚拟化机制](https://en.wikipedia.org/wiki/Operating-system-level_virtualization)。一个容器是由一个或多个运行在沙箱中的进程组成。从进程的角度来看,它们有自己的端口命名空间和根文件系统。你可以限制容器的内存和 CPU 资源。一些容器实现也有 I/O 速率限制。容器技术的相关例子有 [Docker](https://www.docker.com/) 和 [Solaris Zones](https://en.wikipedia.org/wiki/Solaris_Containers)。
图 6-3 展示了该模式的结构: 图 6-3 展示了该模式的结构:
![图 6-3、服务可以各自运行在自的容器中](resources/6-3.png) ![图 6-3、服务可以运行在自的容器中](resources/6-3.png)
要使用此模式,请将的服务打包成一个容器镜像。容器镜像是由运行服务所需的应用程序和库组成的文件系统镜像。一些容器镜像由完整的 Linux 根文件系统组成。其它的则更加轻便。例如,要部署一个 Java 服务,您可以构建一个包含了 Java 运行时的容器镜像,或许也包含一个 Apache Tomcat 服务器和编译好的 Java 应用程序 要使用此模式,请将的服务打包成一个容器镜像。容器镜像是由运行服务所需的应用和库组成的文件系统镜像。一些容器镜像由完整的 Linux 根文件系统组成。其它的则更加轻便。例如,要部署一个 Java 服务,你可以构建一个包含了 Java 运行时的容器镜像,有时也可能包含一个 Apache Tomcat 服务器和编译好的 Java 应用。
将服务打包成一个容器镜像后,您将启动一个或多个容器。通常在每个物理或虚拟主机上运行多个容器。您可以使用集群管理工具(如 [Kubernetes](https://kubernetes.io/) 或 [Marathon](https://github.com/mesosphere/marathon))来管理容器。集群管理工具将主机视为一个资源池。它根据容器所需的资源和每个主机上可用的资源来决定每个容器放置的位置。 将服务打包成一个容器镜像后,你将启动一个或多个容器。通常在每台(个)物理或虚拟主机上运行多个容器。你可以使用集群管理工具(如 [Kubernetes](https://kubernetes.io/) 或 [Marathon](https://github.com/mesosphere/marathon))来管理容器。集群管理工具将主机视为一个资源池。它根据容器所需的资源和每个主机上可用的资源来决定每个容器放置的位置。
每个容器一个服务实例模式模式有优点和缺点。容器的优点与虚拟机的类似。它们将服务实例彼此隔离。您可以轻松地监控每个容器所消耗的资源。此外,与 VM 一样,容器封装了服务的实现技术。容器管理 API 作为管理您的服务的 API。 每个容器一个服务实例模式模式有优点也有缺点。容器的优点与虚拟机的类似。它们将服务实例彼此隔离。你可以轻松地监控每个容器所消耗的资源。此外,与 VM 一样,容器封装了服务的实现技术。可将容器管理 API 作为服务管理 API。
然而,与虚拟机不同,容器是轻量级技术。容器镜像通常可以非常快速地构建。例如,在我的笔记本电脑上,将一个 [Spring Boot](http://projects.spring.io/spring-boot/) 应用程序打包成一个 Docker 容器只需要 5 秒钟的时间。容器也可以很快地启动,因为没有繁琐的操作系统引导机制。当一个容器启动时,它所运行的就是服务。 然而,与虚拟机不同,容器是轻量级技术。容器镜像可以非常快速地构建。例如,在我的笔记本电脑上,将一个 [Spring Boot](http://projects.spring.io/spring-boot/) 应用打包成一个 Docker 容器只需要 5 秒钟的时间。容器也可以很快地启动,因为没有繁琐的操作系统引导机制。当一个容器启动时,它所运行的就是服务。
使用容器有一些缺点。虽然容器基础架构正在快速发展走向成熟,但它并不像虚拟机的基础架构那么成熟。此外,容器不像 VM 那样安全,因为容器彼此共享主机的 OS 内核。 使用容器有一些缺点。虽然容器基础架构正在快速发展走向成熟,但它并不像虚拟机的基础架构那么成熟。此外,容器不像 VM 那样安全,因为容器彼此共享主机的 OS 内核。
容器的另一个缺点是您需要负责未划分的容器镜像管理的负担。此外,除非您使用了托管容器解决方案[如 [Google Container Engine](https://cloud.google.com/container-engine/) 或 [Amazon EC2 Container Service](https://cloud.google.com/container-engine/)ECS否则必须自己管理容器基础设施,可能还有运行容器的 VM 基础架构。 容器的另一个缺点是你需要负责管理这些庞大且无法区分的容器镜像。此外,除非你使用了托管容器解决方案[如 [Google Container Engine](https://cloud.google.com/container-engine/) 或 [Amazon EC2 Container Service](https://cloud.google.com/container-engine/)ECS否则必须自己管理容器基础设施,可能还有运行容器的 VM 基础架构。
此外,容器通常部署在一个按单个 VM 收费的基础设施上。因此,如之前所述,可能会产生超额配置 VM 的额外成本,以处理负载峰值 此外,容器通常部署在一个按单个 VM 收费的基础设施上。因此,如之前所述,当有处理负载峰值时,可能会产生超额配置 VM 的额外成本。
有趣的是,容器和 VM 之间的区别可能会有些模糊。如之前所述Boxfuse VM 可以很快地构建和启动。[Clear Containers](https://clearlinux.org/features/clear-containers) 项目旨在创建轻量级虚拟机。[Unikernels](https://en.wikipedia.org/wiki/Unikernel) 也正在蓬勃发展。Docker 公司于 2016 年初收购了 Unikernel 系统。 有趣的是,容器和 VM 之间的区别可能会有些模糊。如之前所述Boxfuse VM 可以很快地构建和启动。[Clear Containers](https://clearlinux.org/features/clear-containers) 项目旨在创建轻量级分的虚拟机。[Unikernels](https://en.wikipedia.org/wiki/Unikernel) 也正在蓬勃发展。Docker 公司于 2016 年初收购了 Unikernel 系统。
还有一个日益流行的 server-less无服务器部署概念这是一种避免了“在容器中还是在虚拟机中部署服务”问题的方法。接下来我们来看看 还有一个日益流行的 server-less无服务器部署概念它避免了「在容器中还是在虚拟机中部署服务」这一问题
<a id="serverless-deployment"></a> <a id="serverless-deployment"></a>
## 6.4、Serverless 部署 ## 6.4、Serverless 部署
[AWS Lambda](https://aws.amazon.com/lambda/) 就是一个 serverless 部署技术示例。它支持 Java、Node.js 和 Python 服务。要部署微服务,请将其打包成 ZIP 文件并将上传到 AWS Lambda。您还要提供元数据其中包括了被调用来处理请求又称为事件的函数的名称。AWS Lambda 自动运行足够的微服务服务实例来处理请求。您只需根据每个请求所用时间和内存消耗来付费。当然,问题往往出现在细节上,您很快注意到了 AWS Lambda 的局限性。但是,作为开发人员的您或组织中的任何人都无需担心服务器、虚拟机或容器的任何方面 ,这非常有吸引力,足以令人难以置信。
[AWS Lambda](https://aws.amazon.com/lambda/) 就是一个 serverless 部署技术示例。它支持 Java、Node.js 和 Python 服务。要部署微服务时,需将服务打包成 ZIP 文件并将上传到 AWS Lambda。你还要提供元数据其中包括了被调用用来处理请求又称为事件的函数的名称。AWS Lambda 会自动运行足够的微服务服务实例来处理请求。你只需根据每个请求所用时间和内存消耗来付费。当然,问题往往出现在细节上,你很快注意到了 AWS Lambda 的局限性。但作为开发人员的你或组织中的任何人都无需担心服务器、虚拟机或容器方面的任何问题 ,这非常有吸引力,足以令人难以置信。
Lambda 函数是无状态服务。它通常通过调用 AWS 服务来处理请求。例如,当图片上传到 S3 存储桶时 Lambda 函数将被调用,该函数可插入一条记录到 DynamoDB 图片表中,并将消息发布到 Kinesis 流以触发图片处理。Lambda 函数还可以调用第三方 Web 服务。 Lambda 函数是无状态服务。它通常通过调用 AWS 服务来处理请求。例如,当图片上传到 S3 存储桶时 Lambda 函数将被调用,该函数可插入一条记录到 DynamoDB 图片表中,并将消息发布到 Kinesis 流以触发图片处理。Lambda 函数还可以调用第三方 Web 服务。
@ -113,17 +120,18 @@ Lambda 函数是无状态服务。它通常通过调用 AWS 服务来处理请
- 直接使用 Web 服务请求 - 直接使用 Web 服务请求
- 自动响应一个 AWS 服务(如 S3、DynamoDB、Kinesis 或 Simple Email Service生成的事件 - 自动响应一个 AWS 服务(如 S3、DynamoDB、Kinesis 或 Simple Email Service生成的事件
- 通过 AWS API 网关自动处理来自应用程序客户端的 HTTP 请求 - 通过 AWS API 网关自动处理来自应用客户端的 HTTP 请求
- 按照一个类似 cron 的时间表,定期执行 - 按照一个类似 cron 的时间表,定期执行
正如您所见AWS Lambda 是一个便捷的微服务部署方式。基于请求的定价意味着您只需为服务实际执行的工作付费。另外,由于您不需要对 IT 基础架构负任何责任,因此可以专注于开发应用程序 正如你所见AWS Lambda 是一个便捷的微服务部署方式。基于请求的定价意味着你只需为服务实际执行的工作付费。另外,由于你不需要对 IT 基础架构负任何责任,因此可以专注于开发应用。
然而其也存在一些明显的局限性。Lambda 函数不适用于部署长时间运行的服务,例如消耗第三方消息代理消息的服务。请求必须在 300 秒内完成。服务必须是无状态的因为理论上AWS Lambda 可能为每个请求运行一个单独的实例。他们必须使用受支持的语言来编写。服务启动速度也必须快,否则,他们可能会因超时而终止。 然而其也存在一些明显的局限性。Lambda 函数不适用于部署长时间运行的服务,例如消耗第三方消息代理消息的服务。请求必须在 300 秒内完成。服务必须是无状态的因为理论上AWS Lambda 可能为每个请求运行一个单独的实例。ta们必须使用受支持的语言来编写。服务启动速度也必须快否则们可能会因超时而终止。
<a id="summary"></a> <a id="summary"></a>
## 6.5、总结 ## 6.5、总结
部署微服务应用程序充满着挑战。您可能有数个甚至数百个使用了各种语言和框架编写的服务。每个应用程序都是一个迷你应用程序,有自己特定的部署、资源、扩展和监视需求。有几个微服务部署模式,包括每个虚拟机一个服务实例和每个容器一个服务实例模式。部署微服务的另一个有趣的选择是 AWS Lambda一种 serverless 方式。在本书的下一章也是最后一章中,我们将介绍如何将单体应用程序迁移到微服务架构。
部署微服务应用充满着挑战。你可能有数个甚至数百个使用了各种语言和框架编写的服务。每个应用都是一个迷你应用,有自己特定的部署、资源、扩展和监控需求。有几个微服务部署模式,包括每个虚拟机一个服务实例和每个容器一个服务实例模式。部署微服务的另一个有趣的选择是 AWS Lambda一种 serverless 方式。在本书的下一章也是最后一章中,我们将介绍如何将单体应用迁移到微服务架构。
<a id="microservices-in-action"></a> <a id="microservices-in-action"></a>
@ -131,10 +139,10 @@ Lambda 函数是无状态服务。它通常通过调用 AWS 服务来处理请
by Floyd Smith by Floyd Smith
NGINX 对于各种类型的部署具有许多优势 — 无论是单体应用程序、微服务应用程序还是混合应用程序(将在下一章介绍)。使用 NGINX您可以智能抽取不同的部署环境出来并整合入 NGINX。如果您使用针对不同部署环境的工具,则有许多应用程序功能将以不同的方式工作,但如果使用 NGINX那么在所有环境中都可以使用相同的方式进行工作。 NGINX 对于各种类型的部署有许多优势 —— 无论是单体应用、微服务应用还是混合应用(将在下一章介绍)。使用 NGINX你可以智能抽取不同的部署环境出来并整合入 NGINX。如果你使用针对不同部署环境的工具,则有许多应用功能将以不同的方式工作,但如果使用 NGINX那么在所有环境中都可以使用相同的方式进行工作。
这一特性也为 NGINX 和 NGINX Plus 带来了第二个优势:通过在多个部署环境中同时运行应用程序来扩展应用程序的能力。假设您拥有和管理着的本地服务器,但是您的应用程序使用情况正在增长,并且预计将超出这些服务器可以处理的峰值。如果你已经使用了 NGINX您就有了一个强大的选择扩展到云端 — 例如,[扩展到 AWS 上](https://www.nginx.com/products/nginx-plus-aws/),而不是购买、配置和保持额外的服务器来为了以防万一。也就是说,当的本地服务器上的流量达到容量限制时,可根据需要在云中启动其他微服务实例来处理。 这一特性也为 NGINX 和 NGINX Plus 带来了第二个优势:通过在多个部署环境中同时运行应用来扩展应用的能力。假设你拥有和管理着的本地服务器,但是你的应用使用量正在增长,并预计将超出这些服务器可以处理的峰值。如果你已经使用了 NGINX你就有了一个强大的选择扩展到云端 —— 例如,[扩展到 AWS 上](https://www.nginx.com/products/nginx-plus-aws/),而不是购买、配置和保持额外的服务器来为了以防万一。也就是说,当的本地服务器上的流量达到容量限制时,可根据需要在云中启动其他微服务实例来处理。
这只是因使用 NGINX 变得更加灵活的一个例子。维护单独的测试和部署环境、切换环境的基础设施、以及管理各种环境中的应用程序组合都变得更加现实和可实现。 这只是因使用 NGINX 变得更加灵活的一个例子。
[NGINX 微服务参考架构](https://www.nginx.com/blog/introducing-the-nginx-microservices-reference-architecture/)被明确设计为支持这种灵活部署,其假设在开发和部署期间使用容器技术。如果您还没尝试可以考虑转移到容器、NGINX 或 NGINX Plus以轻松地转移到微型服务以及使您的应用程序、开发和部署灵活性以及人员更具前瞻性。 [NGINX 微服务参考架构](https://www.nginx.com/blog/introducing-the-nginx-microservices-reference-architecture/)被明确设计为支持这种灵活部署方式,其假设在开发和部署期间使用容器技术。如果你还没尝试可以考虑转移到容器、NGINX 或 NGINX Plus以轻松地转移到微服务使你的应用、开发和部署灵活性以及人员更具前瞻性。

View File

@ -1,37 +1,40 @@
# 7、重构单体应用为微服务 # 7、重构单体应用为微服务
本书主要介绍如何使用微服务构建应用程序,这是本书的第七章,也是最后一章。[第一章](1-introduction-to-microservices.md)介绍了微服务架构模式,讨论了使用微服务的优点与缺点。随后的章节讨论了微服务架构的方方面面:[使用 API ​​网关](2-using-an-api-gateway.md)、[进程间通信](3-inter-process-communication.md)、[服务发现](4-service-discovery.md)、[事件驱动数据管理](5-event-driven-data-management-for-microservices.md)和[部署微服务](6-choosing-deployment-strategy.md)。在本章中,我们将介绍单体应用迁移到微服务的策略。
我希望这本电子书能够让您对微服务架构、其优点和缺点以及何时使用它有很好的了解。微服务架构也许很适合您的组织 本书主要介绍如何使用微服务构建应用,这是本书的第七章,也是最后一章。[第一章](1-introduction-to-microservices.md)介绍了微服务架构模式,讨论了使用微服务的优点与缺点。随后的章节讨论了微服务架构的方方面面:[使用 API ​​网关](2-using-an-api-gateway.md)、[进程间通信](3-inter-process-communication.md)、[服务发现](4-service-discovery.md)、[事件驱动数据管理](5-event-driven-data-management-for-microservices.md)和[部署微服务](6-choosing-deployment-strategy.md)。在本章中,我们将介绍单体应用迁移到微服务的策略
您正工作于大型复杂的单体应用程序上,这是相当不错的机会。然而,您开发和部署应用程序的日常经历是缓慢而痛苦的。微服务似乎是一个遥不可及的天堂。幸运的是,有一些策略可以用来逃离单体应用的地狱。在本文中,我将描述如何将单体应用程序逐渐重构为一组微服务。 我希望这本电子书能够让你对微服务的架构、其优点和缺点以及何时使用它有更好的了解。微服务架构也许很适合你的组织。
你正忙于大型复杂的单体应用上,这是相当不错的机会。然而,你开发和部署应用的日常操作是缓慢而痛苦的。微服务似乎是一个遥不可及的天堂。幸运的是,有一些策略可以帮你逃离单体应用的地狱。在本文中,我将描述如何将单体应用逐渐重构为一组微服务。
<a id="overview-of-refactoring-to-microservices"></a> <a id="overview-of-refactoring-to-microservices"></a>
## 7.1、微服务重构概述 ## 7.1、微服务重构概述
单体应用程序转换为微服务的过程是[应用程序现代化](https://en.wikipedia.org/wiki/Software_modernization)的一种形式。这是几十年来开发人员一直在做的事情。因此,在将应用程序重构为微服务时,有一些想法是可以重用的。
一个不要使用的策略是“大爆炸”重写。就是您将所有的开发工作都集中在从头开始构建新的基于微服务的应用程序。虽然这听起来很吸引人,但非常危险,有可能会失败。[据 Martin Fowler 讲到](http://www.randyshoup.com/evolutionary-architecture):“大爆炸重写的唯一保证就是大爆炸!”("the only thing a Big Bang rewrite guarantees is a Big Bang!" 单体应用转换为微服务的过程是[应用现代化](https://en.wikipedia.org/wiki/Software_modernization)的一种形式。这是几十年来开发人员一直在做的事情。因此,在将应用重构为微服务时,有一些想法是可以重用的
您应该逐步重构单体应用程序,而不是通过大爆炸重写。您可以逐渐添加新功能,并以微服务的形式创建现有功能的扩展 — 以互补的形式修改单体应用,并且一同运行微服务和修改后的单体应用。随着时间推移,单体应用程序实现的功能量会缩小,直到它完全消失或变成另一个微服务。这种策略类似于在 70公里/小时的高速公路上驾驶一辆汽车,很具挑战性,但比尝试大爆炸改写的风险要小得多。 一个不要使用的策略是「爆炸式」重写。就是你将所有的开发工作都集中在从头开始构建新的基于微服务的应用。虽然这听起来很吸引人,但非常危险,有可能会失败。[据 Martin Fowler 讲到](http://www.randyshoup.com/evolutionary-architecture):「爆炸式重写的唯一保证就是大爆炸!」("the only thing a Big Bang rewrite guarantees is a Big Bang!")。
你应该逐步重构单体应用,而不是通过爆炸式重写来实现。你可以逐渐添加新功能,并以微服务的形式创建现有功能的扩展 —— 以互补的形式修改单体应用,并且与单体应用共同运行。随着时间推移,单体应用实现的功能量会慢慢减少,直到它完全消失或变成另一个微服务。这种策略类似于在 70 公里/小时的高速公路上维修一辆汽车,很有挑战性,但至少比尝试爆炸式重写的风险要小得多。
![葡萄树](resources/7.png) ![葡萄树](resources/7.png)
Martin Fowler 将这种应用现代化策略称为[杀手应用](http://www.martinfowler.com/bliki/StranglerApplication.html)Strangler Application。这个名字来自发现于热带雨林中的葡萄树也称为绞杀榕。一棵葡萄树生长在一棵树上以获取森林冠层之上的阳光。有时树死了留下一树形的腾。应用现代化也遵循相同的模式。我们将构建一个新应用程序包括了围绕遗留应用的微服务(它慢慢缩小或者最终消亡 Martin Fowler 将这种应用现代化策略称为[绞杀者应用](http://www.martinfowler.com/bliki/StranglerApplication.html)Strangler Application。这个名字来自发现于热带雨林中的葡萄树也称为绞杀榕。一棵葡萄树生长在一棵树上以获取森林冠层之上的阳光。有时树死了留下一树形的腾。应用现代化也遵循相同的模式。我们将围绕遗留应用来构建一个由微服务组成的新应用,遗留应用将慢慢缩小最终消亡。
让我们来看看能做到这点的不同策略。 让我们来看看能做到这点的策略。
<a id="strategy-1-Stop-digging"></a> <a id="strategy-1-Stop-digging"></a>
## 7.2、策略一:停止挖掘 ## 7.2、策略一:停止挖掘
[洞穴定律](https://en.wikipedia.org/wiki/Law_of_holes)说到,每当您身处在一个洞穴中,您应该停止挖掘。当您的单体应用变得难以管理时,这是一个很好的建议。换句话说,您应该停止扩张,避免使单体变得更大。这意味着当您要实现新功能时,您不应该向单体添加更多的代码。相反,这一策略的主要思想是将新代码放在独立的微服务中。
[洞穴定律](https://en.wikipedia.org/wiki/Law_of_holes)讲到,当你身处在一个洞穴中时,你应该停止挖掘。当你的单体应用变得难以管理时,这是一个不错的建议。换句话说,你应该停止扩张,避免使单体变得更大。这意味着当你要实现新功能时,你就不应该向单体添加更多的代码。相反,这一策略的主要思想是将新代码放到独立的微服务中。
应用此方法后,系统架构如图 7-1 所示。 应用此方法后,系统架构如图 7-1 所示。
![图 7-1、将新功能实现为单独的服务而不是将模块添加到单体](resources/7-1.png) ![图 7-1、将新功能实现为单独的服务而不是将模块添加到单体](resources/7-1.png)
除了新服务和遗留的单体应用还有另外两个组件。第一个是请求路由它处理传入的HTTP请求类似于[第二章](2-using-an-api-gateway.md)中描述的 API 网关。路由向新服务发送与新功能相对应的请求。它将遗留的请求路由到单体应用。 除了新服务和遗留的单体应用还有另外两个组件。第一个是请求路由它处理传入的HTTP请求类似于[第二章](2-using-an-api-gateway.md)中描述的 API 网关。路由向新服务发送与新功能相对应的请求。它将遗留系统的请求路由到单体应用。
另一个组件是粘合代码,它将微服务与单体应用集成。一个服务很少孤立存在,通常需要访问单体应用的数据。位于单体应用、微服务或两者中的粘合代码负责数据集成。该微服务使用粘合代码来读取和写入单体应用数据。 另一个组件是粘合代码,它将微服务与单体应用集成。服务很少孤立存在,通常需要访问单体应用的数据。位于单体应用、微服务或两者中的粘合代码负责数据集成。该微服务使用粘合代码来读取和写入单体应用数据。
服务可以使用三种策略来访问单体应用的数据: 服务可以使用三种策略来访问单体应用的数据:
@ -39,72 +42,79 @@ Martin Fowler 将这种应用现代化策略称为[杀手应用](http://www.mart
- 直接访问单体应用的数据库 - 直接访问单体应用的数据库
- 维护自己的数据副本,与单体应用的数据库同步 - 维护自己的数据副本,与单体应用的数据库同步
粘合代码有时被称为防护层anti-corruption layer。这是因为粘合代码阻止了服务被遗留的单体应用领域模型的概念所污染这些服务拥有属于自己的新领域模型。粘合代码在两种不同的模型之间转换。防护层一词首先出现于埃里克·埃文斯Eric Evans所著的必读图书[《领域驱动设计》](http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215/ref=sr_1_1?ie=UTF8&s=books&qid=1238687848&sr=8-1)Domain Driven Design并在[白皮书](http://docs.scala-lang.org/overviews/core/futures.html)中进行了改进。开发一个防护层并不是一件简单的事情。但是,如果您想要从单体应用地狱中走出来,这是必不可少的步骤。 粘合代码有时被称为防护层anti-corruption layer。这是因为粘合代码阻止了服务被遗留的单体应用领域模型的概念所污染这些服务拥有属于自己的新领域模型。粘合代码在两种不同的模型之间转换。防护层一词最初出现在埃里克·埃文斯Eric Evans所著的必读图书[《领域驱动设计》](http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215/ref=sr_1_1?ie=UTF8&s=books&qid=1238687848&sr=8-1)Domain Driven Design并在[白皮书](http://docs.scala-lang.org/overviews/core/futures.html)中进行了改进。开发一个防护层并不是一件简单的事。但是,如果你想要从单体应用地狱中走出来,这是必不可少的步骤。
使用轻量级服务来实现新功能有几个好处。它防止单体变得更加难以管理。该服务可以独立于单体应用开发、部署和扩展。可让创建的每个新服务体验到微服务架构的优势。 使用轻量级服务来实现新功能有几个好处。它防止单体变得更加难以管理。该服务可以独立于单体应用开发、部署和扩展。可让创建的每个新服务体验到微服务架构的优势。
然而,这种方法没有解决单体应用的问题。要解决这些问题,需要分解单体应用。让我们来看看这样做的策略。 然而,这种方法没有解决单体应用的问题。要解决这些问题,需要分解单体应用。让我们来看看这样做的策略。
<a id="strategy-2-split-frontend-and-backend"></a> <a id="strategy-2-split-frontend-and-backend"></a>
## 7.3、策略二:前后端分离 ## 7.3、策略二:前后端分离
缩小单体应用的一个策略是从业务逻辑层和数据访问层拆分出表现层。一个典型的企业应用由至少三种不同类型的组件组成: 缩小单体应用的一个策略是从业务逻辑层和数据访问层拆分出表现层。一个典型的企业应用由至少三种不同类型的组件组成:
- **表现层Presentation LayerPL** - **表现层Presentation LayerPL**
处理 HTTP 请求并实现RESTAPI 或基于 HTML 的 Web UI 组件。在具有复杂用户界面的应用中,表现层通常存在大量代码。 处理 HTTP 请求并实现RESTAPI 或基于 HTML 的 Web UI 组件。在有复杂用户界面的应用中,表现层通常存在大量代码。
- **业务逻辑层Business Logic LayerBLL** - **业务逻辑层Business Logic LayerBLL**
作为应用程序核心,实现业务规则的组件。 作为应用核心,实现业务规则的组件。
- **数据访问层Data Access LayerDAL** - **数据访问层Data Access LayerDAL**
访问基础架构组件的组件,如数据库和消息代理。 数据访问基础设施组件,如数据库和消息代理。
表现逻辑部分与业务和数据访问逻辑部分之间通常有一个清晰的界限。业务层有由一个或多个门面组成的粗粒度 API其封装了业务逻辑组件。这个 API 是一个天然的边界,您可以沿着该边界将单体应用拆分成两个较小的应用程序。一个应用程序包含表现层。另一个应用程序包含业务和数据访问逻辑。分割后,表现逻辑应用程序对业务逻辑应用程序进行远程调用。 表现逻辑部分与业务和数据访问逻辑部分之间通常有一个清晰的界限。业务层有由一个或多个门面组成的粗粒度 API其封装了业务逻辑组件。这个 API 是一个天然边界,你可以沿着该边界将单体应用拆分成两个较小的应用。一个应用包含表现层。另一个应用包含业务和数据访问逻辑。分割后,表现逻辑应用远程调用业务逻辑应用。
重构之前和之后的架构如图 7-2 所示。 重构之前和之后的架构如图 7-2 所示。
![图 7-2、重构现有的应用程序](resources/7-2.png) ![图 7-2、重构现有的应用](resources/7-2.png)
以这种方式拆分单体应用有两个主要优点。它使能够独立于彼此开发、部署和扩展这两个应用。特别是它允许表现层开发人员在用户界面上快速迭代,并且可以轻松执行 A/B 测试。这种方法的另一个优点是它暴露了可以被微服务调用的远程 API。 以这种方式拆分单体应用有两个主要优点。它使能够独立于彼此开发、部署和扩展这两个应用。特别是它允许表现层开发人员在用户界面上快速迭代,并且可以轻松执行 A/B 测试。这种方法的另一个优点是它暴露了可以被微服务调用的远程 API。
然而,这一策略只是一个局部解决方案。两个应用程序中的一个或两个很可能在将来膨胀成一个无法管理的单体应用。您需要使用第三种策略来继续消减单体应用。 然而,这一策略只是一个局部解决方案。两个应用中的一个或两个很可能在将来会膨胀成一个无法管理的单体应用。你需要使用第三种策略来继续缩小单体应用。
<a id="strategy-3-extract-services"></a> <a id="strategy-3-extract-services"></a>
## 7.4、策略三:提取服务 ## 7.4、策略三:提取服务
第三个重构策略是将庞大的现有模块转变为独立的微服务。每次提取一个模块并将其转换成微服务时,单体就会缩小。一旦您转换了足够的模块,单体应用将不再是一个问题。或者它完全消失,或者变得小到可以被当做一个服务看待。
第三个重构策略是将庞大的现有模块转变为独立的微服务。每次提取一个模块并将其转换成微服务时,单体就会缩小。一旦你转换了足够多的模块,单体应用将不再是问题。它将完全消失,或者变得小到可以被当做一个服务看待。
<a id="prioritizing-which-modules-to-convert-into-services"></a> <a id="prioritizing-which-modules-to-convert-into-services"></a>
### 7.4.1、优先将哪些模块转换为微服务 ### 7.4.1、优先将哪些模块转换为微服务
一个庞大而复杂的单体应用由几十个或几百个模块组成,所有模块都是提取的候选项。弄清楚要先转换哪些模块往往存在一定的挑战。一个好的方法是从容易提取的几个模块开始。这将给你的微服务开发带来好的体验,特别是在提取过程方面。之后,您应该提取那些能给您最大收益的模块。
将模块转换为服务通常是耗时的。按照您将获得的收益对模块进行排列。提取频繁更改的模块通常是有益的。一旦将模块转换为服务,您就可以独立于单体应用开发和部署,这将加快开发工作 一个庞大而复杂的单体应用由几十个或几百个模块组成,所有模块都是待提取部分。弄清楚要先转换哪些模块往往是件令人头疼的事。一个好的方法是从容易提取的几个模块开始。这样可以给你的微服务开发带较好的体验,特别是在提取方面。之后,你应该提取那些能给你最大收益的模块
提取单体应用中相对来说耗资源的模块也是有益的。例如,将有一个有内存数据库的模块转换为服务是很有用的,这样可以部署在具有大量内存的主机上,无论是裸机服务器、虚拟机还是云服务器。同样,提取实现了大量复杂算法的模块也是值得的,因为该服务可以部署在具有大量 CPU 的主机上。通过将具有特定资源需求的模块转换为服务,您可以使应用程序更加容易、廉价地扩展 将模块转换为服务通常是耗时的,可按照你将获得的收益对模块进行排列。优先考虑提取频繁更改的模块。一旦将模块转换为服务,你就可以独立于单体应用开发和部署,加快开发工作
当找到要提取的模块时,寻找现有的粗粒度边界(又称为接缝)是有用的。它们使模块转成服务更容易。有关这种边界的一个例子是一个仅通过异步消息与应用程序的其他部分进行通信的模块。将该模块转变为微服务相对比较廉价和简单。 也有可以优先考虑提取单体应用中相对耗资源的模块。例如,将有一个使用到内存数据库的模块转换为服务,这样可以部署到有大量内存的主机上。同样,提取实现了大量复杂算法的模块也是值得的,因为该服务可以部署到有大量 CPU 的主机上。通过将有特定资源需求的模块转换为服务,你可以使应用更加容易、廉价地扩展。
当找到要提取的模块时,寻找现有的粗粒度边界(又称为接缝)。它们使模块转成服务更加容易。有关这种边界的一个例子是一个仅通过异步消息与应用的其他部分进行通信的模块。将该模块转变为微服务相对比较廉价和简单。
<a id="how-to-extract-a-module"></a> <a id="how-to-extract-a-module"></a>
## 7.4.2、如何提取模块 ## 7.4.2、如何提取模块
提取模块的第一步是在模块和单体应用之间定义一个粗粒度的接口。它很可能是一个双向 API因为单体应用需要服务拥有的数据反之亦然。由于该模块和应用程序的其余模块之间存在着复杂的依赖关系和细粒度的交互模式因此实现这样的 API 通常存在挑战。由于领域模型类之间的众多关联,使用[领域模型模式](http://martinfowler.com/eaaCatalog/domainModel.html)实现的业务逻辑的重构尤其具有挑战性。您通常需要进行重大的代码更改才能打破这些依赖。图 7-3 展示了重构。
提取模块的第一步,在模块和单体应用之间定义一个粗粒度的接口。它可能是一个双向 API因为单体应用需要服务的数据反之亦然。由于该模块和应用的其它模块之间存在着复杂的依赖关系和细粒度的交互模式因此实现这样的 API 存在一定的难度。领域模型类之间存在众多关联,重构使用[领域模型模式](http://martinfowler.com/eaaCatalog/domainModel.html)实现的业务逻辑更加困难。你需要进行大量的代码更改才能打破这些依赖。图 7-3 展示了重构。
![图7-3、单体模块可转换为微服务](resources/7-3.png) ![图7-3、单体模块可转换为微服务](resources/7-3.png)
一旦实现了粗粒度的接口,您就可以将模块变成独立的服务。要做到这点,您必须编写代码以使单体应用和服务通过使用进程间通信IPC机制的 API 进行通信。图 7-3 显示了重构前、重构中和重构后的架构。 一旦实现了粗粒度的接口,你就可以将模块变成独立的服务。要做到这点,你必须编写代码使单体应用和服务可通过进程间通信IPC机制的 API 进行通信。图 7-3 显示了重构前、重构中和重构后的架构。
在此例中,模块 Z 是要提取的候选模块。它被模块 X 调用,并且它调用了模块 Y。第一个重构步骤是定义一对粗粒度的 API。第一个接口是一个使用模块 X 来调用模块 Z 的入站接口。第二个接口是一个使用模块 Z 调用模块 Y 的出站接口。 在此例中,模块 Z 是要提取的候选模块。它被模块 X 调用,并且它调用了模块 Y。第一个重构步骤是定义一对粗粒度的 API。第一个接口是一个使用模块 X 来调用模块 Z 的入站接口。第二个接口是一个使用模块 Z 调用模块 Y 的出站接口。
第二个重构步骤是将模块转换为一个独立服务。入站和出站接口使用 IPC 机制的代码来实现。您很可能需要把 Module Z 与 [Microservice Chassis](http://microservices.io/patterns/microservice-chassis.html) 框架相结合来构建服务,该框架负责处理诸如服务发现之类的横切点。 第二个重构步骤是将模块转换为一个独立服务。入站和出站接口使用 IPC 机制的代码来实现。你很可能需要将 Module Z 与 [微服务框架](http://microservices.io/patterns/microservice-chassis.html) 框架相结合来构建服务,该框架负责处理诸如服务发现之类的横切点。
一旦您提取了一个模块,您就可以独立于单体应用和任何其他服务开发、部署和扩展服务。您甚至可以从头开始重写服务。在这种情况下,整合服务与单体应用的 API 代码成为在两个领域模型之间转换的防护层。每次提取服务时,您都会朝微服务方向迈近一步。随着时间的推移,单体将缩小,您将拥有越来越多的微服务。 一旦你提取了一个模块,你就可以独立于单体应用和其他服务进行开发、部署和扩展服务。你甚至可以从头开始重写服务。在这种情况下,整合服务与单体应用的 API 代码成为在两个领域模型之间转换的防护层。每次提取服务时,你都会朝微服务的方向迈近一步。随着时间的推移,单体将缩小,你将拥有越来越多的微服务。
<a id="summary"></a> <a id="summary"></a>
## 7.5、总结 ## 7.5、总结
将现有应用程序迁移到微服务的过程是应用程序现代化的一种形式。您不应该从头开始重写您的应用来迁移到微服务。相反,您应该将应用程序逐渐重构为一组微服务。可以使用这三种策略:将新功能实现为微服务;从业务组件和数据访问组件中分离出表现组件;将单体中的现有模块转换为服务。随着时间推移,微服务的数量将会增长,您的开发团队的灵活性和速度也同样会增加。
将现有应用迁移到微服务的过程是应用现代化的一种形式。你不应该从头开始重写你的应用来迁移到微服务。相反,你应该将应用逐渐重构为一组微服务。可以使用这三种策略:将新功能实现为微服务;从业务组件和数据访问组件中分离出表现组件;将单体中的现有模块转换为服务。随着重构工作不断进行,微服务的数量将会增长,开发团队的灵活性和速度也同样会得到提升。
<a id="microservices-in-action"></a> <a id="microservices-in-action"></a>
@ -112,18 +122,20 @@ Martin Fowler 将这种应用现代化策略称为[杀手应用](http://www.mart
by Floyd Smith by Floyd Smith
如本章所述,将单体转换为微服务可能是一个缓慢而具有挑战性的过程,但这同样具有许多好处。使用 NGINX您可以在实际开始转换过程之前获得微服务器的一些优势。 如本章所述,将单体转换为微服务可能是一个缓慢而困难的过程,但这同样有许多好处。使用 NGINX你可以在实际开始转换过程之前获得微服务器的部分优势。
您可以通过将 NGINX 放在您现有的单体应用之前,以节省迁移微服务所花费的大量时间。以下简要说明与微服务关的好处: 你可以通过将 NGINX 放在你现有的单体应用之前,以节省迁移微服务所花费的大量时间。以下简要说明与微服务关的好处:
- **更好地支持微服务** - **更好地支持微服务**
如第五章尾栏所述NGINX 和 [NGINX Plus](https://www.nginx.com/products/) 具有利于开发基于微服务的应用的功能。当您开始重新设计单体应用时,由于 NGINX 的功能,您的微服务将执行得更好、更易于管理。 如第五章尾栏所述NGINX 和 [NGINX Plus](https://www.nginx.com/products/) 有利于开发基于微服务的应用的功能。当你开始重新设计单体应用时,结合 NGINX 的功能,你的微服务将执行得更好、更易于管理。
- **跨环境的功能抽象** - **跨环境的功能抽象**
从您管理的服务器甚至是各种公共云、私有云和混合云上将功能迁移到 NGINX 作为反向代理服务器可以减少部署在新环境中的设施数量变化。这补充扩展了微服务所固有的灵活性。 从你管理的服务器甚至是各种公共云、私有云和混合云上将功能迁移,将 NGINX 作为反向代理服务器可以减少部署到新环境中的设施数量的变化。这补充扩展了微服务所固有的灵活性。
- **NGINX 微服务参考架构可用性** - **NGINX 微服务参考架构可用性**
您迁移到 NGINX 时,您可以借鉴 [NGINX 微服务参考架构](https://www.nginx.com/blog/introducing-the-nginx-microservices-reference-architecture/)MRAMicroservices Reference Architecture以便在迁移到微服务之后定义应用程序的最终结构,并根据需要使用的 MRA 部分应用于您创建的每个新的微服务 你迁移到 NGINX 时,你可以借鉴 [NGINX 微服务参考架构](https://www.nginx.com/blog/introducing-the-nginx-microservices-reference-architecture/)MRAMicroservices Reference Architecture以便在迁移到微服务后定义应用的最终结构,并根据需要使用 MRA 部分应用在你的新微服务中
总而言之,实现使用 NGINX 作为您转型的第一步,压倒您的单体应用程序,使其更容易获得微服务的所有优势,并为您提供用于进行转换的模型。您可以了解有关 MRA 的更多信息,并获得 NGINX Plus 的免费试用版。 总而言之,使用 NGINX 作为你转型的第一步,压倒你的单体应用,使其更容易获得微服务的所有优势,并为你提供用于转换的模型。你可以了解有关 MRA 的更多信息,并获得 NGINX Plus 的免费试用版。