当前位置: 首页 > 科技观察

被泼冷水后,谁能超越微服务?

时间:2023-03-23 11:07:21 科技观察

作者|由ShaiAlmog策划|云昭历史总是在重演。刚刚过去的一切都会再次被提起。Shai是开源项目CodenameOne的联合创始人,也是SunMicrosystems开源LWUIT项目的合著者,参与了无数开源项目。作为第一批Java开发者,我最近感慨地说:Monolith回来了!Shai说:我在这个圈子里呆了很长时间,看到了被抛弃、重新发现、超越“流行语”、凯旋归来的想法。他进一步举了个例子,“这几年,SQL也在挣扎,起死回生。我们又爱上了关系型数据库。我认为单体架构将再次迎来神奇的旅程。微服务和无服务器是云提供商推动的趋势.当然是卖给我们更多的云计算资源。然而对于大多数用例来说,微服务在财务上没有多大意义。是的,供应商当然也可以削减成本。但是当他们扩展时,他们将用红利来弥补成本。增加仅在可观察性方面的成本就已经让‘大型云’提供商的口袋膨胀了!”作为从业近30年的资深技术大牛,为何感叹?本文以“使用模块降低架构成本”为题,帮助大家梳理当前架构设计中存在的问题,希望对大家有所启发。1.问题背景我最近领导了一个关于微服务与整体服务主题的会议小组。该集团认为,单块的规模不如微服务。对于亚马逊、eBay等已经取代的庞然大物来说,这可能是正确的。这些确实是巨大的代码库,每次修改都很痛苦,而且很难扩展。但这不是一个公平的比较。新方法通常比旧方法更好。但是,如果我们使用更新的工具构建单体应用,我们是否会获得更好的可扩展性?它有什么局限性?现代单体(也称为单体)应该是什么样子?2.单体回归示例:ModulithSpringModulith是一种模块化的单体结构,它允许我们使用动态隔离器构建单体结构。通过这种方法,我们可以将测试、开发、文档和依赖项分开。这促进了微服务开发的独立方面,几乎不涉及开销。它消除了远程调用和功能重复(存储、身份验证等)的开销。SpringModulith不基于Java平台模块化(Jigsaw)。他们在测试和运行时强制分离,这是一个常规的SpringBoot项目。它有一些额外的运行时特性,可以实现模块化的可观察性,但它主要是一个“最佳实践”的执行者。这种分离的价值超出了我们通常通过微服务获得的价值,但也有一些权衡。例如,传统的Spring单体将具有包含以下包的分层架构:层与层之间;例如,DB层不应该依赖于服务层。我们可以像这样使用模块并有效地将依赖图推向一个方向:向下。但随着我们的成长,这并没有多大意义。每一层都将充满业务逻辑类和数据库复杂性。使用Modulith,我们的架构看起来更像这样:myapp.invoicing.servicescom.debugagent.myapp.invoicing.dbcom.debugagent.myapp.invoicing.restcom.debugagent.myapp.hrcom.debugagent.myapp.hr.servicescom.debugagent.myapp.hr.dbcom.debugagent.myapp.hr.rest这看起来非常接近合适的微服务架构。我们根据业务逻辑将所有部分分开。在这里,交叉依赖性得到了更好的控制,团队可以专注于各自孤立的领域,而不会踩到彼此的脚趾。这是没有开销的微服务的价值之一。我们可以更进一步,使用注解以声明方式实现分离。我们可以定义哪个模块使用哪个并强制执行单向依赖,因此HR模块将与发票无关。客户端模块也不会。我们可以在客户和发票之间建立单向关系,并使用事件进行反馈。Modulith中的事件简单、快速且具有事务性。他们毫不费力地消除了模块之间的依赖关系。这个用微服务可以实现,但是很难实现。例如,计费需要将接口暴露给不同的模块。如何防止客户端使用该接口?使用模块,我们可以做到这一点。用户可以更改代码并提供访问权限,但这需要代码审查,这会带来自身的问题。请注意,对于模块,我们仍然可以依赖常见的微服务,如功能标志、消息系统等。您可以在文档和NicolasFr?nkel的博客上阅读更多关于SpringModulith的信息。模块系统中的每个依赖项都映射并记录在代码中。Spring实现包括使用方便的最新图表自动记录所有内容的能力。您可能认为依赖性是Terraform的原因。这种“高级”设计适合放在这里吗?对于Modulith部署,基础架构即代码(IaC)解决方案(如Terraform)仍然存在,但它们会简单得多。问题是责任的划分。如下图所示,微服务并没有消除整体结构的复杂性。我们只是向DevOps团队踢了“硬骨头”。更糟糕的是,我们没有给他们正确的工具来理解这种复杂性,因此他们不得不在外部进行管理。来源:推特这就是为什么我们行业的基础设施成本在上涨,而传统行业的基础设施价格却在下降。当DevOps团队遇到问题时,他们会投入资源解决问题。这显然不是正确的做法。3.其他模块我们可以使用标准的Java平台模块(Jigsaw)来构建SpringBoot应用。这具有分解应用程序和标准Java语法的优点,但有时可能会很尴尬。使用外部库或将一些工作拆分为通用工具时可能会更有效率。另一种选择是Maven中的模块系统。该系统允许我们将构建分解为单独的项目。这是一个非常方便的过程,为我们省去了很多项目的麻烦。每个项目都是独立的且易于使用。它可以使用自己的构建过程。然后,当我们构建主项目时,这些都变成了一个整体。在某种程度上,这就是我们真正想要的。4.单体架构:扩容,有解决办法吗?我们可以使用大多数微服务扩展工具来扩展我们的整体。许多与扩展和集群相关的开发都发生在单体应用上。这是一个更简单的过程,因为只有一个移动部分:应用程序。我们复制其他实例并观察它们。没有服务是失败的。我们拥有细粒度的性能工具,所有功能都可作为统一版本使用。我认为将整体扩展到微服务比直接构建微服务更简单——我们可以使用分析工具并获得瓶颈的合理近似值。我们的团队可以轻松(且负担得起)设置一个暂存环境来运行测试。我们拥有整个系统及其依赖项的单一视图。我们可以单独测试各个模块并验证性能假设。跟踪和可观察性工具很棒。但它们也会影响生产,有时还会产生噪音。在尝试解决扩展瓶颈或性能问题时,这些工具可能会给设计人员带来一些陷阱。我们可以将Kubernetes与单体一起使用,就像将其与微服务一起使用一样有效。图像尺寸会更大(如果我们使用像GraalVM这样的工具,可能不会那么大)。有了这个,我们可以跨区域复制整体,并提供与微服务相同的故障转移行为。相当多的开发人员将monolics部署到Lambdas。我不太喜欢这种方法,因为它非常昂贵。5、单体的瓶颈问题:解决办法是有的,但是还有一个巨大的障碍:数据库。由于微服务本身具有多个独立的数据库,因此它们具有巨大的规模。单体架构通常使用单个数据存储。这通常是应用程序的真正瓶颈。有多种方法可以扩展现代数据库。集群和分布式缓存是强大的工具,可以让我们达到在微服务架构中难以达到的性能水平。在单体结构中,也不需要单个数据库。比如:在使用Redis做缓存的时候,选择使用SQL数据库也是很常见的。但我们也可以为时间序列或空间数据使用单独的数据库。我们也可以使用单独的数据库来提高性能,尽管根据我的经验,这从未发生过。将数据保存在同一个数据库中的好处是巨大的。6.回归单体的好处其实这样做有一个惊人的好处,我们可以在不依赖“最终一致性”的情况下完成交易。当我们尝试调试和复制分布式系统时,我们可能会遇到难以在本地复制的过渡状态,甚至无法通过查看可观察性数据来完全理解。原始性能消除了大量网络开销。通过适当调整的L2缓存,我们可以进一步移除80-90%的读取IO。在微服务中,这更难实现,并且可能无法消除网络调用的开销。正如我之前提到的,应用程序的复杂性并没有在微服务架构中消失。我们只是把它搬到了另一个地方。所以从这个意义上说,微服务并不是真正的进步,因为在此过程中添加了很多移动部件,但没有任何意义,增加了整体的复杂性。因此,回到更智能、更简单的统一架构更有意义。7、看微服务的卖点编程语言的选择是微服务亲和度的首要指标之一。微服务的兴起与Python和JavaScript的兴起相关。这两种语言都非常适合小型应用,但不太适合大型应用。Kubernetes使扩展此类部署变得相对容易,从而为已经增长的趋势增添了动力。微服务也有一些相对快速的起伏。这使得能够以更精细的方式进行成本控制。在这方面,微服务作为降低成本的一种方式被出售给组织。这并非完全没有道理。如果以前的服务器部署需要功能强大(且昂贵)的服务器,那么这个论点可能有些道理。这可能适用于极端的使用情况,例如:突然面临很高的负载,但随后又不堵塞。在这些情况下,可以从托管的Kubernetes提供者动态地(且廉价地)获取资源。微服务的主要卖点之一是组织调度方面。这允许各个敏捷团队在不完全了解“大局”的情况下解决小问题。这样做的问题是它创造了一种“单打独斗”的文化,每个团队都“做自己的事”。在裁员期间问题更大,尤其是在代码“腐烂”的情况下。该系统可能仍然可以工作多年,但无法有效维护。8.为什么互联网要建立在单体之上?作者小组的共识是我们应该始终从单体开始。它更容易构建,如果我们选择使用微服务,我们可以稍后分解整体。关于特定软件相关的复杂性,我们讨论单个模块而不是单个应用程序更有意义。两者在资源使用和财务浪费方面的差异是巨大的。在这个追求“降低成本”的时代,为什么人们仍然默认构建微服务,而不是动态模块化单体架构?我们可以从这两个“建筑阵营”中学到很多东西。诚然,微服务为亚马逊创造了奇迹。但公平地说,这个奇迹涵盖了他们的云成本。所以,搞微服务的人的教条肯定是有问题的。另一方面,互联网是建立在单体之上的。它们中的大多数都不是模块化的。两者都有普遍适用的技术。因此,在笔者看来,正确的选择是构建一个模块化的单体结构,首先构建一个合适的认证基础设施。如果我们以后要转向微服务,我们可以利用这些基础设施进行解构和拆分。9.后记在设计应用程序时,我们目前面临着更多“二选一”的架构选择:单体和微服务。两者通常被视为相反的方法。在小型系统的演进过程中,单体应用程序随着时间的推移往往会在架构上退化,这是不争的事实,即使它们在生命周期的开始就被定义为架构。随着时间的推移,各种架构限制逐渐进入项目,并且随着时间的推移,系统变得更难改变并且进化受到影响。另一方面,微服务提供了更强的分离手段,但同时引入了很多复杂性,因为即使是小型应用,团队也不得不应对分布式系统的挑战。单一回归也是一种特定的条件回归。我们可以看到趋势的变化意味着特定的任务或目标在一定时期内正在发生变化。由于目标的改变,我们不能再教条地对待微服务和单体架构之间的选择问题。事物往往是螺旋式发展的,建筑也是如此。原文链接:https://dzone.com/articles/is-it-time-to-go-back-to-the-monolith