你不需要微服务? - itnext


亮点:微服务并不能确保良好的模块化:如果您使用微服务足够多,您可能会构建或借用一些不错的工具来简化服务之间的通信。但是,如果你不小心,你最终会得到一个紧密耦合的微服务式单体,每个函数都有大量的 HTTP 调用和要处理的版本控制。

在 Web 软件架构方面,微服务非常流行。微服务架构有大量高知名度的实践者和支持者。
Facebook、优步、Groupon、Klarna、亚马逊、Netflix、eBay、康卡斯特等。
你可能不是这些公司。也就是说,你的团队可能看起来不像这些公司的团队。您可能不会面临与他们相同的问题。
(banq注:上下文确实是不同,但是不能过于强调特殊性而忽略普遍性,这个普遍性就是,每个程序员都有认知天花板,能力限制,不可能让一个程序员照顾太多代码,加班加点也不行,认知天花板需要量的积累才能质的突破)

微服务是个稻草人
微服务据称有很多好处,问题并不在于微服务没有提供这些好处,而是这些好处并不完全是由微服务来解决的。
大多数好处也可以在某种程度上通过单体实现。

当有人提出微服务架构的优点时,其含义是,为了解决这些问题,你必须采用微服务模型。
现实情况是,微服务会让你买单额外的一层和一定程度的灵活性来解决这些问题。

关键字是买单成本。

微服务并不是免费的。它们的构建和维护成本是众所周知的。
如果你需要这种额外的灵活性?很好。也许这种额外的成本会得到回报,这时微服务是一个很好的选择,也许你应该认真考虑它们。
如果你不这样认为?那么,你刚刚过度设计了你的堆栈,并且严重阻碍了你的团队向客户提供价值的能力。

让我们看看微服务最常提出的一些好处,并考虑我们如何用单体来减轻这些担忧:

一、可扩展性
运行微服务意味着你的应用程序的每个功能都在自己的资源上运行,可以相互独立地进行扩展。当然,这将使你对分配给每个功能的资源数量和类型有高度的控制。

但是,你真的需要这种程度的控制吗?

  • 你的应用程序的不同功能是否经历了不同程度的负载?
  • 它们是否倾向于以不同的速度扩展?
  • 它们在CPU、内存、存储和GPU方面是否有不同的要求?

对于很多团队来说,通过简单地增加可用的Pod的大小或数量来弥补这些资源方面的差异是比较便宜的。大多数时候,不对基础设施进行优化,使其达到最佳状态,是比较划算的。

1、修复你的单体
解决你的单体的性能问题和瓶颈可能比过渡到一个新的架构模式更容易。这方面的细节是针对堆栈的,但你不需要走得太远,就能找到如何收紧你的应用的想法。

2、将流量导向独立可扩展的集群
如果你有一个以上的服务器,你就要在它前面运行某种负载平衡器。你可以使用这个负载平衡器的配置,将流量路由到你的应用实例的独立可扩展集群。
你也可以把异步任务拉到有独立可扩展队列的后台作业中。确保你有足够的队列,让你对盒子数量的控制有足够的颗粒度,以保持你的队列减少和你的基础设施成本合理。

3、故障隔离
适当设计的微服务架构的一大好处是,你的应用程序的一个单一功能发生故障时,不会使其他功能也发生故障。

4、将流量路由到隔离的集群
将不同类型的流量路由到集群以实现规模化的想法也可以提供对故障的保护措施。
想一想你的大部分历史故障来自哪里。这将给你一个指示,说明如何最好地路由你的流量。如果你与 "嘈杂的邻居 "作斗争,你可能想根据账户ID进行路由。如果你有一个脆弱但次要的功能,习惯于使所有的东西瘫痪,也许可以把它的端点路由到它自己的应用程序实例集群。如果你有问题的后台工作,把它们放在自己的队列中,不影响其他工作。

5、自动测试
预防胜于治疗。如果你能预防或至少降低故障的数量,你就不必为隔离它们而担心。
培育一种健康的测试文化,以确保对你所运送的东西的质量有信心是关键。不仅是在其可靠地提供所需功能的能力方面。而且,它在生产中的负载能力也是如此。

6、编程语言和技术的不可知性
引入新的语言和技术而不把它们作为独立的服务,这样的选择并不多。
在大多数情况下,这更像是一个特点而不是一个错误。在选择语言和技术时,给工程师太多的选择,会导致技术栈的分散和过于复杂。

7、倾向于单体带来的简单性和一致性
如果你确实对针对特定功能的专业语言有特定领域的要求,你可能要考虑单独的服务。你需要权衡任何额外技术带来的好处和维护它的额外成本。


二、微服务并不能确保良好的模块化
尽管微服务强制执行模块化,但并不能保证它是良好的模块化。如果在设计上没有充分考虑,微服务很容易成为一个紧密耦合的 "分布式单体"。
如果你不能成功地将一个单体模块化,你将很难构建一个成功的微服务架构。

微服务迫使人们进行模块化,但它们使做好模块化变得更加困难。

1、可独立部署
在你可能做出的许多改变中,能够独立部署服务是一种好处。但对于你的面包和黄油,你的日常变化,这可能会成为一个棘手的瓶颈。
在不同的服务中协调若干部署的要求会使快速发布功能变得更加困难和复杂。

2、分解复杂的变化
在单体中,仍有可能将复杂的、有风险的变化分解成独立的部署。一个常见的例子是使迁移与他们自己的PR和他们自己的部署向前和向后兼容。
这显然为交付功能增加了一定程度的复杂性,与微服务的方式相同。你不会想轻率地使用它。但它确实提供了微服务的一些好处,而不是被迫为每一个变化而利用它。

3、依赖性管理
微服务允许你对每个服务有单独的依赖性,但你真的需要它们吗?
在一个大型单体中管理依赖关系已经很困难了。把它分割成几个小的列表,可以简化对每个列表的管理,但对整个系统来说,却会使其复杂化。
在单体中,你迟早会遇到 "依赖性地狱",在两个依赖性之间出现冲突。微服务并不能确保你避免这种情况,但它们应该减少出现问题的可能性。

4、紧跟依赖性更新
让你的依赖关系保持最新显然是可取的。但在现实世界中,通常情况下,有些东西是允许滑动的。
保持在可用版本的边缘,实际上可能会加剧这个问题,因为一个依赖关系比其他相关的依赖关系发展得更快。但是,"保持领先 "并不意味着在所有可能的情况下都要更新到最新的版本。

三、更简单、更容易理解的代码
这个好处充其量是虚伪的,更糟糕的是,是一个赤裸裸的谎言。
每个服务都更简单,更容易理解。当然,系统作为一个整体要复杂得多,也更难理解。
你并没有消除复杂性;你只是增加了它,然后把它移植到其他地方。
(banq注:这取决于上下文,如果你站在上帝视角,试图理解一个超过你能力以外的代码是不可能的,微服务让你只能理解你能力以内的代码,微服务确实没有消除复杂性,只是将其迁移到其他地方,而那些地方不需要你照顾,由其他团队照顾,你只关心你力所能及的范围,你无需操单体整体的心,如同你饭都吃不饱,还操心国家大事一样,国家这个整体不是你一个人能力能达到的)

四、模块化你的单体
我们不需要为了让我们的代码更容易被工程师理解而引入网络边界和孤立的流程。
一个被分解成具有明确定义和有限关注点的模块的单体,要比一个被分解成独立服务的系统更容易,甚至更容易理解。
(banq注:单体被分解为多个模块,这句话还是站在上帝视角俯视的,你对整个单体都不了解,都没有能力理解,你如何去划分切分?你对一个不了解的事物进行解构,这本身就是认知上的误区)

我们正感受到我们的单体的痛苦
如果你的单体遇到了问题,那可能是因为你的单体有问题,而不是因为它是一个单体整体。

有可能你的单体是代码质量、工具化和模块化的一个闪亮的灯塔,那么你可能是时候开始考虑微服务了,但如果不是这样,你首先需要改进你的单体。
(banq注:假设一个团队能变成上帝,对整个公司的单体全部承包了,而且能做到如此高的代码质量,但是软件质量不只是部署前的代码质量,而是代码随着维护时间不断扩展的质量,代码质量是否能随着多次修改以后还能易于扩展呢?软件是一个编写 测试 部署的动态循环过程,单体模块化并不能确保部署的独立性,一个团队修改一个模块以后,无法像微服务那样单独部署,客户要求的新价值就无法得到满足,这种代码质量再高也是一种自以为上帝的自大)

构建软件是困难的。组织大型复杂的系统,其中有很多随时间演变的移动部件,是非常困难的。

我把我的手举起来,我建立的单体都是一团糟。
我不是来评判任何人的。
但是,如果你认为你的单体所面临的问题会被神奇地解决,或者甚至被简化,那么你将会面临痛苦的世界。
(banq注:微服务虽然不能完全解决单体的模块化切分,但是至少能让更多团队加入你的单体开发,相信比你有能力的程序员会照顾好他们的狗食)

五、我应该考虑微服务吗?
单体和微服务之间的选择常常被认为是两种相互排斥的思维模式。旧派与新派。正确或错误。一个或另一个。
事实上,它们都是有效的方法,有不同的取舍。正确的选择是针对具体环境的,必须包括一系列广泛的考虑。
选择本身是一个错误的二分法,在某些情况下,应该在逐个功能的基础上进行选择,而不是为整个组织的工程团队选择单一的方法。
(banq注:二分法虽然如同太极阴阳很简单,但是通常错误的,但是但是,二分法容易让你理解,微服务和单体模块化最大区别是测试、部署的独立性,相互不干扰,可以增加更多团队独立地开展工作,如果你需要这个好处,你现有团队又遭遇认知负荷天花板,那么微服务是不二之选)

你应该考虑微服务吗?
就像通常的情况一样,这取决于:你是否真的会从微服务架构中受益。
当然有一些情况下,他们会支付他们带来的成本,特别是一个中小型团队或早期阶段的项目。

你可能不需要微服务!
不相信我?问一问
在行业内问一问,你会发现关于微服务和它们给团队带来的问题的警告性故事不胜枚举。

Segment是一个有据可查的高知名度的例子,它是一个在微服务上转弯的团队。
这同样适用于作为单体的微服务。他们在执行中出现问题并不意味着核心前提有根本性的缺陷。
(banq注:失败的原因是否确实因为微服务引起的?还是对微服务的误解引起的,微服务的引入根本原因是由团队管理因素决定的,不是由纯粹技术决定的,参与康威定律

然而,如果你打算采用微服务方法,你需要睁大眼睛进去。接受权衡,并准备好额外的资源,以成功地完成它。

单体应该仍然是新的、小型和中型工程团队的默认选择。微服务仍然是一种选择,但你应该有令人信服的特定理由来证明它们的使用。
对于大中型团队来说,应该考虑到这一点,但要对其进行大量的了解和权衡。
(banq注:对于新的小型团队,从一开始注意团队成员的认知天花板,不要让团队做自己能力以外的事情,如果超过了,则带来创业失败,这时候不是硬着头皮用单体模块化,会导致更严重的技术债务,这时候应该寻找更多投资资金或让出原始股股权,引入更多程序员,组建更多团队,参考团队拓扑

banq:单体和其导致的技术负债是让你一个人干十个人工作的根本原因,你不是十倍全栈程序员,软件不是手工艺而是工程团队,当你加班加点以后软件还是不稳定、新功能交付延长,这时候考虑引入新的人员,只有微服务才能让你新人员立即投入工作,单体只会让这些新成员加班加点学习试图理解整个单体代码,这不会产生任何价值效益,变成了培训学校了。