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

实现有效微服务架构的10个优秀实战技巧_0

时间:2023-03-19 18:38:26 科技观察

去年,有人提出微服务会被疯狂致死,关于微服务的争论从未停止过。今天小新给大家带来的是一个不得不提的系列——微服务架构正确实现的10个技巧(也是10个优秀实践)。什么是微服务架构?这是作者自己的定义:微服务架构是将一个软件系统分解成自治的模块,可以独立部署,以轻量级、语言无关的方式进行通信,共同实现业务目标。软件系统很复杂。由于人脑只能容忍一定程度的复杂性,大型软件系统的高度复杂性会产生许多问题。大规模、复杂的软件系统难以开发、增强、维护、现代化和扩展。多年来,已经进行了许多尝试来解决软件系统的复杂性。在1970年代,DavidParnas和EdsgerW引入了模块化软件开发。Dijkstra解决了软件系统复杂性的问题。在90年代,引入了分层软件架构来解决业务应用程序的复杂性。自2000年代初期以来,面向服务的体系结构(SOA)已脱颖而出,用于开发复杂的业务应用程序。微服务架构是处理现代软件应用程序复杂性的最新方法。此时可能会出现一个问题:为什么突然需要一种新的软件开发方法?简而言之,软件开发运行的整个生态系统在过去十年中发生了巨大变化。今天,软件通过敏捷方法开发,使用CI/CD方法部署在容器+云上,然后存储在NoSQL数据库中,最后呈现在浏览器或智能手机上,这些设备在高速网络下连接在一起。基于这些因素,微服务架构在2012年应运而生。微服务orMonolith对于微服务和Monolith,主要有两类人持相反的观点。对于一群人来说,微服务架构是一种货物崇拜(Cargo-Cult)或趋势驱动开发(HypeDrivenDevelopment),就像是喜欢技术的开发者的游乐场。另一群人说,微服务架构是“统治一切的架构”,将消除任何软件系统的复杂性。在笔者看来,微服务和Monolith架构是相辅相成的。对于长期精简的应用,Monolith架构更适合。另一方面,对于大型和复杂的应用程序或者可能变得庞大和复杂的应用程序,微服务架构是一个更好的解决方案。今天的软件开发是一个非常庞大的工程,可以实现微服务架构和Monolith架构的共存,就像SQL和NoSQL的共存一样。10个最佳实践使用正确的方法设计微服务架构非常具有挑战性和困难。微服务架构不同于单体架构,后者可以提供一劳永逸的解决方案。微服务架构针对不同的问题提供了不同的解决方案。如果选择了错误的解决方案,微服务架构就是一颗注定要爆炸的定时炸弹。设计不当的微服务架构比单体架构更糟糕。为微服务架构定义一套最佳实践也很困难。我在一些会议演讲中听到一些知名且受人尊敬的软件工程师提出了适得其反的微服务架构最佳实践。本文介绍了一些微服务架构的良好实践,有助于开发有效的微服务应用程序,目标项目可以存在6个月以上,团队规模为中型到大型(6名以上开发人员)。以下文章介绍了有关微服务架构的综合最佳实践,例如MartinFowler的文章《微服务架构的特征》或ChrisRichardson的《微服务模式》或Netflix的?:TonyMauro的《架构设计的若干教训》。还有一些很棒的演讲,例如StefanTilkov的演讲《微服务模式和反模式》、DavidSchmitz的演讲《应对微服务严重失败的10条技巧》、SamNewman的演讲《微服务原理》。1、微前端不幸的是,大多数后端开发者对前端开发的看法是落后的,认为前端开发很容易。由于大多数软件架构师都是后端开发人员,他们很少关心前端,而前端在架构设计中往往被忽略。在微服务项目中,后端数据库通常是高度模块化的,但有一个Monolith前端。在最好的情况下,开发人员会考虑使用最热门的SPA(React、Angular、Vue)之一来开发Monolith前端。但主要问题是前端Monolith和作者在《微服务架构:简介与在项目中应用的必要性》(微服务架构:简要概述以及为什么要在下一个项目中使用它)一文中描述的后端Monolith一样糟糕。此外,由于更改浏览器也会使前端保持同步,因此需要进行大爆炸式现代化(这就是为什么许多公司仍在使用过时的Angular1框架的原因)。Web简单但功能强大,并提供本地嵌入。基于微前端开发SPA的方法有很多:使用iFrame、WebComponents或通过Elements(Angular/React)。2.持续交付微服务架构的一个关键USP是每个微服务都可以独立部署。如果系统有100个微服务,需要更改一个微服务,那么只更新一个微服务即可,其他99个微服务不做更改。但是在没有自动化的情况下独立部署100多个微服务(DevOps、CI/CD)是一项艰巨的任务。要充分利用此微服务功能,需要CI/CD和DevOps方法。使用没有CI/CD、DevOps和自动化的微服务架构就像购买最新的保时捷并踩着刹车行驶。毫不奇怪,CI/CD被微服务专家MartinFowler列为使用微服务架构的三个先决条件之一。3.微服务优先许多专家认为,对于新建(新)项目,最好从松散耦合的单体架构开始,因为微服务架构需要大量初始工作来设置操作。专家认为,一旦项目变得足够成熟,一个“精心”设计的Monolith可以很容易地转换为微服务。但是,作者认为这种做法在大多数情况下都会失败。事实上,Monolith内部的模块是紧密耦合的,这使得它很难转换为微服务。同样,一旦应用程序投入生产,在不破坏应用程序的情况下转换为微服务就变得更加困难。所以,如果有计划最后使用微服务架构,建议一开始就使用微服务。4.库基础设施在微服务软件开发的早期,Netflix主要使用Java编程来开发微服务。Netflix也开发了一些库(包括Hystrix、Zuul的NetflixOSSStack)。许多公司跟随Netflix并开始使用NetflixOSS库。后来,很多公司(包括Netflix)发现Java并不是开发微服务的事实上的语言,因为它的体积大和冷启动问题。Netflix后来转向了Polyglot微服务范式,并决定不再进一步开发NetflixOSS,这给跟随Netflix的公司带来了麻烦。因此,与其大量投资于特定语言的库(例如基于Java的NetflixOSS),不如使用框架(例如服务网格、API网关)更为明智。5.领域驱动设计开发微服务的最大挑战是将大型、复杂的应用程序分解为小型、可管理且可独立部署的模块。如果微服务没有以正确的方式拆分应用程序,那么就会出现紧密耦合的微服务,它们将具有单体的所有缺点和微服务(又名分布式单体)的所有复杂性。幸运的是,已经有一个解决方案可以在这方面提供很大帮助。曾在不同公司多次遇到业务应用程序复杂性问题的软件工程顾问埃里克·埃文斯(EricEvans)在他2004年出版的书中总结了《域驱动设计:解决软件核心中的复杂性》非常有价值的见解。本书的核心概念可分为以下三类:软件开发团队应与业务部门或领域专家密切合作。架构师或开发人员和领域专家应该从战略设计开始:找到限界上下文和相关核心域、通用语言、子域、上下文映射。然后架构师或开发人员应该进行战术设计,将核心域分解为细粒度的构建块:实体、值对象、聚合、聚合根。领域驱动设计的详细讨论超出了本文的范围,但您应该阅读EricEvans的原著《域驱动设计:解决软件核心中的复杂性》(蓝皮书)或VaughnVernon的原著《实施域驱动设计》(红皮书)。如果将一个大型系统划分为核心域和子域,然后将核心域和子域映射到一个或多个微服务,就可以获得理想的松耦合微服务。6.可观察性微服务架构的主要缺点之一是以操作为代价的软件开发的便利性。使用Monolith监控应用程序要简单得多。但是,由于很多微服务运行在容器上,整个系统的可观察性变得非常关键和复杂。由于无法将来自许多容器或机器的日志聚合到一个中央位置,甚至日志记录也变得复杂。幸运的是,市场上已经有很多企业级解决方案。例如,ELK/Splunk为微服务提供日志记录。Prometheus/AppDynamics提供行业级监控。微服务世界中另一个非常重要的可观察性工具是Tracing。通常,对微服务的一个API请求会导致对其他微服务的多个级联调用。要分析微服务系统的延迟,有必要测量每个微服务的延迟。Zipkin/Jaeger为微服务提供了出色的跟踪支持。7、统一技术栈的微服务架构表明需要采用最适合微服务的编程语言和框架。这不应该从字面上理解。有时微服务可能需要新的技术栈,例如对于CPU繁重或高性能任务,可以选择C++/Rust等编程语言。如果微服务可以与机器学习一起使用,也许Python是更好的选择。然而,在没有任何正当理由的情况下使用不同的编程语言或框架会导致编程语言和框架过多而没有任何实际好处。想象这样一个场景:使用SpringBoot+Kotlin+React+MySQL开发一个微服务,使用JakartaEE+Java+Angular+PostgreSQL开发另一个微服务,再使用Scala+PlayFramework+VueJS+Oracle开发另一个微服务,那么维护不同的编程语言、数据库和框架需要付出很多努力,但收效甚微。8.每个微服务的数据库将复杂的应用程序拆分成微服务模块后,下一个挑战出现了——数据库怎么办?数据库是否应该在微服务之间共享。这个问题的答案是一把双刃剑,有利也有弊。一方面,微服务之间共享数据库会引入强耦合,这与微服务架构的目标恰恰相反。即使数据库中的微小变化也需要团队之间的同步操作。同样,在服务中管理事务和锁定数据库可能具有挑战性。但是跨多个分布式微服务管理事务或锁定数据库是一项艰巨的任务。另一方面,如果每个微服务都有自己的数据库或专用表,则在微服务之间交换数据会带来打开潘多拉魔盒的挑战。因此,许多杰出的软件工程师提倡一种实用的微服务共享解决方案。但是,笔者认为,微服务完全是一个可持续的、长期的软件开发过程。因此,每个微服务都应该有自己的数据库(或专用表)。9.异步通信微服务架构中最具挑战性的设计决策之一是服务如何通信和共享数据。当每个微服务都有自己的数据存储时,这一点尤为重要。通常,微服务可以独立存在,但无法单独满足所有业务目标。所有微服务协同工作以实现一个业务目标并持续协同工作,这些微服务需要交换数据或触发其他微服务来完成任务。微服务之间最简单和最常见的通信方式是通过同步RESTAPI,这种方式很有用但不可持续。如果服务A调用服务B,服务B调用服务C,服务C同步调用服务D,延迟会累加起来。此外,由于微服务主要是分布式系统,因此它们可能会出现故障。同步微服务通常会导致级联故障,其中一项服务的故障可能导致其他服务的故障。微服务之间的同步通信也会导致微服务之间的紧耦合。对于长期解决方案,微服务应该异步通信。微服务之间的异步通信有很多方法:例如,通过MessageQueueKafka,通过AsynchronousREST(ATOM)或CQRS。10.组织方面的考虑大约50年前(1967年),MelvinConway观察到公司的软件架构受其组织结构的限制(康威定律)。尽管这一发现已有50年历史,但麻省理工学院和哈佛商学院最近发现该定律在现代仍然有效。如果一个组织计划开发微服务架构,团队规模应该相应增加(两个“美国”披萨团队:5或9人)。此外,团队应该是跨职能的,最好有前端或后端开发人员、运维工程师和测试人员。微服务架构只有在高级管理层也相应地改变观点和愿景的情况下才能发挥作用。希望大家看完上面的技巧,能够正确的实现微服务架构~