在过去的四年中,使用微服务来构建应用程序彷佛成了一种标准。大多数我所合做过的团队也对此表现出了不一样程度的兴趣。前端
微服务所承诺的弹性、高可用、低耦合、敏捷,以及可以解决单体架构带来的问题,这些都是它流行的主要缘由。程序员
可是近段时间来,对于微服务的一些保留意见和注意事项彷佛引发了人们的注意。数据库
在这篇文章中,我重点想讨论的是微服务的应用,它的缺点是什么,以及在什么状况下应该慎重考虑使用微服务架构。后端
什么是微服务安全
在工业级别,关于微服务基本特征的定义比较一致。服务器
这些特征能够总结以下:网络
一个典型的微服务实现模式以下图:架构
图 1:典型的微服务实现模式框架
从上图中咱们能够看到:异步
主要问题是,对于那些适用采用微服务架构的用例,人们对微服务的见解趋于一致。
这就是为何我想采起相反的方法,并试图说明在哪些状况下,微服务可能不是最佳选择。
微服务的种种挑战
程序员知道种种优点,却对代价一无所知。 —— Rich Hickey (Clojure设计者) |
实现微服务须要权衡利弊。因为本文的重点不是抨击微服务的缺陷,因此尽可能简明扼要。
1. 微服务很难被正确设计
这里有专门的一本书《Microservices AntiPatterns and Pitfalls》来记录它的缺陷。它须要很是很是多的迭代来完成一个使人满意的领域设计。
同时几个基本的和结构化问题没有直接的答案,每每须要调整和迭代,例如:如何水平切分关注点,如何共享数据以及以什么方式进行数据复制,如何管理报告,是否应该在服务中包括 UI 组件等。
2. 微服务引入复杂性
微服务引入了必定程度上的复杂性,这些复杂性已经被详细地记录下来,其中最著名的是“微服务——不是免费午饭”。
图 2:成倍的增长了 API 的数量
微服务带来的挑战包括:
尽管这些复杂性经过技术手段均可以克服,可是这须要技术人员付出额外的精力,不能让他们专一于实现那些更具价值的业务功能。
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技术,架构技术感兴趣的同窗,欢迎加群,一块儿学习,相互讨论。