逃离单体地狱

Posted 树懒很努力

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了逃离单体地狱相关的知识,希望对你有一定的参考价值。

文章目录

单体架构的好处

应用程序相对较小,单体架构具有以下好处:

  • 应用的开发很简单:IDE和其他开发工具只需要构建这一个单独的应用程序。
  • 易于对应用程序进行大规模的更改:可以更改代码和数据库模式,然后构建和部署。
  • 测试相对简单直观:开发者只需要写几个端到端的测试,启动应用程序,调用 REST API。
  • 部署简单明了:开发者唯一需要做的,就是把 WAR 文件复制到安装了 Tomcat 的服务器上。
  • 横向扩展不费吹灰之力:项目可以运行多个实例,由一个负载均衡器进行调度。

但是,随着时间的推移,开发、测试、部署和扩展都会变得更加困难。

什么是单体地狱

曾经小巧的、简单的、由一个小团队开发维护应用程序,经过10年的成长,已经演变成一个由大团队开发的巨无霸单体应用程序。同样,小型开发团队现在已成为多个所谓 Scrum 敏捷团队,每个团队都在特定的功能领域工作。作为架构扩展的结果,项目已经陷入了单体地狱,开发变得缓慢和痛苦,敏捷开发和部署已经不可能,我们来看看这是为什么。

过度的复杂性会吓退开发者

  • 这个系统本身过于庞大和复杂,以至于任何一个开发者都很难理解它的全部。因此,修复软件中的问题和正确地实现新功能就变得困难且耗时,各种交付截止时间都可能被错过。
  • 更糟糕的是,这种极度的复杂性正在形成一个恶性循环:由于代码库太难于理解,因此开发人员在更改时更容易出错,每一次更改都会让代码库变得更复杂、更难懂。项目正在一步一步地成为一个巨大的、令人费解的"脏泥球"。

开发速度缓慢

  • 这个巨大的项目把开发人员的 IDE 工具搞得很慢,构建一次应用需要很长时间,更要命的是,因为应用太大,每启动一次都需要很长的时间。因此,从编辑到构建、运行再到测试这个周期花费的时间越来越长,这严重地影响了团队的工作效率。

从代码提交到实际部署的周期很长,而且容易出问题

  • 众多开发人员都向同一个代码库提交代码更改,这常常使得这个代码库的构建结果处于无法交付的状态。尝试采用功能分支来解决这个问题时,带来的是漫长且痛苦的合并过程。
  • 运行测试也需要很长时间。
  • 程序更改部署到生产环境的时间也变得更长,整个流程令人发狂。

难以扩展

  • 团队在对应用进行横向扩展时也遇到了挑战。因为在有些情况下,应用的不同模块对资源的需求是相互冲突的。

交付可靠的单体应用是一项挑战

  • 单体应用的另一个问题是缺乏可靠性,这个问题导致了频繁的系统故障和宕机。系统不可靠的一个原因是应用程序体积庞大而无法进行全面和彻底的测试,缺乏可靠的测试意味着代码中的错误会进入生产环境。更糟糕的是,该应用程序缺乏故障隔离,因为所有模块都在同一个进程中运行。每隔一段时间,在一个模块中的代码错误,例如内存泄漏,将会导致应用程序的所有实例都崩溃。

需要长期依赖某个可能已经过时的技术栈

  • 项目所经历的单体地狱的最终表现,也体现在团队必须长期使用一套相同的技术栈方面。单体架构使得采用新的框架和编程语言变得极其困难。在单体应用上采用新技术或者尝试新技术都是极其昂贵和高风险的,因为这个应用必须被彻底重写。结果就是,开发者被困在了他们一开始选择的这个技术之内。有时候这也就意味着,团队必须维护一个正在被废弃或过时的技术所开发的应用程序。
  • Spring 框架本身保持着持续的演进和更新,同时维持着向后的兼容性。所以理论上来说项目可以随着升级。不幸的是,应用程序使用了与 Spring 新版本不兼容的框架,开发团队也挤不出时间来更新这些旧框架。久而久之,这个应用的绝大部分都被卷入了这个已经过时的框架。更不幸的是,开发人员一直想尝试类似 GoLang 和 Node.js 这样的非 JVM 类编程语言,然而在单体架构之下,这是做不到的。

扩展立方体和服务

《The Art of Scalability》这本书描述了非常有用的三维可扩展模型:扩展立方体

  • X轴扩展:在多个实例之间实现请求的负载均衡。均衡器之后运行应用程序的多个实例,负载均衡器在N个相同的实例之间分配请求,这是提高应用程序吞吐量和可用性的好方法。
  • Z轴扩展:根据请求的属性路由请求。Z轴扩展也需要运行单体应用程序的多个实例,但不同于X轴扩展,每个实例仅负责数据的一个子集。置于前端的路由器使用请求中的特定属性将请求路由到适当的实例。例如,应用程序可能会使用请求中包含的 userId 来路由请求。
  • Y轴扩展:根据功能把应用拆分为服务。X轴和Z轴扩展有效地提升了应用的吞吐量和可用性,然而这两种方式都没有解决日益增长的开发问题和应用复杂性。为了解决这些问题,我们需要采用Y轴扩展,也就是功能性分解。

微服务架构和 SOA 的异同

某些针对微服务架构的批评声称它其实就是 SOA,并没有新鲜的内容。在某些层面,它们的确有些相似。SOA 和微服务架构都是特定的架构风格,它们都以一系列服务的方式来把一个系统组织在一起。但如果深入研究,会发现微服务和 SOA 之间巨大的差异,如下图:

项目SOA微服务
服务间通信智能管道,例如 Enterprise Service Bus(ESB),往往采用重量级协议,例如 SOAP 或其他 WS* 标准使用哑管道,例如消息代理,或服务间通信者服务之间点对点通信,使用例如 REST 或 gRPC 类的轻量级协议
数据管理全局数据模型并共享数据库每个服务都有自己的数据模型和数据库
典型服务的规模较大的单体应用较小的服务

微服务架构的好处

使大型的复杂应用程序可以持续交付和持续部署,并且实现团队的自治

微服务架构通过以下三种方式实现持续交付和持续部署∶

  • 它拥有持续交付和持续部署所需要的可测试性。自动化测试是持续交付和持续部署的一个重要环节。因为每一个服务都相对较小,编写和执行自动化测试变得很容易。因此,应用程序的 bug 也就更少。
  • 它拥有持续交付和持续部署所需要的可部署性。每个服务都可以独立于其他服务进行部署。如果负责服务的开发人员需要部署对该服务的更改,他们不需要与其他开发人员协调就可以进行。因此,将更改频繁部署到生产中要容易得多。
  • 它使开发团队能够自主且松散耦合。你可以将工程组织构建为一个小型团队的集合。每个团队全权负责一个或多个相关服务的开发和部署。

每个服务都相对较小并容易维护

微服务架构的另一个好处在于每个服务都比较小,开发者更容易理解服务中的代码。较小规模的代码库不会把 IDE 等开发工具拖慢,这样可以提升开发者的工作效率,服务的启动速度也比大型的单体应用快得多。

服务可以独立扩展。

服务可以独立扩展,不论是采用 X 轴扩展的实例克隆,还是 Z 轴扩展的流量分区方式。此外,每个服务都可以部署在适合它们需求的硬件之上。这跟使用单体架构的部署和硬件选择是迥然不同的:单体应用中组件对硬件的需求不同(例如有些组件是 CPU 运算密集型的.,有些可能需要更多的内存空间),但是这些组件仍旧必须被部署在一起。

更容易实验和采纳新的技术。

微服务架构可以消除对某项技术栈的长期依赖。原则上,当开发一个新的服务,开发者可以选择适用于这个服务的任何语言和框架。当然,很多公司对此往往有各种限制和规范,但重要的是团队有了选择的权利,而不是被之前选定的技术绑架。

更好的容错性。

微服务架构也可以实现更好的故障隔离。例如,某个服务中的内存泄漏不会影响其他服务,其他服务仍旧可以正常地响应请求。相比之下,单体架构中的一个故障组件往往会拖垮整个系统。

微服务架构的弊端

没有一项技术可以被称为"银弹",微服务架构也存在一些显著的弊端和问题。实际上接下来的大部分文章都是解决这些由微服务架构带来的弊端和问题的,不必被这些弊端和问题吓倒,在后续章节把它们逐一解决。微服务架构的主要弊端和问题如下∶

服务的拆分和定义是一项挑战

采用微服务架构首当其冲的问题,就是根本没有一个具体的、良好定义的算法可以完成服务的拆分工作。与软件开发一样,服务的拆分和定义更像是一门艺术。更糟糕的是,如果对系统的服务拆分出现了偏差,你很有可能会构建出一个分布式的单体应用:一个包含了一大堆互相之间紧耦合的服务,却又必须部署在一起的所谓分布式系统。这将会把单体架构和微服务架构两者的弊端集于一身。

分布式系统带来的各种复杂性

使用微服务架构的另一个问题是开发人员必须处理创建分布式系统的额外复杂性。

  • 服务必须使用进程间通信机制,这比简单的方法调用更复杂。
  • 必须设计服务来处理局部故障,并处理远程服务不可用或出现高延迟的各种情况。
  • 每个服务都有自己的数据库,这使得实现跨服务的事务和查询成为一项挑战。
    - 基于微服务的应用程序必须使用所谓的 Saga 来维护服务之间的数据一致性。
    - 基于微服务的应用程序无法使用简单查询从多个服务中检索数据。相反,它必须使用 API 组合或 CORS视图实现查询。
  • 编写包含多项服务在内的自动化测试也是很令人头疼的工作。

当部署跨越多个服务的功能时需要谨慎地协调更多开发团队

使用微服务架构的另外一项挑战在于当部署跨越多个服务的功能时需要谨慎地协调更多开发团队。必须制定一个发布计划,把服务按照依赖关系进行排序,这跟单体架构下批量部署多个组件的方式截然不同。

开发者需要思考到底应该在应用的什么阶段使用微服务架构

使用微服务架构的另一个问题是决定在应用程序生命周期的哪个阶段开始使用这种架构。在开发应用程序的第一个版本时,你通常不会遇到需要微服务架构才能解决的问题。此外,使用精心设计的分布式架构将减缓开发速度,这对初创公司来说可能是得不偿失的,其中最大的问题通常是在快速发展业务模型和维护一个优雅的应用架构之间的取舍。微服务架构使得项目开始阶段的快速迭代变得非常困难。初创公司几乎肯定应该从单体的应用程序开始。


《微服务架构设计模式》第一章 逃离单体地狱

以上是关于逃离单体地狱的主要内容,如果未能解决你的问题,请参考以下文章

在另一个find(...)的回调中查找,如何逃离回调地狱?

微服务架构设计模式

“逃离”单体,GitHub的微服务架构实践

“逃离”单体,GitHub的微服务架构实践

《微服务架构设计模式》读书笔记

《微服务架构设计模式》读书笔记