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

什么时候不应该采用微服务架构

时间:2023-03-18 16:33:19 科技观察

作者|TomaszNurkiewicz翻译|李腾辉策划|芯源微服务不能“包治百病”。如今,微服务是一种很好的架构,具有模块化、可扩展性和高容错性等优点。许多公司都采用了微服务架构并取得了巨大成功,自然地,如果您要开始一个新项目,微服务似乎是最佳选择。然而,大多数在微服务上取得成功的公司一开始并没有选择这种架构。以Airbnb和Twitter为例。他们在单体应用太大之后选择了微服务路线,目前还在解决由此带来的复杂性。即使是大公司仍在寻找使用微服务的最佳方式。因此,微服务是一把双刃剑,需要权衡利弊。从单体应用程序迁移到微服务绝非易事,使用微服务构建新产品而不进行测试更加复杂。只有在对备选方案进行全面评估后,才应认真考虑是否使用微服务架构。1.微服务只适合成熟的产品对于从头开始使用微服务,MartinFowler总结道:1.几乎所有成功的微服务都是从一个过于庞大而不得不拆分启动的单体应用开始的。2.几乎所有从头开始构建的微服务系统最终都会因为严重的问题而失败。这种情况导致许多人认为,即使您确定您的应用程序会快速增长,也不应该从微服务开始。很难很好地优化设计的第一个版本。新产品的前几次迭代专注于找到用户真正的痛点。因此,成功取决于敏捷以及能够快速优化和重构。在这方面,微服务比单体应用差很多。如果您在不确定原始设计的情况下采用微服务,您的旅程将会更加艰难,因为重构微服务比重构单体应用要困难得多。2.你是在创业公司还是在开发新项目?作为一家创业公司,你已经在与时间赛跑,试图在未知的坏消息到来之前找到突破口。此时你真的不需要关心可扩展性(可能几年内都不需要),那么为什么要使用复杂的架构而忽视客户的需求呢?开发全新的项目时也有类似的情况,这些项目不受以前工作的限制,更不用说任何决策包袱了。《构建微服务:设计细粒度的系统》作者SamNewman说,用微服务构建一个全新的项目非常困难:我仍然坚信,划分一个现有的遗留系统比一个全新的系统要容易得多。你有更多的资源可以帮助,比如你有代码可以参考,你可以和使用和维护系统的人交谈和讨论,你也知道一个“好”的系统是什么样的——基于当前稳定的操作对系统进行更改,使您更容易知道哪里出了问题以及您的决定是否过于激进。3、微服务不是本地部署的最佳选择由于所有组件都是动态变化的,微服务部署需要搭配更强大的自动化机制。在正常环境下,我们可以依靠持续部署流水线(continuousdeploymentpipelines)来完成工作——任务开发者部署微服务,消费者只使用在线服务。但是,这不适用于本地环境。如果开发者发布一个包,消费者需要在自己的本地环境中部署和配置其他服务,这给部署带来了更大的挑战。准确的说,开发本地微服务应用也是可行的,就像Semaphore(一个CI/CD平台)也提供了本地化的部署模式。然而,在这个过程中我们需要克服几个挑战:1.本地微服务的版本控制规则需要更严格,你必须跟踪每个参与发布的微服务。2.你必须做完整的集成和端到端测试,因为你不能在生产中测试。3.如果不能直接访问生产环境,对微服务应用程序进行故障排除要困难得多。第四,您的单个应用程序可能仍然可以使用,每个软件都有自己的生命周期。你可能想要废弃一个整体,因为它既旧又复杂。但是折腾一个系统可能吃力不讨好。稍加努力,或许就能从现在的系统中榨取更多的价值,让他多用几年。只有在这两种情况下,微服务重构才是必做的选择:1.代码混乱:很难在不破坏其他功能的情况下,在原有代码的基础上进行改动和增加新功能2.性能因素:你遇到了瓶颈扩展单体应用程序时5.模块化单体开发人员希望避免采用单体架构的一个常见原因是单体更有可能成为一堆“代码垃圾山”。那时很难添加新功能,因为一切都是相互关联的。但是单体不一定是一团糟。以Shopify为例:它拥有超过300万行代码,是世界上最大的Rails单体之一。但是有一件事,太大的系统会给开发者带来很多痛苦:应用很脆弱,新的代码会有很多意想不到的效果。进行一些更改可能会触发一连串不相关的测试用例失败。例如计算运费和计算税率时重复使用了一些代码,更改计算税率的代码可能会影响运费计算的结果。这是高耦合和无边界的结果,这也导致测试用例难以编写并且在CI上运行非常缓慢。Shopify没有将整个单体应用程序重写为微服务,而是选择模块化作为解决方案。模块化有助于设计更好的单体或微服务。如果不仔细定义模块,我们要么陷入传统的分层单体(大泥球),要么更糟,成为分布式单体应用,兼有单体和微服务的缺点。模块化是一项繁重的工作,但它也带来了巨大的价值,使开发更加直接。新开发人员在开始更改代码之前不必了解整个应用程序,一次只需了解一个模块。良好的模块化可以使大型单元更易于使用。模块化是转向微服务之前的必要步骤,可能是更好的解决方案。与微服务类似,模块化单体通过将代码拆分成独立的模块来解决代码耦合问题。与通过网络通信的微服务不同,单体应用程序中的模块通过内部API调用进行通信。HierarchicalMonolith与ModularMonolith相比,ModularMonolith具有微服务的许多特征,但没有微服务面临的许多挑战。6.单体可以扩展关于单体的另一个误解是它们不能扩展。如果您遇到性能问题并认为微服务是唯一的出路,请查看Shopify,它已经在音频领域超大规模构建了可靠的单体应用程序。架构和技术堆栈将决定如何优化单体应用程序。模块化之后,可以利用云原生技术进行扩展:1.部署单体应用的多个实例,使用负载均衡器进行流量分发2.使用CDN分发静态资源和前端代码3.使用缓存减少数据库负载4.使用边缘计算(edgecomputing)或无服务器功能(serverlessfunction)来实现高需求的功能7.如果系统能高效工作,不要轻易尝试改变if我们将生产力指标定义为多少有价值的功能是按时间单位实现的,那么当生产力价值很高时,切换架构就没有什么意义了。由于更高的维护开销,微服务最初是一种生产力较低的架构,并且随着单体的增长,系统变得更加复杂并且添加新功能变得更加困难。微服务只有在交叉之后才会变得更有效率。不可否认,有些事情最终确实必须完成,但那是多年后才可能考虑的事情。到那时,需求可能已经改变——谁知道届时是否会出现新的架构模型?8.Brooks定律与开发人员生产力在《人月神话(The Mythical Man Month)》一书中,FrederickP.Brooks,Jr.曾说过:“在软件项目的后期增加人力,会使交付时间更晚。”发生这种情况是因为新人在能够开发复杂代码之前必须接受指导。此外,随着团队的壮大,沟通成本增加,使组织决策更加困难。在开发大型软件时,布鲁克斯定律指出,在软件项目的后期增加人力只会使时间更长。微服务是减少法律影响的一种方式。但是这种效果只有在代码库复杂和庞大的情况下才会体现出来,因为在这种情况下我们不能将开发拆分成独立的任务。在使用微服务之前,您必须考虑您的单体应用程序是否受到Roux定律的影响。过早地切换到微服务不会增加更多的价值。9.你准备好改变了吗?在开始切换微服务之前,除了准备你的单体,你还必须满足以下条件:1.设置持续集成和持续部署(CI/CD)以实现自动化部署2.实施快速配置以构建按需基础设施3.了解云原生技术栈,包括容器化、K8S、Serverless4.熟悉领域驱动设计(DDD,Domain-DrivenDesign)、测试驱动开发(Test-DrivenDevelopment)、行为驱动开发(Behavior-Driven)开发)5.团队重组以实现跨职能沟通以消除信息孤岛并采用扁平化管理以激发创新6.培养DevOps文化,使开发人员和运营人员更加一致地工作改变组织的文化可能需要数年时间,学习所有微服务的必要知识可能需要几个月的时间,如果你没有准备好转向微服务是注定的。10.小结上面关于转微服务的讨论,我们可以用一句话来概括:除非你有充分的理由,否则不要轻率地去做。任何在没有准备好且没有可靠设计的情况下使用微服务的公司都会遇到非常困难的时期。需要营造良好的技术文化氛围,做好技术储备,再考虑微服务。同时,如果您的系统运行良好并且仍在以预期的速度开发,为什么要急于改变?最后,感谢您阅读本文,祝您编程愉快!原文链接:https://dzone.com/articles/when-microservices-are-a-bad-idea译者介绍李腾辉,社区编辑,目前在东南亚互联网金融独角兽任高级Java工程师,负责负责金融借贷平台架构设计和核心建设工作,对互联网金融架构和微服务体系有深入研究,期待在互金领域继续深耕。