第1章-逃离单体噩梦

本章包含:

  • 单体噩梦(monolithic hell)的症状以及如何通过采用微服务架构来逃离它
  • 微服务架构的本质特征及其优缺点
  • 微服务是如何支持 DevOps 风格的大型复杂应用程序的开发
  • 微服务架构模式语言以及为什么要使用它

那只是周一的午餐时间, 但是 Food to Go(FTGO) 公司的首席技术官 Mary 已经感到沮丧了.她的一天开始得很好.在上一周的一次优秀会议上, 她与其他软件架构师和开发人员一起学习了最新的软件开发技术, 包括持续部署和微服务架构.Mary 还和她以前在北卡罗莱纳A&T州(North Carolina A&T State)的计算机科学同学见面,分享了技术领导战争的故事.这次会议让她感到自己被赋予了权力, 并渴望改进 FTGO 开发软件的方式.

不幸的是, 这种感觉很快就消失了.她刚回到办公室的第一天早上, 又一次痛苦地与高级工程师和商务人士会面.他们花了两个小时讨论为什么开发团队会错过另一个关键的发布日期.可悲的是, 这种会议在过去几年里越来越普遍.尽管采用了敏捷, 开发的速度却在减慢, 几乎不可能实现业务目标.更糟糕的是, 似乎没有一个简单的解决方案.

会议让 Mary 意识到 FTGO 正遭受着 单体噩梦(monolithic hell) 的折磨, 解决之道就是采用微服务架构.但是在会议上描述的微服务架构和相关的最先进的软件开发实践感觉像是一个难以实现的梦想.Mary 不清楚她如何在改善 FTGO 软件开发方式的同时扑灭今天的大火.

幸运的是, 正如你将在这本书中学到的, 有一个方法.但首先, 让我们看看 FTGO 面临的问题以及它们是如何实现的.

缓慢地走向单体噩梦

自 2005 年末推出以来, FTGO 的发展突飞猛进.如今, 它是美国领先的在线食品递送公司之一.该公司甚至计划向海外扩张, 尽管由于在实现必要功能方面的拖延, 这些计划处于危险之中.

FTGO 应用程序的核心非常简单.消费者使用 FTGO 网站或移动应用程序在当地餐馆下单.FTGO 协调一个运送订单的快递网络.它还负责支付快递员和餐厅的费用.餐厅使用FTGO 网站来编辑菜单和管理订单.该应用程序使用各种 web 服务. 包括用于支付的 Stripe, 用于消息传递的 Twilio 和用于电子邮件的 Amazon Simple Email 服务(SES).

与许多其他老化的企业应用程序一样, FTGO 应用程序是一个整体, 由单个 Java Web 应用程序存档(WAR)文件组成.多年来, 它已经成为一个庞大而复杂的应用程序.尽管FTGO 开发团队尽了最大的努力, 但它已经成为一个泥球模型的例子(www.laputan.org/mud/).用这种模式的作者 Foote 和 Yoder 的话来说, 这是一种 “结构松散、杂乱无章、草率、管道胶带和捞砂线、意大利面条式代码丛林”.软件交付的速度已经放缓.更糟糕的是, FTGO 应用程序是使用一些过时的框架编写.FTGO 应用程序显示了单体噩梦的所有症状.

下一节描述 FTGO 应用程序的架构.然后讨论了为什么单体架构一开始工作得很好.我们将讨论 FTGO 应用程序的架构是如何不适应其发展的, 以及这是如何导致单体噩梦的.

FTGO 应用程序的架构

FTGO 是一个典型的企业 Java 应用程序.图 1.1 显示了它的架构.FTGO 应用程序有一个六边形架构, 这种架构风格将在第 2 章中详细描述.在六边形架构中, 应用程序的核心由业务逻辑组成.围绕业务逻辑的是实现 UI 并与外部系统集成的各种适配器.

Figure-1.1_The_FTGO_application_has_a_hexagonal_architecture

业务逻辑由模块组成, 每个模块都是域对象的集合.这些模块的示例包括订单管理交付管理账单支付.有几个适配器与外部系统交互.一些是入站(inbound)适配器, 它们通过调用业务逻辑(包括 REST APIWeb UI 适配器)来处理请求.其他的是出站(outbound)适配器, 它使业务逻辑能够访问 MySQL 数据库并调用 Twilio 和 Stripe 等云服务.

尽管有一个逻辑模块化的架构, 但是 FTGO 应用程序被打包成一个 WAR 文件.该应用程序是广泛使用的单体风格软件架构的一个示例, 这种风格将系统构造为单个可执行或可部署组件.如果 FTGO 应用程序是用 Go 语言(GoLang)编写的, 那么它就是一个可执行文件.应用程序的 Ruby 或 NodeJS 版本将是源代码的单个目录层次结构.单体架构本身并不坏.FTGO 开发人员在为他们的应用程序选择单体架构时做出了一个很好的决定.

单体架构的好处

在 FTGO 的早期, 当应用程序相对较小时, 应用程序的单体架构有很多好处:

  • 开发简单-IDEs 和其他的开发工具关注于构建单体应用.
  • 易于对应用程序进行彻底更改-你以更改代码和数据库 schema、构建和部署.
  • 直接进行测试-开发人员编写端到端测试来启动应用程序, 调用 REST API 并使用 Selenium 测试 UI.
  • 直接进行部署—开发人员只需将 WAR 文件复制到安装了 Tomcat 的服务器.
  • 容易扩展-FTGO 在负载均衡器后面运行应用程序的多个实例.

然而, 随着时间的推移, 开发、测试、部署和扩展变得越来越困难.让我们看看为什么.

生活在单体噩梦中

不幸的是, 正如 FTGO 开发人员所发现的, 单体架构有一个巨大的限制.成功的应用程序,如 FTGO 应用程序, 有一种在单体架构上不断扩展的习惯.每一次冲刺, FTGO 开发团队都会实现更多的功能, 这使得代码库越来越大.此外, 随着公司越来越成功, 开发团队的规模也在稳步增长.这不仅提高了代码库的增长率, 还增加了管理开销.

如图 1.2 所示, 曾经小巧、简单的 FTGO 应用程序多年来已经成长为一个庞然大物.同样, 小型的开发团队现在已经变成了多个 Scrum 团队, 每个团队都在一个特定的功能领域工作.由于它的架构已经过时, FTGO 处于一个单体应用的状态.发展是缓慢而痛苦的.敏捷开发和部署是不可能的.让我们看看为什么会这样.

Figure-1.2 A case of monolithic hell

复杂性威胁着开发人员

FTGO 应用程序的一个主要问题是它太复杂了.它太大了, 任何开发人员都无法完全理解.因此, 修复 bug 和正确实现新特性变得非常困难和耗时.最后期限错过了.

更糟糕的是, 这种压倒性的复杂性往往是螺旋式下降.如果代码库难以理解, 开发人员就不会正确地进行更改.每一次更改都会使代码基逐渐变得更复杂, 更难理解.图 1.1 前面所示的整洁的模块化架构并不反映现实.FTGO 正逐渐变成一个可怕的、难以理解的、巨大的泥球.

Mary 记得最近参加了一个会议, 她遇到了一个开发人员, 他正在编写一个工具来分析数以百万计的代码行(lines-of-code, LOC)应用程序中数千个 jar 之间的依赖关系.当时, 这个工具似乎是 FTGO 可以使用的.现在她不那么肯定了.Mary 认为更好的方法是迁移到更适合复杂应用程序的架构: 微服务.

开发缓慢

FTGO 开发人员发现, 除了必须克服难以克服的复杂性之外, 日常的开发任务也很缓慢.大型应用程序会重载并减慢开发人员的 IDE 速度.构建 FTGO 应用程序需要很长时间.而且, 由于它太大, 应用程序需要很长时间才能启动.因此, 编辑构建-运行-测试循环需要很长时间, 这会严重影响生产率.

从提交到部署的路径是漫长而艰巨的

FTGO 应用程序的另一个问题是, 将更改部署到生产环境是一个漫长而痛苦的过程.团队通常每个月部署一次产品更新, 通常是在周五或周六晚上.Mary 一直认为, 软件即服务(SaaS)应用程序的最先进技术是持续部署:每天在工作时间多次将更改部署到生产环境中.显然, 到 2011 年为止, Amazon.com 每 11.6 秒就部署一次更改到生产环境中, 而不会对用户产生任何影响!对于 FTGO 开发者来说, 每月更新一次以上的产品似乎是一个遥远的梦想.而采用连续部署几乎是不可能的.

FTGO 部分采用了敏捷.工程团队分为小队, 使用两周的冲刺.不幸的是, 从代码完成到在生产环境中运行的过程是漫长而艰辛的.许多开发人员都提交到相同的代码库, 其中一个问题是构建常常处于不可发布的状态.当 FTGO 开发人员试图通过使用特性分支来解决这个问题时.他们的尝试导致了冗长而痛苦的合并.因此, 一旦一个团队完成了冲刺, 随之而来的就是很长一段时间的测试和代码稳定.

将更改引入到生产中需要很长时间的另一个原因是测试需要很长时间.由于代码库非常复杂, 而且还不清楚更改的影响, 开发人员和持续集成(CI)服务器必须运行整个测试套件.系统的一些部分甚至需要人工测试.诊断和修复测试失败的原因也需要一段时间.因此, 完成一个测试周期需要几天的时间.

扩展困难

FTGO 团队在扩展其应用程序方面也存在问题.这是因为不同的应用程序模块有相互冲突的资源需求.例如, 餐馆数据存储在一个大的内存数据库中, 该数据库理想地部署在具有大量内存的服务器上.相反, 图片处理模块是 CPU 密集型的, 最好部署在具有大量 CPU 的服务器上.因为这些模块是同一个应用程序的一部分, 所以 FTGO 必须在服务器配置上妥协.

交付一个可靠的单体是具有挑战性

FTGO 应用程序的另一个问题是缺乏可靠性.因此, 经常出现生产中断.它不可靠的一个原因是, 由于应用程序很大, 彻底测试应用程序是很困难的.这种可测试性的缺乏意味着 bug 会进入生产环境.更糟糕的是, 应用程序缺乏故障隔离, 因为所有模块都在同一个进程中运行.每隔一段时间, 一个模块中的一个 bug—例如内存泄漏—就会使得应用程序的所有实例逐个崩溃.FTGO 开发人员不喜欢在半夜被传呼由于生产中断.商人更不喜欢失去收入和信任.

受困于日益过时的技术栈中

FTGO 团队体验到的单体噩梦的最后一个方面是, 架构迫使他们使用一个正在变得越来越过时的技术栈.单一架构使得采用新的框架和语言变得困难.重写整个单体应用程序, 使用一种可能更好的新技术, 是非常昂贵和危险的.因此, 开发人员被在项目开始时所做的技术选择卡住了.通常, 他们必须维护使用日益过时的技术栈编写的应用程序.

Spring 框架在向后兼容的同时继续发展, 因此理论上 FTGO 可以进行升级.不幸的是, FTGO 应用程序使用的框架版本与新版本的 Spring 不兼容.开发团队从来没有时间升级这些框架.因此, 应用程序的主要部分使用越来越过时的框架编写.更重要的是, FTGO 开发人员希望试验像 GoLang 和 NodeJS 这样的非 JVM 语言.遗憾的是, 对于单体应用程序来说, 这是不可能的.

为什么此书和你相关

您很可能是开发人员、架构师、CTO 或工程副总裁.您负责的应用程序已经不再适用于单体架构.就像 FTGO 的 Mary 一样, 您在和软件交付做斗争, 想要知道如何逃离单体应用的噩梦.或者, 您可能担心您的组织正在走向单体噩梦, 您想知道如何在为时已晚之前改变方向.如果您需要逃离或避免单体噩梦, 这本书适合你.

这本书花了很多时间来解释微服务架构的概念.我的目标是让你理解这些概念, 不管你使用什么技术.你所需要的只是熟悉企业应用程序架构和设计的基础知识.特别是, 你需要知道以下几点:

  • 三层架构
  • Web 应用程序设计
  • 如何使用面向对象设计来开发业务逻辑
  • 如何使用 RDBMS: SQL 和 ACIS 事务
  • 如何使用消息代理(message broker)和 REST API 进行进程间通信
  • 安全性,包括认证和授权

本书中的代码示例使用 Java 和 Spring 框架编写.这意味着为了充分利用示例, 您还需要熟悉 Spring 框架.

你会从书中学到什么

当你读完这本书的时候, 你会明白下面的内容:

  • 微服务架构的本质特征, 它的优点和缺点, 以及何时使用
  • 分布式数据管理模式
  • 有效的微服务测试策略
  • 微服务的部署选项
  • 将单体应用程序重构为微服务架构的策略

你也可以做到以下几点:

  • 使用微服务架构模式架构一个应用程序
  • 开发服务的业务逻辑
  • 使用 sagas 维护跨服务的数据一致性
  • 实现跨服务的查询
  • 有效地测试微服务
  • 开发安全,可配置和可观察的生产就绪服务
  • 将现有的单体应用重构为微服务

微服务架构的救援

Mary 得出结论, FTGO 必须迁移到微服务架构.

有趣的是, 软件架构与功能需求几乎没有什么关系.您可以使用任何架构实现一组用例(应用程序的功能需求).事实上, 对于成功的应用程序(如 FTGO 应用程序)来说, 称为泥球是很常见的.

然而, 架构很重要, 因为它影响所谓的服务质量(quality of service )需求, 也称为非功能性需求(nonfunctional requirements)质量属性( quality attributes)质量(ilities).随着 FTGO 应用程序的发展, 各种质量属性都受到了影响, 最明显的是那些影响软件交付速度的属性:可维护性、可扩展性和可测试性.

一方面, 一个纪律严明的团队可以放慢其走向单体噩梦的步伐.团队成员可以努力维护他们的应用程序的模块化.他们可以编写全面的自动化测试.另一方面, 他们不能避免在单个单体应用程序上工作的大型团队的问题.它们也无法解决日益过时的技术栈问题.一个团队能做的最好的事情就是推迟不可避免的事情.为了逃离单体应用的噩梦, 他们必须迁移到一个新的架构: 微服务架构.

如今, 越来越多的人认为, 如果您正在构建一个大型的、复杂的应用程序, 您应该考虑使用微服务架构.但究竟什么是微服务?不幸的是, 这个名字起不到什么作用, 因为它过分强调了大小.微服务架构有许多定义.有些人太过拘泥于字面意思, 声称服务应该是很小的——例如, 100 行代码.另一些人则认为一项服务只需要两周的开发时间.Adrian Cockcroft 以前在 Netflix 工作, 将微服务架构定义为由具有有限上下文的松散耦合元素组成的面向服务的架构.这个定义还不错, 但有点复杂.我们看看能不能做得更好.

规模立方(Scale cube)和微服务

我对微服务架构的定义受到 Martin Abbott 和 Michael Fisher 的优秀著作《可伸缩性的艺术》(Addison-Wesley, 2015)的启发.本书描述了一个有用的三维可伸缩性模型: 规模立方(scale cube), 如图 1.3 所示.

Figure-1.3 The scale cube

这种模型定义了三种方式来伸缩应用程序: X, Y 和 Z.

X 轴扩展负载平衡跨越多个相同的实例的请求

X 轴缩放是扩展单体应用程序的一种常见方法.图 1.4 显示了X 轴缩放的工作原理.在负载均衡器后面运行应用程序的多个实例.负载均衡器在应用程序的 N 个相同实例之间分发请求.这是提高应用程序容量和可用性的好方法.

Figure-1.4 X-axis scaling

Z 轴缩放基于请求的属性路由请求

Z 轴扩展同样运行单体应用程序的多个实例, 但与 X 轴扩展不同的是, 每个实例只负责数据的一个子集.图 1.5 显示了Z 轴伸缩的工作原理.位于实例前面的路由器使用请求属性将其路由到适当的实例.例如, 应用程序可以使用 userId 路由请求.

Figure-1.5 Y-axis scaling

在本例中, 每个应用程序实例负责一个用户子集.路由器使用请求授权(Authorization)头指制定 userId 选择应用程序的 N 个相同实例中的一个.Z 轴伸缩是扩展应用程序以处理不断增加的事务和数据量的好方法.

Y 轴伸缩功能将应用程序分解为服务

X 轴和 Z 轴伸缩提高了应用程序的容量和可用性.但是这两种方法都不能解决增加开发和应用程序复杂性的问题.要解决这些问题, 您需要应用 Y 轴伸缩或功能分解.图 1.6 显示了 Y 轴伸缩的工作方式: 通过将单个应用程序分割成一组服务.

Figure-1.6 Y-axis scaling

一个服务是一个微型应用程序, 它实现了狭义的功能, 比如订单管理、客户管理等等.服务使用 X 轴缩放来扩展, 尽管有些服务也可以使用 Z 扩展.例如, 订单服务由一组负载均衡的服务实例组成.

微服务架构(microservices)的高层定义是一种架构风格, 在功能上将应用程序分解为一组服务.注意, 这个定义没有说明大小.相反, 重要的是每个服务都有一组集中的、有凝聚力的职责.稍后我将在书中讨论这是什么意思.

现在让我们看看微服务架构是一种怎样的模块化形式.

微服务作为一种模块化的形式

在开发大型、复杂的应用程序时, 模块化是必不可少的.像 FTGO 这样的现代应用程序太大, 个人无法开发.它也很复杂, 没发被一个人理解.应用程序必须分解成由不同的人开发和理解的模块.在单体应用程序中, 模块是使用编程语言结构(如 Java 包)和构造构件(如 Java JAR 文件)的组合来定义的.然而, 正如 FTGO 开发人员所发现的, 这种方法在实践中往往不能很好地工作.长寿命的单体应用程序通常会退化为巨大的泥球.

微服务架构使用服务作为模块化的单元.服务有一个 API, 这是难以违反的不可跨越的边界.不能像使用 Java 包那样绕过 API 访问内部类.因此, 随着时间的推移, 保持应用程序的模块化要容易得多.使用服务作为构建块还有其他好处, 包括能够独立部署和扩展它们.

每个服务有自己的数据库

微服务架构的一个关键特征是服务是松散耦合的, 并且仅通过 API 进行通信.实现松耦合的一种方法是每个服务都有自己的数据存储.例如, 在在线商店中, 订单服务(Order Service)有一个包含 ORDERS 表的数据库, 而 客户服务(Customer Service)有一个包含 CUSTOMERS 表的数据库.在开发时, 开发人员可以更改服务的schema, 而不必与从事其他服务的开发人员协调.在运行时, 服务彼此隔离-例如, 一个服务永远不会被阻塞, 因为另一个服务持有数据库锁.

别担心: 松散耦合不会让 Larry Ellison(拉里·埃里森)更富有
要求每个服务都有自己的数据库并不意味着它有自己的数据库服务器.例如, 您不必在 Oracle RDBMS 许可证上多花 10 倍的钱.第2章深入探讨了这个主题.

FTGO 微服务架构

现在我们已经定义了微服务架构并描述了它的一些基本特性, 接下来让我们看看如何将其应用到 FTGO 应用程序中.

本书的剩余部分将深入讨论 FTGO 应用程序的微服务架构.但首先让我们快速看看将 Y 轴缩放应用到这个应用程序意味着什么.如果我们对 FTGO 应用程序应用 Y 轴分解, 就会得到如图 1.7 所示的架构.分解后的应用程序由许多前端和后端服务组成.我们还将应用 X 轴, 可能还有 Z 轴缩放, 以便在运行时每个服务都有多个实例.

前端服务包括 API 网关和餐馆 Web UI.API 网关扮演着门面的角色, 在第 8 章中有详细描述, 它提供了由消费者和快递人员的移动应用程序使用的 REST API.餐馆 Web UI 实现了餐馆用来管理菜单和处理订单的 Web 界面.

Figure-1.7 Some of the services of the microservice architecture

许多服务与本章前面描述的模块相对应.不同的是, 每个服务及其 API 都有非常明确的定义.每一个都可以独立开发、测试、部署和扩展.而且, 这种架构在保持模块化方面做得很好.开发人员不能绕过服务的 API 来访问其内部组件.第 13 章描述了如何将现有的单体应用程序转换为微服务.

微服务架构与 SOA 的比较

一些批评微服务架构的人声称它并不是什么新东西-它是面向服务的架构(SOA).从高层次来讲, 它们有一些相似之处.SOA 和微服务架构都是将系统构造为一组服务的架构风格.但是, 如表 1.1 所示, 一旦深入研究, 就会发现显著的差异.

表 1-1 SOA 和微服务对比

SOA微服务
内部服务通信智能管道(Smart pipes), 如企业服务总线(ESB), 使用重量级协议, 如 SOAP 和其他 WS* 标准哑管道(Dumb pipes), 如消息代理, 或直接服务对服务通信, 使用轻量级协议, 如 REST 或 gRPC
数据全局数据模型与共享数据库每个服务都有数据模型和数据库
典型的服务大型单体应用小型服务

SOA 和微服务架构通常使用不同的技术栈.SOA 应用程序通常使用重量级技术, 如 SOAP 和其他 WS* 标准.他们通常使用 ESB, 一个包含业务和消息处理逻辑的智能管道(Smart pipes)来集成服务.使用微服务架构构建的应用程序倾向于使用轻量级的开源技术.服务通过哑管道(Dumb pipes)进行通信, 比如消息代理或 REST 或 gRPC 之类的轻量级协议.

SOA 和微服务架构在处理数据的方式上也有所不同.SOA 应用程序通常具有全局数据模型并共享数据库.相反, 正如前面提到的, 在微服务架构中, 每个服务都有自己的数据库.此外, 如将在第 2 章所述的, 通常认为每个服务都有自己的领域模型.

SOA 和微服务架构之间的另一个关键区别是服务的大小.SOA 通常用于集成大型、复杂、独立的应用程序.尽管微服务架构中的服务并不总是很小, 但它们几乎总是要小得多.因此, SOA 应用程序通常由一些大型服务组成, 而基于微服务的应用程序通常由几十个或数百个较小的服务组成.

微服务架构的优点和缺点

让我们先想想优点, 然后再看看缺点.

微服务架构的优点

微服务架构有以下的优点:

  • 它支持大型复杂应用程序的持续交付和部署.
  • 服务很小, 很容易维护.
  • 服务独立部署.
  • 服务独立扩展.
  • 微服务架构使团队能够自治.
  • 它允许轻松地试验和采用新技术.
  • 它具有更好的故障隔离.

让我们看下每一种优点.

它支持大型复杂应用程序的持续交付和部署

微服务架构最重要的优点是它支持大型复杂应用程序的持续交付和部署.正如 1.7 节后面所述的, 持续交付/部署是 DevOps 的一部分, DevOps 是一组用于快速、频繁和可靠交付软件的实践.高性能的 DevOps 组织通常将更改部署到生产环境中而很少出现生产问题.

有三种方式使微服务架构能够持续交付/部署:

  • 它具有持续交付/部署所需的可测试性-自动化测试是持续交付/部署的关键实践.由于微服务架构中的每个服务都相对较小, 因此自动化测试更容易编写, 执行速度也更快.因此, 应用程序的 bug 会更少.
  • 它具有持续交付/部署所需的可部署性-每个服务都可以独立于其他服务部署.如果负责服务的开发人员需要部署该服务的本地更改, 他们不需要与其他开发人员协调.他们可以部署他们的变更.因此, 更容易将更改频繁地部署到生产环境中.
  • 它使开发团队能够自治和解耦-您可以将工程组织构建为小型(例如, 两个批萨)团队的集合.每个团队单独负责一个或多个相关服务的开发和部署.如图 1.8 所示, 每个团队可以独立于所有其他团队开发、部署和扩展其服务.因此, 开发速度大大提高.

Figure-1.8 The microservices-based FTGO application consists of a set of loosely coupled services

持续交付和部署的能力有几个商业利益:

  • 它缩短了进入市场的时间, 从而使业务能够迅速对客户的反馈做出反应.
  • 它使企业能够提供当今客户所期望的可靠服务.
  • 员工满意度更高, 因为更多的时间花在交付有价值的功能上, 而不是去救火.

因此,微服务架构已经成为任何依赖软件技术的业务的关键所在.

服务很小, 很容易维护

微服务架构的另一个好处是每个服务都相对较小.对于开发人员来说, 代码更容易理解.小型的代码库不会降低 IDE 的速度, 从而提高开发人员的工作效率.而且, 每个服务的启动速度通常都比大型整体服务快得多, 这也使得开发人员更有效率, 并加快了部署速度.

服务独立扩展

微服务加过中的每个服务都可以使用 X 轴克隆和 Z 轴分区独立于其他服务进行伸缩.此外, 每个服务都可以部署在最适合其资源需求的硬件上.这与使用单体架构时非常不同, 在单体架构中, 具有完全不同的资源需求的组件(例如, CPU 密集型组件和内存密集型组件)必须一起部署.

更好的故障隔离

微服务架构具有更好的故障隔离.例如, 一个服务中的内存泄漏只影响该服务.其他服务将继续正常处理请求.相比之下, 单体架构中一个行为不好的组件将导致整个系统的崩溃.

轻松地试验和采用新技术

最后但并非最不重要的一点是, 微服务架构消除了对技术栈的任何长期承诺.原则上, 在开发新服务时, 开发人员可以自由选择最适合该服务的语言和框架.在许多组织中, 限制选择是有意义的, 但关键是你不受过去决定的约束.

此外, 因为服务很小, 所以使用更好的语言和技术重写它们变得很实用.如果一项新技术的试验失败了, 你可以放弃这项工作, 而不用让整个项目冒风险.这与使用单体架构时非常不同, 在单体架构中, 最初的技术选择严重限制了将来使用不同语言和框架的能力.

微服务架构的缺点

当然, 没有什么技术是银弹, 而且微服务架构有许多明显的缺陷和问题.事实上, 这本书的大部分内容都是关于如何解决这些缺点和问题的.当你读到这些挑战时, 不要担心.在这本书的后面, 我描述了解决这些问题的方法.

下面是微服务架构的主要缺陷和问题:

  • 寻找合适的服务集是具有挑战性的
  • 分布式系统非常复杂, 这使得开发、测试和部署变得非常困难
  • 部署跨多个服务的特性需要仔细的协调
  • 决定何时采用微服务架构是很困难的

让我们依次看下每一个.

寻找合适的服务集是具有挑战性的

使用微服务架构的一个挑战是, 没有一个具体的、定义良好的算法来将系统分解为服务.与许多软件开发一样, 这是一门艺术.更糟糕的是, 如果不正确地分解一个系统, 您将构建一个分布式单体系统(distributed monolith), 这个系统由必须部署在一起的耦合服务组成.分布式单体架构既有单体架构的缺点, 也有微服务架构的缺点.

分布式系统是复杂的

使用微服架构的另一个问题是, 开发人员必须处理创建分布式系统的额外复杂性.服务必须使用进程间通信机制.这比简单的方法调用更复杂.此外, 服务必须被设计为能够处理分区故障, 并能处理远程服务不可用或具有高延迟.

实现跨多个服务的用例需要使用不熟悉的技术.每个服务都有自己的数据库, 这使得实现跨服务的事务和查询成为一项挑战.如第 4 章所述, 基于微服务的应用程序必须使用众所周知的 sagas 来维护服务之间的数据一致性.第 7 章解释了基于微服务的应用程序不能使用简单查询从多个服务检索数据.相反, 它必须使用 API 组合或 CQRS 视图来实现查询.

IDE 和其他开发工具关注于构建单体应用程序, 而不为开发分布式应用程序提供显式支持.编写涉及多个服务的自动化测试是一项挑战.这些都是特定于微服务架构的问题.因此, 为了成功地使用微服务, 组织的开发人员必须具有复杂的软件开发和交付技能.

微服务架构还引入了重大的操作复杂性.更多的移动部件-不同类型服务的多个实例-必须在生产中进行管理.要成功部署微服务, 您需要高度自动化.您必须使用以下技术:

  • 自动部署工具, 比如 Netflix Spinnaker
  • 一个现成的 PaaS, 比如 Pivotal Cloud Foundry 或 Red Hat OpenShift
  • Docker 编排平台, 如 Docker Swarm 或 Kubernetes

我在第 12 章中更详细地描述部署选项.

部署跨越多个服务的特性需要仔细的协调

使用微服务架构的另一个挑战是, 部署跨多个服务的特性需要在不同的开发团队之间进行仔细的协调.您必须创建一个部署计划, 根据服务之间的依赖关系对服务部署进行排序.这与单体架构非常不同, 在单体架构中, 您可以轻松地将更新部署到多个组件上.

决定何时采用微服务架构是很困难的

使用微服务架构的另一个问题是决定在应用程序生命周期的哪个点应该使用这个架构.在开发应用程序的第一个版本时, 通常不会遇到架构所要解决的问题.此外, 使用复杂的分布式架构会减慢开发速度.对于初创企业来说, 这可能是一个很大的难题, 其中最大的问题通常是如何快速发展业务模型和相应的应用程序.使用微服务架构使快速迭代变得更加困难.几乎可以肯定的是, 创业应该从单一应用程序开始.

但是, 稍后, 当问题是如何处理复杂性时, 从功能上将应用程序分解为一组微服务是有意义的.您可能会发现, 由于复杂的依赖关系, 重构很困难.第13章讨论了将单个应用程序重构为微服务的策略.

正如您所看到的, 微服务架构提供了许多好处, 但也有一些明显的缺点.由于这些问题, 采用微服务架构不应该轻率地进行.但对于复杂的应用程序, 比如面向消费者的web 应用程序或 SaaS 应用程序, 这通常是正确的选择.著名的网站如 eBay(www.slideshare.net/randyshoup/ebay-architecturestriking -balance-between site-stability-features-speed-performance-cost)、Amazon.com、Groupon 和 Gilt 都已经从一个单一的架构发展成为一个微服务架构.

在使用微服务架构时, 您必须解决许多设计和架构问题.更重要的是, 许多问题都有多种解决方案, 每一个都有不同的权衡.没有一个完美的解决方案.为了帮助指导您的决策, 我创建了微服务架构模式语言.在本书的其余部分中, 当我向您介绍微服务架构时, 我引用了这种模式语言.让我们看看什么是模式语言.以及它为什么有用.

微服务架构语言

架构和设计都是关于决策的.您需要决定是单体架构还是微服务架构最适合您的应用程序.在做这些决定时, 你要考虑很多权衡取舍.如果选择了微服务架构, 则需要解决许多问题.

描述各种架构和设计选项并改进决策制定的一个好方法是使用模式语言.首先让我们了解为什么需要模式和模式语言, 然后我们将介绍微服务架构模式语言.

微服务架构不是银弹

早在 1986 年,《人月神话》(Addison-Wesley Professional, 1995 年)的作者 Fred Brooks 说, 在软件工程中, 没有灵丹妙药.这意味着没有任何技术或技巧可以让你的生产力提高十倍.然而几十年后, 开发人员仍然在激烈地争论他们最喜欢的银弹, 他们坚信他们最喜欢的技术将大大提高他们的生产力.

很多论据都遵循了 suck/rock 二分法(http://nealford.com/memeagora/2009/08/05/suck-rock-dichotomy.html), Neal Ford 创造的一个术语, 它描述了软件世界中的所有东西要么是 suck 的, 要么是 rock 的, 没有中间立场.这些论点都有这样的结构: 如果你做 X,那么小狗狗就会死去,因此你必须做 Y.例如, 同步与反应式编程、面向对象与函数式、Java 与 JavaScript、REST 与消息传递.当然, 现实更加微妙.每一种技术都有其倡导者经常忽视的缺点和局限性.因此, 采用的技术通常遵循 Gartner 技术成熟度曲线(https://en.wikipedia.org/wiki/Hype_cycle), 其中新兴技术经历五个阶段, 包括过高期望的峰值(它很狂热-rock), 随后是理想幻灭的低谷(它很糟糕-suck), 并以实质生产的高峰期结束(我们现在明白了权衡和何时使用它).

Gartner 技术成熟度曲线中文可参考 技术成熟度曲线

技术成熟度曲线
(图片来自 http://huaban.com/pins/111734468/)

微服务也不能幸免于银弹现象.这个架构是否适合您的应用程序取决于许多因素.因此, 建议始终使用微服务架构是不好的建议, 但建议永远不要使用它同样是不好的建议.和许多事情一样, 这要视情况而定.

这些关于技术的两极分化和炒作的根本原因是, 人类主要是由他们的情感驱动.乔纳森海特(Jonathan Haidt)在他的优秀著作《正义的心灵: 为什么好人会被政治和宗教分裂》(Vintage 出版社, 2013 年)中,用大象和骑手的比喻来描述人类的心灵是如何运作的.大象代表人类大脑的情感部分.它做了大部分的决定.骑手代表大脑的理性部分.它有时会影响大象, 但主要是为大象的决定提供理由.

我们-软件开发社区-需要克服我们的情感天性, 找到一种更好的方式来讨论和应用技术.讨论和描述技术的一个好方法是使用模式格式(pattern format), 因为它是客观的.在以模式格式描述技术时, 您必须描述其缺点.让我们看看模式格式.

模式和模式语言

模式是对在特定上下文中发生的问题的可重用解决方案.这个想法起源于现实世界的架构, 并被证明在软件架构和设计中是有用的.模式的概念是由现实世界的建筑师 Christopher Alexander 提出.他还创建了模式语言的概念, 这是解决特定领域问题的相关模式的集合.他的书《模式语言:城镇、建筑物、建筑》(牛津大学出版社, 1977 年)描述了一种建筑模式语言, 由 253 种模式组成.这些模式从解决方案到高层次的问题, 比如城市的位置(“取水”), 到低层次的问题, 比如如何设计房间(“每个房间的两面都有灯光”).这些模式中的每一种都通过将范围从城市到窗口的物理对象排列来解决问题.

Christopher Alexander 的著作启发了软件社区采用模式和模式语言的概念.由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 合著的《设计模式:可重用面向对象软件的元素》(Addison-Wesley Professional, 1994)是面向对象设计模式的集合.这本书在软件开发人员中普及了模式.自上世纪 90 年代中期以来, 软件开发人员记录了大量的软件模式.软件模式通过定义一组协作软件元素来解决软件架构或设计问题.

例如, 假设您正在构建一个必须支持各种透支策略的银行应用程序.每项政策都对账户余额和透支账户收取的费用进行了限制.您可以使用策略模式来解决这个问题, 策略模式是经典设计模式书籍中的一个著名模式.该策略模式定义的解决方案由三个部分组成:

  • 一个策略接口 Overdraft 封装了透支的算法
  • 一个或多个具体的策略类, 每个特定上下文对应一个
  • Account 类使用这个算法

策略模式是面向对象的设计模式, 因此解决方案的元素是类.在本节后面, 我将描述高级设计模式, 其中解决方案由协作服务组成.

模式之所以有价值, 一个原因是模式必须描述它所应用的上下文.解决方案是特定于特定上下文的, 在其他上下文中可能不能很好地工作, 这种想法是对通常讨论的技术的改进.例如, 对于用户较少的应用程序来说, 以 Netflix 的规模解决这个问题的解决方案可能不是最好的方法.

然而, 模式的价值远远超过了要求您考虑问题的上下文.它迫使您描述解决方案的其他重要但经常被忽略的方面.一个常用的模式结构包括三个特别有价值的部分:

  • 约束(forces)
  • 产生的背景
  • 相关的模式

让我们从力开始, 看看每一个.

约束:解决疑难时必须解决的问题

模式的约束部分描述了在给定上下文中解决问题时必须解决的约束问题.约束可能会发生冲突, 因此不可能解决所有的冲突.哪种约束更重要取决于环境.你必须优先解决一些问题.例如, 代码必须易于理解并具有良好的性能.用响应式编写的代码比同步代码有更好的性能, 但通常更难于理解.明确列出这些约束是有用的, 因为它清楚地表明哪些问题需要解决.

产生的背景: 应用模式的后果

模式产生的背景部分描述了应用模式的后果.它包括三个部分:

  • 优点-模式的优点, 包括已经解决的约束
  • 缺点-模式的缺点, 包括未解决的约束
  • 问题-应用模式引入的新问题

产生的背景提供了解决方案的更完整和更少偏见的视图, 从而能够做出更好的设计决策.

相关模式:五种不同类型的关系

模式的相关模式部分描述了模式和其他模式之间的关系.模式之间有五种关系:

  • 前身(Predecessor)-前身模式是一种激发对这种模式需求的模式.例如, 除了单体架构模式之外, 微服务架构模式是模式语言中其他模式的前身.
  • 后继者(Successor)-解决这个模式引入的问题的模式.例如, 如果应用微服务架构模式, 则必须应用许多后继模式, 包括服务发现模式和断路器模式.
  • 替代模式-为这种模式提供另一种解决方案的模式.例如, 单体架构模式和微服务架构模式是构建应用程序的可替代方法.你选择其中一个.
  • 泛化(Generalization)-一个问题的通用解决方案.例如, 在第 12 章中, 您将了解单主机单服务模式(Single service per host pattern)的不同实现.
    专门化(Specialization)-特定模式的专门化形式.例如, 在第 12 章中, 您将了解将服务作为容器模式部署是单主机单服务的专门化.

此外, 您可以将处理特定问题区域中的问题的模式组织成组.相关模式的明确描述为如何有效地解决特定问题提供了有价值的指导.图 1.9 显示了如何以可视方式表示模式之间的关系.

Figure-1.9 The visual representation of different types of relationships between the patterns

图 1.9 所示的模式之间不同类型的关系表示如下:

  • 体现了前身-后继者模式的关系
  • 模式是同一问题的替代解决方案
  • 表明一个模式是另一个模式的专门化
  • 适用于特定问题领域的模式

通过这些关系联系起来的模式集合有时形成所谓的模式语言.模式语言中的模式一起工作以解决特定领域中的问题.特别是, 我已经创建了微服务架构模式语言.它是微服务相关的软件架构设计模式的集合.让我们来看看这种模式语言.

微服务架构模式概览

微服务架构模式语言是一组模式, 帮助您使用微服务架构构建应用程序.图 1.10 显示了模式语言的高级结构.模式语言首先帮助您决定是否使用微服务架构.它描述了单体架构和微服务架构, 以及它们的优缺点.然后, 如果微服务架构非常适合您的应用程序, 那么模式语言可以通过解决各种架构和设计问题来帮助您有效地使用它.

Figure-1.10 A high-level view of the Microservice architecture pattern language

模式语言由几组模式组成.在图 1.10 的左边是应用程序架构模式组、单体架构模式和微服务架构模式.这些是我们在本章中讨论过的模式.模式语言的其余部分由一组模式组成, 这些模式是使用微服务架构模式引入的问题的解决方案.

模式分为三层:

  • 基础架构模式-它们解决了开发之外的大部分基础设施问题.
  • 应用程序基础架构模式-这些都是影响开发的基础设施问题.
  • 应用程序模式-解决了开发者面对的问题.

这些模式是根据它们解决的问题分组在一起的.让我们来看看主要的模式组.

将应用程序分解为服务的模式

决定如何将系统分解为一组服务在很大程度上是一门艺术, 但是有许多策略可以提供帮助.图 1.11 中显示的两个分解模式是您可以用来定义应用程序架构的不同策略.

Figure 1.11 There are two decomposition patterns Decompose by business capability

第 2 章详细描述了这些模式.

通信模式

使用微服务架构构建的应用程序是一个分布式系统.因此, 进程间通信(IPC)是微服务架构的重要组成部分.关于您的服务如何彼此通信以及如何与外部世界通信, 您必须作出各种架构和设计决策.图 1.12 为通信模式, 分为五组:

  • 通信方式-应该使用什么样的 IPC 机制?
  • 发现(Discovery)-服务的客户端如何确定服务实例的 IP 地址, 以便比如发出 HTTP 请求?
  • 可靠性-您如何确保服务之间的通信是可靠的, 即使服务不可用?
  • 事务性消息-如何将消息的发送和事件的发布与更新业务数据的数据库事务集成起来?
  • 外部 API-应用程序的客户端如何与服务通信?

Figure 1.12 The five groups of communication patterns

第 3 章介绍了前四组模式:通信方式、发现、可靠性和事务消息.第 8 章介绍了外部 API 模式.

用于实现事务管理的数据一致性模式

如前所述, 为了确保松耦合, 每个服务都有自己的数据库.不幸的是, 每个服务都有一个数据库会带来一些重要的问题.我在第 4 章中描述了使用分布式事务(2PC)的传统方法对于现代应用程序来说不是一个可行的选择.相反, 应用程序需要使用 Saga 模式来维护数据一致性.图 1.13 显示了与数据相关的模式.

Figure 1.13 use the Saga pattern to maintain data consistency across services

第 4、5、6 章详细地描述了这些模式.

用于在微服务架构中查询数据的模式

每个服务使用数据库的另一个问题是, 一些查询需要 join 多个服务拥有的数据.服务的数据只能通过其 API 访问, 因此不能对其数据库使用分布式查询.图 1.14 显示了一些用于实现查询的模式.

Figure 1.14 use one of the querying patterns to retrieve data scattered across multiple services

有时您可以使用 API 组合模式, 它调用一个或多个服务的 API 并聚合结果.其他时候, 您必须使用命令查询责任隔离(CQRS)模式, 该模式维护一个或多个更容易查询的数据副本.第 7 章介绍了实现查询的不同方法.

服务部署模式

部署单个应用程序并不总是容易的, 但是从某种意义上说, 部署单个应用程序非常简单.您必须在负载均衡器后面运行应用程序的多个实例.

相比之下, 部署基于微服务的应用程序要复杂得多.可能有数十或数百个服务是用各种语言和框架编写的.还有许多活动部件需要管理.图 1.15 显示了部署模式.

Figure 1.15 Several patterns for deploying microservices

传统的, 通常是手工的, 以特定于语言的打包格式部署应用程序的方式, 例如 WAR 文件, 不能扩展到支持微服务架构.您需要高度自动化的部署基础设施.理想情况下, 您应该使用一个部署平台, 为开发人员提供一个简单的 UI(命令行或 GUI)来部署和管理他们的服务.部署平台通常基于虚拟机、容器或无服务器技术.第 12 章介绍了不同的部署选项.

可观察性模式提供了对应用程序行为的洞察

操作应用程序的一个关键部分是了解其运行时行为, 并对失败请求和高延迟等问题进行故障排除.虽然理解和排除单个应用程序的故障并不总是容易的, 但是它有助于以简单、直接的方式处理请求.每个传入的请求都被负载均衡到一个特定的应用程序实例, 该实例对数据库进行一些调用并返回一个响应.例如, 如果需要了解如何处理某个特定请求, 可以查看处理该请求的应用程序实例的日志文件.

相比之下, 理解和诊断微服务架构中的问题要复杂得多.在最终将响应返回到客户端之前, 请求可以在多个服务之间跳转.因此, 没有一个日志文件可以检索.同样, 由于存在多个疑点, 延迟问题更难以诊断.

您可以使用以下模式来设计可观察的服务:

  • 健康检查 API-暴露返回服务健康状态的端点.
  • 日志聚合-日志服务活动, 并将日志写入中央日志服务器, 该服务器提供搜索和警报功能.
  • 分布式跟踪-为每个外部请求分配一个唯一的 ID, 并在它们在服务之间流动时跟踪请求.
  • 异常跟踪-报告异常跟踪服务的异常, 该服务删除重复的异常, 提醒开发人员, 并跟踪每个异常的解决方案.
  • 应用程序度量—维护度量, 例如计数器和度量, 并将它们暴露给度量服务器.
  • 审计日志-记录用户行为.

第 11 章详细描述了这些模式.

用于服务自动化测试的模式

微服务架构使单个服务更容易测试, 因为它们比单体应用程序小得多.但是, 与此同时, 重要的是测试不同的服务在一起工作, 同时避免使用复杂、缓慢和脆弱的端到端测试, 这些测试将多个服务一起测试.以下是通过隔离测试服务简化测试的模式:

  • 消费者驱动的契约测试(Consumer-driven contract test)-验证服务是否满足其客户端的期望.
  • 消费者端契约测试(Consumer-side contract test)-验证服务的客户端可以与服务通信.
  • 服务组件测试-隔离测试服务.

第 9 章和第 10 章将详细地描述这些测试模式.

处理横切关注点的模式

在微服务架构中, 每个服务都必须实现许多关注点, 包括可观察性模式和发现模式.它还必须实现外部化配置模式, 该模式在运行时向服务提供诸如数据库凭据之类的配置参数.在开发新服务时, 从头开始重新实现这些关注点将花费大量时间.更好的方法是应用微服务机箱模式(Microservice Chassis pattern), 并在处理这些问题的框架之上构建服务.第 11 章更详细地描述了这些模式.

安全模式

在微服务架构中, 用户通常通过 API 网关进行身份验证.然后, 它必须将关于用户的信息(如标识和角色)传递给它调用的服务.一种常见的解决方案是应用访问令牌(token)模式.API 网关将访问 token, 例如 JWT(JSON Web Token)传递给服务, 服务可以验证令牌并获取关于用户的信息.第 11 章更详细地讨论了访问 token 模式.

毫不奇怪, 微服务架构模式语言中的模式关注于解决架构和设计问题.为了成功地开发软件, 您当然需要正确的架构, 但这不是唯一需要考虑的问题.您还必须考虑流程和组织.

超越微观服务: 流程与组织

对于大型、复杂的应用程序, 微服务架构通常是最佳选择.但是除了拥有正确的架构之外, 成功的软件开发还需要您拥有组织、开发和交付流程.图 1.16 显示了流程、组织和架构之间的关系.

Figure 1.16 the relationships between process and organization and architecture

我已经描述了微服务架构.让我们看看组织和流程.

软件开发和交付组织

成功必然意味着工程团队将成长.一方面, 这是一件好事, 因为更多的开发人员可以完成更多的工作.大型团队的问题是, 正如 Fred Brooks 在《人月神话》中所写的, 规模为 N 的团队的沟通开销为 O(N ^ 2).如果团队太大, 由于沟通开销, 它将变得低效.举个例子, 想象一下, 每天和 20 个人一起做一次站立会议.

解决方案是将一个大型单一团队重构为一个团队的团队.每个小组人数不多, 不超过 8-12 人.它有一个明确定义的面向业务的任务: 开发并可能操作一个或多个服务, 这些服务实现了一个特性或业务功能.团队是跨功能的, 可以开发、测试和部署其服务, 而不必经常与其他团队进行通信或协调.

反向康威操纵(reverse Conway maneuver)
为了在使用微服务架构时有效地交付软件, 您需要考虑 Conway 定律(https://en.wikipedia.org/wiki/Conway%27s_law), 声明如下:
设计系统的组织…被限制生产这些组织的通信结构的副本的设计.
–Melvin Conway
换句话说, 应用程序的架构反映了开发它的组织的结构.因此, 很重要的一点是反向应用 Conway 法则(www.thoughtworks.com/radar/techniques/inverse-conway-maneuver), 并设计您的组织, 使其结构反映您的微服务架构.通过这样做, 您可以确保开发团队与服务一样松耦合.

多个团队的速度明显高于单个大团队的速度.正如前面 1.5.1 节所述, 微服务架构在使团队能够自治方面扮演着关键角色.每个团队可以在不与其他团队协调的情况下开发、部署和扩展其服务.此外, 当服务不符合 SLA 时, 很清楚应该联系谁.

更重要的是, 开发组织的可伸缩性更强.您可以通过添加团队来发展组织.如果一个团队变得太大, 您可以将其与其关联的服务或服务分开.因为团队是松耦合的, 所以可以避免大型团队的通信开销.因此, 您可以在不影响生产力的情况下增加人员.

软件开发和交付流程

使用带有瀑布式开发流程的微服务架构就像驾驶一辆马拉的法拉利-您浪费了使用微服务的大部分好处.如果您希望使用微服务架构开发应用程序, 那么采用敏捷开发和部署实践, 如 Scrum 或 Kanban(看板)是非常重要的.更好的是, 您应该实践持续交付/部署, 这是 DevOps 的一部分.

Jez Humble(https://continuousdelivery.com/)对持续交付的定义如下:

持续交付是将所有类型的更改, 包括新特性、配置更改、bug 修复和试验, 安全且快速地以可持续的方式交付到生产或用户手中的能力.

持续交付的一个关键特征是软件总是可发布的.它依赖于高度自动化, 包括自动化测试.持续部署在自动将可发布代码部署到生产环境中的实践中, 进一步实现了持续交付.执行连续部署的高性能组织每天将多次部署到生产环境中, 生产中断的情况要少得多, 并且能够从发生的任何中断中快速恢复(https://puppet.com/resources/whitepaper/state-of-devops-report).正如前面 1.5.1 节所述, 微服务架构直接支持持续交付/部署.

快速行动而不破坏事物
持续交付/部署(以及更一般的 DevOps)的目标是快速而可靠地交付软件.评估软件开发的四个有用指标如下:

  • 部署频率-软件部署到生产环境中的频率
  • 交付周期-从开发人员签入变更到部署变更的时间
  • 平均恢复时间-从生产问题中恢复的时间
  • 更改故障率-

在传统的组织中, 部署频率较低, 交付时间较长.压力重重的开发人员和操作人员通常会熬夜, 在维护窗口期间解决最后一分钟出现的问题.相反, DevOps 组织频繁地发布软件, 通常是每天多次, 生产问题要少得多.例如, 亚马逊(Amazon)在 2014 年每 11.6 秒将变更部署到生产中(http://www.youtube.com/watch?v=dxk8b9rSKOo), 而 Netflix 的一个软件组件交付时间为 16 分钟(https://medium.com/netflix-techblog/how-we-build-code-at-netflix-c5d9bd727f15).

采用微服务的人性化方面

采用微服务架构将改变您的架构、组织和开发流程.但最终, 它改变了人们的工作环境, 正如前面提到的, 这些人是情绪化的生物.如果被忽视, 他们的情绪可能会让微服务的采用变得崎岖不平.Mary 和其他 FTGO 领导人将努力改变 FTGO 开发软件的方式.

威廉和苏珊•布里吉斯合著的畅销书《过渡管理》(Da Capo life Books, 2017,https://wmbridges.com/books)介绍了过渡的概念, 即人们如何在情绪上对变化做出反应的过程.它描述了一个三阶段转换模型:

  1. 结束, 失败, 和放手-当人们面对迫使他们走出舒适区的变化时, 情绪波动和抗拒的时期.他们经常为失去了旧的做事方式而悲伤.例如, 当人们重新组织成跨职能的团队时, 他们会想念以前的队友.类似地, 拥有全局数据模型的数据建模组将受到每个服务拥有自己的数据模型的想法的威胁.

  2. 中立区-介于新旧做事方式之间的中间阶段, 人们经常感到困惑.他们经常努力学习新的做事方法.

  3. 新的开始-最后一个阶段, 人们热情地接受新的做事方式, 并开始体验其中的好处.

本书描述了如何最好地管理产品化的每个阶段, 并增加成功实现变更的可能性.FTGO 无疑正遭受着 “单体的噩梦”, 需要迁移到微服务架构.它还必须更改其组织和开发流程.然而, FTGO 要想成功实现这一点, 就必须考虑到转型模式, 并考虑人们的情绪.

在下一章中, 您将了解软件架构的目标以及如何将应用程序分解为服务.

总结

  • 单体架构模式将应用程序构建为单个可部署单元.
  • 微服架构模式将系统分解为一组独立部署的服务, 每个服务都有自己的数据库.
  • 对于简单的应用程序, 单体架构是一个不错的选择, 但是对于大型复杂的应用程序, 微服务架构通常是一个更好的选择.
  • 微服务架构通过允许小型、自治的团队并行工作来加速软件开发的速度.
  • 微服务架构并不是万能的-它有很多明显的缺点, 包括复杂性.
  • 微服务架构模式语言是帮助您使用微服务架构构建应用程序的模式集合.它帮助您决定是否使用微服务架构, 如果选择微服务架构, 模式语言将帮助您有效地应用它.
  • 您需要的不仅仅是微服务架构来加速软件交付.成功的软件开发还需要 DevOps 和小型的、自治的团队.
  • 不要忘记采用微服务的人性化一面.为了成功地过渡到微服务架构, 您需要考虑员工的情绪.
Swagger2Markup bug-生成的 html 文档有问题当 ApiModel value 包含斜线
第2章-分解策略