微服务架构有毒,什么时候不使用微服务?

在过去的四年中,使用微服务来构建应用程序彷佛成了一种标准。大多数我所合做过的团队也对此表现出了不一样程度的兴趣。前端

微服务

微服务所承诺的弹性、高可用、低耦合、敏捷,以及可以解决单体架构带来的问题,这些都是它流行的主要缘由。程序员

可是近段时间来,对于微服务的一些保留意见和注意事项彷佛引发了人们的注意。数据库

在这篇文章中,我重点想讨论的是微服务的应用,它的缺点是什么,以及在什么状况下应该慎重考虑使用微服务架构。后端

什么是微服务安全

在工业级别,关于微服务基本特征的定义比较一致。服务器

这些特征能够总结以下:网络

  • 微服务是一种应用于组件设计(服务如何分组)和部署架构(服务如何部署和通讯)的模式。
  • 微服务适用于建立具备“必定功能复杂性”的分布式应用程序。
  • 各个服务必须小。
  • 各个服务按功能划分,实现关注点分离。
  • 各个服务保持自治和相互解耦,能够独立进行部署、版本控制和伸缩。
  • 各个服务之间经过轻量级 API 和异步通道相结合的方式进行通讯。
  • 各个服务拥有独立的状态,而且只能经过服务自己来对其进行访问。

一个典型的微服务实现模式以下图:架构

典型的微服务实现模式

图 1:典型的微服务实现模式框架

从上图中咱们能够看到:异步

  • 微服务中的每组服务有本身的前端(由一个 API 和一个可选的 UI 组件组成)、一个实现自身服务领域逻辑的域层以及独立的数据存储。
  • 前端复合。将全部前端组件(UI 组件或 API)组合成一致前端(复合 UI 或 API 网关)。
  • 一条事件总线,做为异步通讯的骨干。

主要问题是,对于那些适用采用微服务架构的用例,人们对微服务的见解趋于一致。

这就是为何我想采起相反的方法,并试图说明在哪些状况下,微服务可能不是最佳选择。

微服务的种种挑战

程序员知道种种优点,却对代价一无所知。

—— Rich Hickey (Clojure设计者)

实现微服务须要权衡利弊。因为本文的重点不是抨击微服务的缺陷,因此尽可能简明扼要。

1. 微服务很难被正确设计

这里有专门的一本书《Microservices AntiPatterns and Pitfalls》来记录它的缺陷。它须要很是很是多的迭代来完成一个使人满意的领域设计。

同时几个基本的和结构化问题没有直接的答案,每每须要调整和迭代,例如:如何水平切分关注点,如何共享数据以及以什么方式进行数据复制,如何管理报告,是否应该在服务中包括 UI 组件等。

2. 微服务引入复杂性

微服务引入了必定程度上的复杂性,这些复杂性已经被详细地记录下来,其中最著名的是“微服务——不是免费午饭”。

成倍的增长了 API 的数量

图 2:成倍的增长了 API 的数量

微服务带来的挑战包括:

  • 成倍的增长了 API 的数量。这使得变动代码变得困难,并引入了版本控制的复杂性,增长了服务功能性分解的难度。
  • 引入了网络延迟。在组合服务时须要在可伸缩性和响应时间增长之间作出权衡。
  • 鉴于 CAP 理论,处理横跨多个服务的事务很是复杂。和拥有单一数据库的单体架构不一样,这些事务一般不是由基础设施处理。
  • 调试分布式系统是复杂的(参见“微服务—不是免费的午饭”)。异步系统、服务间锁和竞态条件中产生的错误很难进行定位和排除。

尽管这些复杂性经过技术手段均可以克服,可是这须要技术人员付出额外的精力,不能让他们专一于实现那些更具价值的业务功能。

3. 微服务须要组织架构发生转变

微服务须要组织转向自治的、跨职能的团队。根据康威定律,这是相当重要的一步。

这意味着前端和后端开发人员、数据平台工程师、QA、产品经理和操做人员必须在一个团队中互相合做。

微服务须要组织架构发生转变

图 3:微服务须要组织架构发生转变

这样的组织运做起来很是平滑。这是由于大多数依赖关系都存在于团队内部,并且因为优先级是相同的,所以都可以快速解决。

4. 微服务须要过程和实践的改变

微服务须要过程和实践的改变。从偶尔发布几个大版本,到常常发布许多小版本。

从手动的资源供给,到基础设施即代码等自动化形式的资源供给。微服务架构的成功依赖于组织和流程改变的能力,而这每每是最难的。

图 4:微服务须要过程和实践的改变

5. 微服务须要深刻的技术栈

上面讨论的这些技术挑战意味着团队的技术集须要更加全面的拓展。

团队成员须要理解分布式系统、DevOps、基础架构即代码(IaC)、不一样类型的数据库、前端组件化和复合化、单元测试、全自动发布、迭代、小版本发布计划、测试工具、多版本管理等等。

何时不该该使用微服务

1. 应用程序规模过小

应用程序规模过小不足以证实微服务的合理性。固然,这个应用在将来可能会出现增加,直到整个领域添加到其中。

在这种状况下,当接近 RoI 阈值时,使用微服务。一样的道理也适用于那些小型团队。

代码行数与维护成本

图 5:代码行数与维护成本

2. 领域不明确

领域不明确或不肯定,使得领域模型不肯定。好比,当产品被描述为“门户”时、当你开始创业准备作一个应用时、当一个 CRM 系统要管理订单甚至是有邮递外送时,这种问题就会凸显。

在这种状况下,单体结构要灵活得多。在晚上,当你独自将 CRM 领域转换成逻辑解决方案的时候,你可能会惊讶于利用 IDE 来进行重构所带来的便利性以及单元测试套件带来的安全感。

3. 组织不能作出改变

组织不能改变以适应微服务。它仍然包含一个数据组、一个前端组、一个后端组等等。

康韦定律有利于将服务组成一个分层的微服务体系结构。你能够将图 1 与图 6 进行比较。

传统的组织形式来作微服务

图 6:传统的组织形式来作微服务

因为不一样的团队有不一样的优先级,致使跨团队的依赖关系环环相扣,形成延迟和冲突。

4. 缺少理解

团队缺少对微服务概念、DDD 或概念设计的经验和理解。虽然这可能算不上关键,但你应该仔细阅读相关文档并向有经验的人寻求建议。

一个体系结构设计不良的的产物每每是一个高耦合的分布式“单体架构”系统,以及随之而来的一切问题:网络的通讯性和延迟、复杂性、隐藏的依赖、部署时产生耦合等等。

咱们大多数人都喜欢学习新事物,但并不是全部人都喜欢,何况学习须要时间和精力。

有时候甚至要不断地犯错误,包括大错误,而后才可能学到一些东西。甚至在某些状况下须要废弃初始的版本,而后从头开始。这些都是潜在的成本,必需要在作出决定以前考虑清楚。

管理层也须要尽早适应重构,在某些极端状况下甚至要接受从头开始一个项目。

常常失败。早点失败。快速失败。拥抱失败是走向成功的一种方式。不要惧怕失败,要学会接受失败。

——Gary Burnison, CEO of Korn Ferry

接受失败不是一件容易的事情,由于沉没成本每每会错误指导你的下一步决策。

5. 其余

团队不成熟,技术栈不适应微服务或者人员流动率高。由于系统的无序性(熵)会随着时间的推移而不断增大,代码的维护性也会随着时间的推移而降低。

并且因为一个更复杂的系统更难维护,这可能会加重第 3.4 带来的问题。

困惑和压力每每会让人们退回到他们所熟悉的圈子。他们会“抄近路”把东西弄出来,或者走捷径来规避复杂性。

很快,这样产生的软件架构可能会被污染到技术组件、“核心”库、服务与服务之间的引用、编排器甚至“CSV 导入服务”,而后这些服务开始进入彼此的数据库。

接下来,有人会问“咱们应该如何编排部署以管理服务之间的依赖关系?”这无异因而软件版本的地狱,这种系统也被称为分布式“单体架构”。

组件依赖

图 7:组件依赖

运行和调试的复杂性可能会下降开发的总体效率。跨服务的 Bug 调查和日志分析是很是复杂的。

这会带来一个问题,那就是这些工做只能交给那些团队中技术经验更加丰富的成员。

可是这些成员的关注点应该是如何保持系统长期稳定运行,而不是救火。简而言之,在这种状况下,微服务不但没有带来优点,反而会让整个团队为消极结果买单。

应该如何抉择?

全部软件系统均可以分解为两个主要元素:策略和细节。策略元素包含全部业务规则和过程。策略是系统的真正价值所在。

而细节是令人类、其余系统和程序员可以与策略进行通讯的必备基础,可是这些细节都不会影响策略的行为。细节包括 IO 设备、数据库、Web 系统、服务器、框架、通讯协议等等。

架构师的目标是为系统建立一个外形。这个外形将策略看作是系统中最重要的元素,同时作到细节与策略无关。这使得有关细节的决策能够延迟和推后。

—— Robert C. Martin, Clean Architecture

若是您正在构建的应用程序有一个至关清晰的领域,将来会演进到一个至关的规模,在项目开始就会配置大型的团队,而且你对团队的技术有信心,你在分布式设计方面有一些经验或者至少有一些素养,同时又能得到管理层方面对于失败和学习的支持和容忍,那么微服务会是一个很好的选择。

可是要注意有时布局候微服务可能会拔苗助长。若是你所处的场景与前面的描述相相似,那么使用一些更简单的架构做为开始可能更加明智。

好比一个单体架构或者一个分层架构(自己可能包含一些专门的服务)。大部分微服务架构可以解决的问题,其余方案也能解决。

低耦合、可伸缩性和前瞻性的系统来自于精心设计的应用程序架构。这种架构每每具备明肯定义的边界和专门的数据存储。

微服务只能经过提供物理限制来知足这种场景。另外一种建立物理限制的方法是经过组件(DLL、JAR)。组件架构和部署架构的选择应该尽量的慎重。

容器和基础结构即代码(IaS)能够与微服务架构一块儿配合使用。事实上,它们每每更容易实现,由于网络是直接的,配置的数量不那么重要。同时容器也能让搭建和销毁环境变得更加容易,并能够加速开发环境的部署。

构建自动化和频繁发布能够经过增长关注点和减小在制品(Reduced WIP)、小批量(Small Batches)、原子化更改流(Atomic Change Flow)和减小协做来实现。

对于复杂的分布式系统,微服务无疑是一个很好的选择。但微服务并非惟一的选择,对于微服务的诉求每每会促令人们作出采用它们的决定,而忽略了它带来的种种问题。

一我的应该考虑各类选择,进而作出一个有意识的、有素养的、理性的选择。

感兴趣的能够本身来个人Java架构群,能够获取免费的学习资料,群号:855801563对Java技术,架构技术感兴趣的同窗,欢迎加群,一块儿学习,相互讨论。

相关文章
相关标签/搜索