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

了解微服务失败的这11个原因,及时预防止损!

时间:2023-03-14 00:45:24 科技观察

微服务“很香”,它有很多优点,比如开发速度更快、扩展性更好、独立团队更小等等。然而,许多团队都在与微服务作斗争并且没有利用它。是什么原因?这是本文作者试图回答的问题。在过去的几年里,我对几个推进数字化转型的产品团队进行了架构审查。我的发现:大多数团队都按照微服务架构构建产品。更快的开发、更好的可扩展性、更小的独立团队、独立部署以及使用正确的技术来完成工作等等。这些优势让他们有充分的理由采用微服务架构。但是,我经常发现许多团队都在为微服务而苦苦挣扎。他们没有充分利用微服务。为什么很多团队在微服务的道路上“挣扎”?这就是我要回答的问题。如果您不熟悉微服务,我建议您阅读MartinFowler关于微服务的文章。https://martinfowler.com/articles/microservices.html这篇文章解释了什么是微服务架构:微服务架构的风格是一种将单个应用程序开发成一组小服务的方式,每个应用程序都在自己的进程中运行并且与轻量级机制(通常是HTTP资源API)通信。这些服务围绕业务功能构建,可以通过完全自动化的部署机制独立部署。这些服务具有最少的集中管理,可以用不同的编程语言编写,并使用不同的数据存储技术。1.管理层低估了开发微服务的复杂性我曾与许多非常看好微服务的客户合作过。对于他们来说,微服务是解决他们所有问题的“灵丹妙药”。随着讨论的进行,我发现大多数团队及其管理层都低估了微服务开发的复杂性。要开发微服务,开发人员需要高效的本地环境设置。随着系统中的服务数量开始增加,在一台机器上运行应用程序的一个子集变得越来越困难。如果您使用内存密集型语言(如Java)构建应用程序,则尤其如此。以下是与本地开发设置相关的要点:本地开发的第一个重要方面是拥有一台好的开发机器。我发现大多数组织都希望使用所有最新、最好的技术,但不想更换他们糟糕的Windows开发机器。开发人员仅限于他们的开发机器。我见过开发人员使用VDI映像或配置交错机器构建基于微服务的系统。这不仅会降低他们的工作效率,还会使他们无法完全投入工作。使用糟糕的开发机器的一个副作用是开发人员得不到快速反馈。知道您必须等待几分钟才能运行您的集成测试套件将使您避免编写更多的集成测试套件,这会给您带来更多的痛苦。糟糕的开发机器会导致糟糕的开发实践。一旦为开发人员提供了合适的开发机器,下一步就是确保所有服务都使用构建工具。您应该能够在没有太多配置的情况下在新机器上构建整个应用程序。根据我在微服务方面的经验,拥有一个构建整个应用程序的根构建脚本也很??有帮助。下一点是让开发人员可以轻松地在他们的系统上运行部分应用程序。配置所有端口和卷后,您应该为不同的服务使用多个docker-compose文件。接下来,如果你正在使用像Kubernetes这样的容器编排工具,你应该投资像Telepresence这样的工具来轻松调试Kubernetes集群中的应用程序。如果组织缺乏对微服务开发复杂性的理解,团队速度会随着时间的推移而降低。2.没有将库和工具更新到最新版本我发现新平台已经成为遗留问题。该团队没有确保依赖项是最新的,也没有将数据库等工具升级到最新版本。结果,两年前开始的现代化努力现在背负着数月的技术债务。几年前,许多团队开始使用SpringCloudNetflixOSS项目进行微服务。他们使用像Kubernetes这样的容器编排工具,但是因为他们从NetflixOSS开始,所以他们没有使用Kubernetes必须提供的所有功能。虽然Kubernetes内置了服务发现,但他们仍然使用Eureka进行服务发现。此外,使用像Istio这样的服务网格,您可以摆脱NetflixOSS提供的大部分功能。这有助于降低复杂性并将许多“横切关注点”转移到平台上。另一件要记住的事情是保持所有服务的依赖版本同步。最近在帮一个客户用SpringBoot搭建微服务。在过去的两年里,他们已经构建了20多个SpringBoot服务。在他们的环境中,他们使用的SpringBoot版本从1.5到2.1不等。这意味着一旦有人设置了他们的机器,他们就必须下载多个版本的SpringBoot。此外,它们缺少自1.5版以来在SpringBoot中所做的许多改进。建议组织应在其积压工作中为这些升级创建技术债务项目。这些技术债务项目应该作为架构委员会会议的一部分进行讨论并定期解决。在我的上一个项目中,我们每三个月设置一次为期一周的冲刺,以将所有依赖项更新到最新版本。3.利用共享服务促进本地开发由于本地开发状况不佳,大多数团队已经开始依赖共享环境来提供关键服务。开发人员机器中的第一件事是数据库。大多数年轻的开发人员没有意识到在共享数据库上进行开发是“邪恶的”。以下是我在共享数据库中看到的主要问题:团队成员必须建立工作的社会契约以避免最后写入胜利(LWW)问题。开发人员可以删除其他开发人员为他们的工作编写的数据。这种工作方式很痛苦,容易失败,迟早会影响到整个团队。开发人员害怕实验,因为他们的工作会影响其他团队成员。我们都知道,更好的学习方法是实验和快速反馈。使用共享数据库,可以进行实验。我们需要进行实验以提出数据库模式并执行性能调整等任务。另一个副作用是很难单独测试更改。您的集成测试将变得不可靠,进一步减慢开发速度。共享数据库必须像宠物一样对待,因为您不希望它处于不一致和不可预测的状态。你可能会遇到这样的场景,一个开发人员想在表为空时测试一个边缘情况,但其他开发人员需要一个表来记录。只有共享数据库拥有系统工作所需的所有数据。随着时间的推移,团队成员失去了更改的可追溯性,因此没有人知道如何在他们的机器上复制相同的设置。唯一的方法是获取完整的数据库转储并使用它。不连接到网络就很难工作。这通常发生在您通勤时间长或乘坐飞机时。数据库只是共享服务的一个示例,但它也可以是消息队列、集中式缓存(如Redis)或任何其他可以发生更改的服务。解决这个问题的最好方法是让开发人员可以轻松地在他们的机器上运行数据库(作为Docker容器)并投资创建SQL脚本来设置模式和初始主数据。这些SQL脚本应保存在版本控制中,并像任何其他代码一样进行维护。4.版本控制托管平台缺乏可见性我曾与一个在其版本控制系统中拥有超过1000个存储库的客户合作。他们使用的是Gitlab版本控制平台。他们有5个产品,每个产品由多个微服务组成。我问他们的第一个问题是帮助我们了解哪些服务及其各自的代码库是产品A的一部分。他们的首席架构师不得不花一天时间弄清楚所有产品A存储库。一天过去了,她仍然不确定自己是否弄清楚了所有服务。解决这个问题的最好方法是从一开始就以某种方式对您的微服务进行分组,这样您就可以始终了解产品的生态系统。Gitlab提供了一种创建组然后在其中创建项目存储库的方法。Github没有组功能,所以你可以使用主题或命名约定来实现它。我个人更喜欢monorepos,因为我发现它们非常方便。我遇到的大多数开发人员都认为它是一种反模式。我同意DanLua的观点,他提到了monorepo的以下好处:简化组织简化依赖关系工具跨项目更改5.服务没有明确定义大多数团队不知道什么应该被视为服务。关于究竟什么构成了一个单一的微服务,存在很多混淆和混淆的概念。让我们举个例子,假设你的应用程序有一个类似插件的架构,你在其中集成了多个第三方服务。每个集成都应该是一个微服务吗?我看到很多团队,为每个集成创建一个微服务。随着集成数量的增加,这会很快失控并变得难以管理。这些服务通常非常小,以至于将它们作为单独的进程运行会增加更多的开销。我认为即使拥有一些大型服务也比拥有太多小型服务要好。我将首先创建一个服务,该服务为企业组织中的整个部门建模。这也符合DDD(领域驱动设计)。我将域拆分为子域和限界上下文。有界上下文代表公司内的一个部门,例如财务和市场营销。您可能认为这会导致大型服务,您是对的。随着知识的增长,您可以转向代表较小问题的细粒度微服务。您可以应用单一职责原则(SingleResponsibilityPrinciple)来了解微服务是否变得太大和做的太多。然后,您可以将其分解为更小的独立服务。任何服务都不应直接与另一个服务的数据库通信。他们应该只通过公布的合同进行交流。在Microservices.io网站上,您可以了解有关按子域模式分解的更多信息。https://microservices.io/patterns/decomposition/decompose-by-subdomain.html我也遵循了Backendlore文档中提到的建议。https://github.com/fpereiro/backendlore这个建议可以帮助将服务限制为服务通信,这是微服务系统性能不佳的首要原因。如果两条信息相互依赖,那么它们应该属于同一个服务器。换句话说,服务的自然边界应该是其数据的自然边界。6.不明确的代码重用策略我曾经与一位客户合作,他在所有基于Java的微服务中复制了四个特定于问题的Java文件。因此,如果在该代码中发现错误,则需要在所有地方应用它的修复。我们都知道,当我们时间紧迫时,我们会错过对一项或多项服务应用更改。这会浪费更多时间并增加挫败感。这并不是说开发团队不知道该做什么。然而,在组织结构上,人们总是默认简单易错的做事方式。正确的方法是使用像Bintray或Nexus这样的工件管理器,并在那里发布你的依赖项。然后,每个微服务都应该依赖这个库。您需要构建工具,以便在发布新版本的库时,应更新和重新部署所有微服务。使用微服务并不意味着您不应该使用迄今为止对我们有用的最佳实践。您需要投资于可以更轻松地升级微服务的工具,这样人们就不必这样做了。在没有合适的工具和自动化的情况下使用微服务可能会导致灾难。7.多语言编程设计我看到团队使用多种编程语言、多个数据库、多个缓存,并以最佳工具的名义工作。所有这些都在项目的初始阶段起作用,但是随着您的产品投入生产,这些选择开始显示出它们的“本色”。原因就像我们正在构建一个JavaSpringBoot应用程序,但我们意识到Java更占用内存并且性能也很差,所以我们决定切换到Node.js。在我的最后一项任务中,我向团队解释说他们的推理能力很弱。(1)Note.js比Java表现更好如果你的工作负载是基于I/O的,Node.js通常会表现得更好。但在任何计算密集型工作负载上,Java都优于Node.js。通过响应式范例,您可以使用Java为I/O工作负载提供更好的性能。SpringBootReactor在I/O工作负载方面与Node.js相当。https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/javascript.htmlhttps://blogs.sap.com/2018/08/03/spring-boot-reactive-vs.-node.js-in-sap-cloud-platform-reflection-on-throughput-measurement/(2)Node.js消耗的内存比Java少从某种程度上来说,这是事实。JavaSpringBoot应用程序并不像大多数人想象的那么糟糕。我在SpringBootJava微服务上进行了负载测试,内存消耗仍然没有超过1GB。使用OpenJ9JVN,您可以通过调整默认JVM参数来限制对类路径的依赖并优化Java内存利用率。此外,还有Java中SpringBoot的新替代品,例如Micronaut和Quarkus,它们消耗的内存与Node.js一样多。(3)Node.js比Java更高效这取决于编写代码的开发人员。具有静态类型和静态分析工具的Java可以帮助在开发生命周期的早期发现问题。大多数时候,这完全取决于上下文。如果你的开发人员不成熟,那么无论你使用什么编程语言,你都会开发出糟糕的产品。我建议一个组织发布一个团队可以使用的语言列表。我觉得2~3是个不错的数字。此外,列出一种语言比另一种语言更适合的原因。以下是您在选择语言之前应该考虑的一些问题:找到成熟的企业软件开发人员有多容易?对开发人员进行新技术再培训有多容易?我们发现Java开发人员可以相对轻松地学习Golang。初始团队之外的开发人员贡献、转移和维护其他人编写的代码有多容易?生态系统在工具和库方面的成熟度如何?这不仅限于编程语言,也适用于数据库领域。如果您的系统中已经有MongoDB,为什么还要在您的生态系统中使用ArangoDB?它们都主要是文档数据库。始终考虑使用多种技术的维护和操作方面。8.人为依赖这不是微服务特有的现象,而是在微服务生态系统中越来越普遍。原因是,大多数团队都专注于他们的特定服务,因此他们不了解完整的生态系统。在我与不同客户的合作中,我发现只有一组建筑师能看到大局。然而,这些架构师的问题在于他们没有积极参与日常活动,因此他们对开发的影响是有限的。我认为最好的方法是确保所有团队都有架构团队的代表,这样他们就可以使他们的团队与整个架构团队的路线图和目标保持一致。要成为成熟的组织,您需要投资构建轻量级治理。9.缺乏文档在过去的几年里,我们接触过的大多数组织都在为文档而苦苦挣扎。大多数开发人员和架构师要么不编写文档,要么他们编写的文档毫无用处。即使他们愿意,他们也不知道如何记录他们的模式。至少,我们应该记录以下内容:设计文档C4模型中的上下文和容器图跟踪关键架构决策作为架构决策记录开发人员入门我建议在版本控制系统中维护所有文档。https://c4model.com/http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions10。平台成熟度之上的能力在其他方面我简要提到了这个原因,但我认为它值得作为首要原因提及。微服务比传统的整体应用程序更复杂,因为您正在构建一个包含许多移动部件的分布式系统。大多数开发人员还不了解系统的不同故障模式。大多数微服务在构建时都考虑到了快乐之路。因此,如果您的管理层只想专注于功能,那您就注定要失败。因为建立在弱平台上的功能无法交付价值。组织需要有平台思维。平台思维不仅仅意味着容器和Kubernetes。它们是解决方案的一部分,但本身并不是完整的解决方案。您还需要考虑分布式跟踪、可观察性、混沌测试、函数调用与网络调用、服务间通信的安全服务、可调试性等。这需要在构建合适的平台和工具团队方面做出认真的努力和投资。如果你是一家资源有限的初创公司,我的建议是重新考虑你的微服务战略。知道你面临的问题是什么。11.缺乏自动化测试大多数团队都知道自动化测试对产品整体质量的重要性,但他们仍然不知道。微服务架构为测试地点和方式提供了更多选项。如果您不进行彻底的自动化测试,您将会惨遭失败。关于这一点,我不再赘述,因为网上很多人都写过。下图是我从MartinFowler网站的微服务测试文章中找到的,该文章讨论了基于微服务的系统的测试金字塔。微服务测试金字塔