给还在犹豫选择的你,微服务架构与整体架构的各自优势

微服务目前是软件开发的一种新趋势,我们所熟知的谷歌、亚马逊,Netflix等都在使用微服务架构。 但微服务架构与整体架构的区别在哪?微服务架构又需要注意哪些运营成本?数人云今天给大家带来的文章将阐述这几个问题。

本文我们将讨论微服务架构与整体架构的区别,为了清晰起见,本文假设:在此上下文中微服务的定义是需要服务之间的物理分离。

微服务加固被认为是“恰当”的即:

在没有/最小的RPC通信请求/服务之间的应答 每个服务都封装了持久性 每个服务都表示一个功能,没有“数据库服务” 如果其中任何一个假设不存在,则结论可能就是无效的。 Martin Fowler在分享中强调了近年来“技术趋势”的一些方面:备受瞩目的是关于“微服务”的架构模型,属于的正是定义,以及通过对需求的仔细分析和项目的情况所产生的问题。

当然,问题不在于用何种架构模式,而是在于为特定的场景提供解决方案,及应用时缺少匹配的需求。

技术推动了微服务的快速落地,近年来出现的新兴技术往往都已经被微服务架构所采纳,比如:

  • 容器化(Docker,Kubernetes)
  • 函数式编程
  • 反应性编程
  • CQRS
  • Event Sourcing
  • Serverless architectures and BaaS
  • 多语言编程
  • 深度学习及机器学习

微服务的目标与特性

重要的是,当涉及到估值时,对于需要解决的目标和问题,必须非常清楚地认识到微服务所带来的转变,这里简短地回忆一下:

快速构建于组件级,项目的可管理性。 非常清晰和严格的界限。 部署独立性和服务质量。 多语言编程/持久性的可能性。

运营成本

其实我们往往低估了每个微服务需要的运营成本: 交付的政策。 - 自动生成,包含重复/包含/生成的脚本。 - 一个交付/部署管道,使用上面提到的脚本。 - 监控/健康检查/自愈。 - 基于特定参数的伸缩策略。 - 一个通用依赖项的定义。 - 一个版本控制存储库。 - 故障管理。 - 最好是集中的日志。

- 对每个服务更具体的需求。

尽管像Docker和Jenkins的DSLs这样的技术在使上述观点可以复制的过程中起到了很大的作用,但运营成本与相比是不可能的:

更多的管道需要更多的硬件和计算资源。 为了验证交互,需要等待多个通道。 复制/看到Bug修复也是一样的。 这些观点受到边界问题的影响(见下文)。

另外,为了不重复支持性和可操作性的方面,需要提取公共库,并对所有公共代码进行相同的处理。

这将从项目的0点增加解决方案的复杂性,生成通道之间的依赖关系,并生成私有存储库的需求。

标准化

从自动化/系统标准化的角度来看,降低运营成本需要一个较强的文化。这通常不是在一个项目中生成的。

可以看到的是,尽管付出了努力,许多微服务体系结构并没有得到它们所需要的操作基础设施支持。

与其他方面一样,如果向微服务迁移是渐进的,那么标准化工作更有效率,而操作方面自然也会从服务的提取中“浮现出来”。

反馈循环

正如上面所提到的,微服务系统仍然是一个复杂的系统,它不仅仅是简单的部分。

假设已经支付了操作和标准化成本,并且微服务的边界相对稳定。

在开发过程中,反馈周期可以与组件级的整体系统相媲美,但很重要的一点是,要清楚的是,在组件级别的反馈和组件组成的反馈之间要有一个平衡,这将会更加复杂。

对于系统级的任何问题,必须在消息传递中寻找它,调试困难。如果出现性能问题,这个问题会变得更加严重。消息通常是无类型的,将问题从编译时移到运行时。解决一个问题,被测试,可能需要重新编译/重建的一个或多个组件。

交互的复杂性

如果复杂性不在组件中,那么它就必然在组件之间的交互中。这就是Martin Fowler所说的“智能服务,Dumb Pipes”的原则。“当替换/更新一个微服务的实例时,最小化依赖关系。”

更为普遍的是,启发式对封装的概念再次作出响应:“智能”越分散,系统就越模块化。

尽管对使用支持异步通信(Message Broker)的技术提供了无条件的支持,但不能否认,两行代码的调试会话和某种类型的总线之间的交互的成本是不同的。

整体架构

一个微服务的重新定义(甚至重写)的隐藏成本远远高于代码库的正常变化,其中包括:

业务成本的应用。 在不同生命周期的子系统中的镜像/数据迁移。 协议的重新定义,公共API的不稳定性。 可测试性仅在集成级别上。

问题在于,正如埃里克·埃文斯(Eric Evans)在《DDD Europe》的最后一版中指出的那样,边界的定义是非常复杂的,特别是在一个系统的进化开始的时候,它就像一个“有弹性的”。 唯一确定的是,第一个设计对于项目的最新需求来说是错误的。此外,这个概念并不新鲜:它是敏捷方法论的基石。

从一开始使用微服务方法可以保证在项目过程中必须更改一个或多个(可能更多)的边界。

这意味着“微服务溢价”将不可避免地得到回报 每一个变化的边界,作为改变的代价(见上文)。

当决定最小化边界更改时,在服务之间的“会话”的倍增级别上,造成了可维护性甚至性能/可伸缩性的问题。

我们认为服务之间交互的数量和质量是面向服务架构的焦点,如果可以用“Many Small Monoliths”来代替“微服务”。

微服务的愿景

具有整体架构的服务质量。

“可扩展性”在这种情况下限制通用“可扩展性”不依赖铁板一块分布与微服务但更多其他属性的更一般的人物,如缺乏共享状态的服务或数据的分布。

可以想象一种情况,即发展是一个单一的Codebase(“monolith”),但分布是多样化的。

因此,整个Monolith将部署在分发服务“用户”的机器上,但只有用户API被发布。这允许部署相同的Monolith的不同版本。它将最小化物理分离的成本,但实现了部署的独立性,这是从微服务体系结构中寻求的特性之一。

在没有特别的“交流”架构的情况下,这种模式在单一和微服务之间的过渡可能是可行的。甚至可以在需要迫切需要组件级可伸缩性的时候摆脱“麻烦”。

为什么要用微服务

如果有那么多问题,为什么要用微服务呢?

本文不是“反对”微服务架构。而是试着提高对所涉及的成本的认识,做出一个合理的决定。试图强调的问题是,最初给微服务架构的简单性的感知,是错误的和扭曲的。

很容易认为一个从0开始的项目,缩小规模,是通过扩展一个系统来开始开发是最简单的事情。问题是,在那一刻,要忘记所有隐藏的成本,因为微服务仍然是整体的一部分。

微服务的优势

更容易理解和维护:微服务通过将应用程序分解为一组易于管理的服务,从而解决复杂性问题,这些服务的开发速度要快得多,而且易于理解和维护。

采用新技术:每个服务都是独立的,所以选择编程语言更依赖于实际的问题,而不是在项目开始时做出的选择。

故障隔离:微服务改善故障隔离,使应用程序在很大程度上不受单个服务的故障影响。

可伸缩和成本效益:随着需求的增加,扩展服务成本非常高。例如,一个应用程序由两个模块组成——Auth和Product。由于微服务体系结构,用户可以扩展任意一个服务(比如Product,而不影响Auth服务)。

此外,由于AWS像汽车可伸缩服务一样,在对特定服务的需求增加的情况下,微服务是非常简单且经济的。

整体架构的优势

复杂性:在基于微服务的应用程序中,很难实现通过各种服务传播的更改。在整体应用程序中,更新相应的模块,添加更改并一次性部署它们,相对简单。

可部署性:对于整体应用程序,所有更改都可以通过单个部署进行推送。相反,微服务应用程序通常使用各种服务。每个服务都需要单独配置、部署、缩放和监视,这增加了额外的开销。

测试:如果一个功能依赖于各种服务,那么测试它就变得非常复杂。在整体应用程序中,测试相对容易。

处理失败:在一个整体应用程序中,组件内部连接在一起,因此处理失败要容易得多,因为每件事都是单个应用程序的一部分。在微服务应用程序中,开发人员需要处理服务之间的逻辑、互通信和故障,这最终会增加复杂性。

结论

基于微服务的体系结构提供了许多处理复杂系统的方法,但也有其自身的挑战和复杂性。以微服务为基础的架构非常有用,如果应用程序真的很大,很复杂,而且做了很多不同的事情。

尽管没有适合所有情况的解决方案,但是,对于简单的应用程序,整体架构是更好的方法。