020 年,如果再讲什么是微服务,已经落伍了,毕竟微服务的成功故事已经开始在业界广为流传了。但是你真的需要微服务吗?
“真的需要微服务吗?”这个想法已经困扰我很长一段时间了,最近我与多位技术人进行了沟通,也许我们可以从解决一个有趣的问题,开始入手。“什么是微服务?我们的解决方案应该遵循这种架构吗?”
问题的第一部分很容易回答,而第二部分则需要高屋建瓴、谨慎对待。在沟通之后,我发现有个事情是大家都达成共识的:
受益者会把微服务架构应用到他们即将推出的产品中,因为他们需要立刻出效果来背书。
参与讨论的人里有大量的非技术人员。当谈话越来越“技术化”,与决策也就越不相关了。
长时间的中断以及提不出问题,这也就意味着不熟悉 Web 服务,更不用说微服务了。
我不会因为他们不知道 Web 服务是做什么,或者微服务如何对他们有利或有害而谴责他们。毕竟,他们在我不擅长的工作上要出色得多。他们打算加入微服务的行列,虽然还不甚了解其影响!
我第一次听到“微服务”这个词是在 2013 年,当时是在 YouTube 上一个解释 Netflix 服务架构的视频中。当时我觉得这让人无法理解,所以毫不犹豫地跳过了。毕竟,这对于当时想方设法要进入设计原理领域的人来说太难了。但是,当新的项目提案宣布采用微服务时,它很快就让我着迷了。这个项目的设计很吸引人,它仍然是我接触过的最好的代码库之一。
说实话,模块化设计的广泛可能性可以减少负担。而我只是一个无知的开发人员,对 DevOps 避之唯恐不及,它带来了额外的复杂性。如果快进 5 年,我可能正在和一群全新的人开发一个全新的产品。我的日子里充斥着由设计糟糕的微服务和业余的 DevOps 战术所引发的问题。虽然问题很快就解决了,但我看到了微服务的脆弱性。这也让我根据自己的经验来审视整个架构。虽然已经太晚了,但晚做总比不做好!
看到了微服务的正反两面影响,我开始告诫自己要多看看反面影响,在实践微服务之前,先问自己以下几个问题。
1应用程序已经大到足以拆分为微服务吗?
必须承认,并不是所有的应用程序都大到可以分解成更小的服务。顾名思义,微服务是一组更小的、具有特定用途的服务。在理想的情况下,我们希望每个服务本身都是一个完整的应用程序。
这是微服务和单体服务之间“每行代码成本”的一个比较。由于微服务在人力和计算成本方面的最小资源限制,即使在比较轻量化的形式下,也会产生较高的成本。成本是每个人都关心的问题,如果不是,你可能根本就不该做决定。
当然,你的代码库将来会增长,它也可能会增加一个新的领域。但你应该永远记住:一个设计良好的代码库随时都可以切换到微服务,所以在接近阈值时实践微服务,是性价比最高的。
2你真的需要扩展应用程序的各个组件吗?
假设你的产品负责人带着一个 HRMS 应用程序的想法来找你,想要通过它管理一个上万人规模的组织。你可能立马就有了解决方案:微服务架构。
当然,这是一个极端的例子,但是你明白我的意思!!
使用微服务架构的一个主要优点是单个组件非常容易扩展。我们可能会发现大量的应用程序需要组件可以单独扩展,但是你的应用程序真的需要这样做吗?
3你是否有跨服务的事务?
现在,这可能是最困难的战略选择之一。跨多个服务的事务是整个架构的负担。解决跨服务的事务意味着,服务之间的互锁、一系列难以跟踪的死锁以及可能破坏服务健康的竞争条件;有时甚至是工程师的健康。
根据定义,REST 服务是无状态的。它们不应该参与超出单个服务的事务。在高性能的世界里,两段提交 [2PC] 是一个不必要的麻烦。而 SAGA 模式只会增加另一层意料之外的复杂性。
微服务引入了最终一致性问题,因为它们坚持分布式的数据管理。在单体架构中,你可以在单个事务中一次更新一堆东西。微服务需要多个资源来更新,不赞成采用分布式事务(理由很充分)。所以现在,开发人员需要注意一致性问题,并在写任何代码之前,弄清楚如何检测不同步。
——Martin Fowler
有可能跨服务进行事务处理吗?
是的,当然。
但是,是否值得在整个无状态的服务中实现一系列操作呢?
恐怕不行!!!
4服务之间是否需要频繁通信?
在传统的单体服务中,每个微服务实例表现为系统内的模块。模块之间的通信在内存中,延迟接近于零。微服务的引入意味着,通信已经从内存事务变成了网络指令。
有许多可靠的解决方案可供我们选择,但它们都以延迟为代价。从内存事务转变为基于网络的通信将把延迟单位从纳秒变为微秒。假设有三个不同的服务通过网络相互通信。假设每个服务调用需要 100 毫秒 [在有负载的情况下这不可能],那么仅在网络上就需要花费 300 毫秒。
有些应用程序生来就与组件和服务紧密集成。在处理实时数据的应用程序中,增加的通信层可能会导致灾难性的结果。想象一下,当你穿着外科手术服或者在控制航空交通时,通讯出现了延迟!
5其他值得思考的问题
增加复杂性——当然,复杂性无法量化,只能相对地进行比较。虽然微服务最初的设计目的是通过将应用程序拆分成更小的块来降低复杂性,但是架构本身在部署和维护方面很复杂。
分布式的成本——微服务是具有分子特性的分布式系统。但分布式也有代价。单体服务将部署在大型 VM 或首选容器上。但是,对于微服务,需要使用多个 VM 或容器(在理想情况下)单独部署每个服务。当然,它们可能很小,你可以自己算算。请记住,我甚至还没有讨论过服务编排和维护所涉及的成本。
Devops 的采用——取决于你从哪个角度看,这可能有益,也可能有害。DevOps 是一种被广泛接受的、经过验证的运营解决方案。但是,如果你属于一个较小的组织,那么构建一个 DevOps 团队所造成的伤害可能会多于带来的进步。但是,有一件事是肯定的,那就是如果没有专门的 DevOps 团队,你就无法维护和监控微服务。
紧密集成——有些应用程序天生就是紧耦合的。将它们解耦以“适应”架构将是灾难性的。
缺乏经验——缺乏经验对于任何问题都至关重要,不仅仅局限于 SOA。但当涉及到微服务时,由于它所持有的抽象定义,它可能会加剧损害。如果你的微服务部署通过部署规则将你推到了次要位置,或者当某个依赖项服务宕机时崩溃,那就太晚了。
端到端测试——一个典型的单体应用程序让你可以几乎同时启动和运行测试。而如果没有可行的编排,那么具有相互依赖关系的多个服务将使测试延期。
混乱的数据契约——在团队中制定和使用数据契约与在团队之间共享数据契约有很大的不同。当你使用微服务时,你的团队可能不在同一个区域;更不用说他们都使用相同的编程语言。为了特殊需要而制定数据契约需要你付出时间和空间成本。
遗留代码库——老实说,对于我们大多数人来说,处理遗留代码库是一项日常工作。它是大多数组织的主要收入来源。日新月异的技术进步让我们保持领先。与此同时,它也将我们与遗留代码库隔离开来。“你确定你刚刚开发的 RabbitMQ 框架适合于托管在 IBM AIX 服务器上的遗留应用程序吗?”
调试缺陷——每个服务都有自己的一组日志文件要查看。更多的服务等于更多的日志文件。
6小结
我是来告诉你“不要使用微服务”的吗?
绝对不是!!!
事实上,微服务一直以来都有不太好的名声,但它们解决了我们都认为无法解决的问题。Netflix 公司采用微服务的故事启发了许多人。而且,这个名单并不仅仅局限于 Netflix,Uber、SoundCloud 和巨头亚马逊都是我们可以立马找到的微服务实践案例。而且,成功的故事不仅限于消费者应用程序,我曾与美国医疗保健巨头合作过,我每次看到他们的源码,都会被其设计深深吸引。
如果你 5 年前就跟风了微服务,我不会谴责你的轻信。时代不同了,我们现在所能做的就是诚实地面对它。现在是 2020 年了,我们受的伤已经够多了,周围有太多粗暴的处理了。无端地引入微服务架构,只会将糟糕的代码变成糟糕的基础设施。
我喜欢充满热情的程序员。我曾经是,现在仍然是。他们热爱自己的工作,超越期望地解决问题。但在做决定时不能这样,这可能会让你和公司都损失一大笔钱。很抱歉让你失望了。微服务不应该是默认的应用程序架构。它们不是你要找的银弹。遵循 KISS 和 YAGNI 原则,让自己保持稳定。
作为一名技术倡导者和爱好者,你有权拥有自己的偏好。然而,让你脱颖而出的是,当选项是“正确的选择”和“你最喜欢的选择”时,你要有做出切合实际选择的能力。