在文章《微服务架构概览》中,我详细讨论了微服务架构以及在现代软件开发中使用它的优缺点。那么,什么是微服务架构呢?我给出的定义是:
微服务架构是将软件系统分解成可独立部署的自治模块,这些模块通过轻量级的、语言无关的方式进行通信,共同实现业务目标。
软件系统是复杂的。由于人脑只能处理一定程度内的复杂性,大型软件系统的高复杂性导致了许多问题。大型复杂的软件系统难于开发、增强、维护、现代化和规模化。多年来,为解决软件系统的复杂性做过许多尝试。在上世纪 70 年代, David Parnas 和 Edsger W. Dijkstra 引入了模块化软件开发,以解决软件系统的复杂性。在上世纪 90 年代,引入了分层软件架构来处理业务应用程序的复杂性。自本世纪初以来,面向服务的架构(Service Oriented Architecture, SOA)成为开发复杂业务应用程序的主流。微服务架构是处理现代软件应用复杂性的最新方法。此时,大家可能会提出一个问题:为什么我们突然需要一个新的软件开发方法?简而言之,与软件开发相关的整个生态系统在过去十年中发生了巨大的变化。如今,软件使用敏捷方法开发,使用 CI/CD 在容器 + 云上部署,在 NoSQL 数据库上持久化,在现代浏览器或智能手机上展现,机器通过高速网络连接。由于这些因素的出现,在 2012 年诞生了微服务架构。
主要有两类人对微服务和单体架构持相反的观点。对于一群人来说,微服务架构完全是关于货物崇拜或炒作驱动的开发,这只是痴迷于技术的开发人员的游乐场。对于另一群人来说,微服务架构是“一个管控所有的架构”,它可以消除软件系统的任何复杂性。在我看来,微服务和单体架构是互补的。如果从长远来看,这个应用程序仍然会较小,则单体架构是适合的方法。另一方面,对于大型而复杂的应用程序或有潜力变得大型而复杂的应用程序,微服务架构是正确的解决方案。现代软件开发是如此庞大,以至于微服务架构和单体架构将像 SQL 和 NoSQL 一样的方式共存。
正确设计微服务架构非常具有挑战性和困难。与单体架构为所有问题提供一个解决方案相反,微服务架构为不同的问题提供不同的解决方案。如果选择了错误的解决方案,那么微服务架构就是一个注定要爆炸的定时炸弹。一个设计糟糕的微服务架构比一个单体架构还要糟糕。为微服务架构定义一组最佳实践也很有挑战性。我曾在一些会议上看到一些著名的、受人尊敬的软件工程师提出了微服务架构的最佳实践,但这些实践却适得其反。
在这里,我提出了一些最佳实践,这些实践将有助于开发有效的微服务应用程序,在这些应用程序中,目标项目应该存在超过 6 个月的时间,并且团队规模从中等到大型(6+ 开发人员)。另外,还有一些关于微服务架构最佳实践的文章,例如 Martin Fowler()的《微服务架构的特征(Characteristics of a Microservice Architecture )》、Chris Richardson 的《微服务模式( Microservices Patterns )》、以及 Tony Mauro 的《在 Netflix 采用微服务:架构设计的教训( Microservices at Netflix: Lessons for Architectural Design )》。也有一些很棒的演讲,例如 Stefan Tilkov 的《微服务模式和反模式( Microservices Patterns and Antipatterns )》,David Schmitz 的《微服务严重失败的 10 个技巧( 10 Tips for failing badly at Microservices)》,Sam Newman 的《微服务原理( Principles of Microservices )》。
开发微服务的首要挑战是将大型、复杂的应用程序分割成小型、自主、独立的可部署模块。如果微服务没有以正确的方式进行分割,将会出现紧耦合的微服务,这些微服务将具有单体架构的所有缺点,并具有分布式单体架构的所有复杂性。幸运的是,已经有一个解决方案可以在这方面提供很大的帮助。Eric Evans 当时是一名软件工程顾问,他在不同公司的业务应用程序中遇到了关于软件复杂性的反复出现的问题,于是在 2004 年出版的《领域驱动设计:处理软件核心的复杂性》一书中总结了他的宝贵见解。该书概述了三个核心概念:
软件开发团队应该与业务部门或领域专家密切合作。
架构师 / 开发人员和领域专家应该首先进行战略设计:找到有界的上下文和相关的核心域以及普遍存在的语言、子域、上下文映射。
然后,架构师 / 开发人员应该进行战术设计,将核心域分解为细粒度的构建块:实体、值对象、聚合、聚合根。
领域驱动设计的详细讨论超出了这篇文章的讨论范围,但是你应该读一下起初的 DDD 书籍 Eric Evans 的《领域驱动设计:处理复杂的软件(蓝皮书)( Domain Driven Design: Tackling Complexity in the Heart of Software (Blue Book))》,或者更现代一点儿的 DDD 书籍 Vaughn Vernon 的《实现领域驱动设计(红皮书)( Implementing Domain Driven Design (Red Book))》。如果将一个大型系统划分为核心域和子域,然后将核心域和子域映射到一个或多个微服务,那么我们将得到理想的松耦合微服务。
在将复杂的应用程序拆分为多个微服务模块之后,下一个挑战出现了,如何处理数据库?我们是否应该在微服务之间共享数据库?这个问题的答案是一把双刃剑。一方面,在微服务之间共享数据库将导致微服务之间的强耦合,这与微服务架构的目标正好相反。即使是数据库中的一个小更改也需要团队之间的协调同步。此外,在一个服务中管理数据库的事务和锁就已经足够具有挑战性了。而在多个分布式微服务之间管理事务和锁更是一项艰巨的任务。另一方面,如果每个微服务都有自己的数据库或私有表,那么在微服务之间交换数据就打开了挑战的潘多拉盒子。因此,许多著名的软件工程师都提倡在微服务之间共享数据库,将其作为一种实用的解决方案。然而,在我看来,微服务是关于可持续和长期的软件开发的。因此,每个微服务都应该有自己的数据库(或者私有表)。
不幸的是,大多数的后端开发人员对前端开发有一种过时的看法,认为前端开发很简单。由于大多数软件架构师都是后端开发人员,他们很少关注前端,而前端在架构设计中往往被忽视。通常在微服务项目中,后端与它们的数据库被很好地模块化,但只有一个整体前端。在最好的情况下,他们考虑用最热门的单页面应用(react、 angular、vue)其中之一来开发独体前端。这种方法的主要问题是,前端的单体架构和后端单体架构一样糟糕,正如我前一篇 文章 所述。另外,当前端因为浏览器的变化而需要更新时,它就需要一个大的更新(这就是为什么那么多公司仍然使用过时的 Angular 1 框架的原因)。网络是简单的,但非常强大,并天生提供了穿透力。开发基于单页面应用的微前端有很多方法:使用 iFrame、Web 组件或借助于(Angular/React)元素。
微服务架构的关键卖点之一是每个微服务都可以独立部署。如果你有一个系统,例如 100 个微服务,并且只需要更改一个微服务,那么你可以只更新一个微服务,而不需要修改其他 99 个微服务。但是,在没有自动化的情况下独立部署 100 个微服务(DevOps、CI/CD)是一项艰巨的任务。要充分利用微服务的这一特性,需要 CI/CD 和 DevOps。使用没有 CI/CD、DevOps 的微服务架构,自动化就像购买最新的保时捷,然后用手刹去驾驶它。难怪微服务专家 Martin Fowler 将CI/CD 列为使用微服务架构的三个先决条件之一。
微服务架构的主要缺点之一是,软件开发变得简单,而牺牲了运维。使用单体架构,监视应用程序要简单得多。但是许多微服务在容器上运行,整个系统的可观察性变得非常重要和复杂。甚至日志记录也变得很复杂,要将来自许多容器 / 机器的日志聚集到一个中心位置。幸运的是,市场上已经有很多企业级的解决方案了。例如,ELK/Splunk 提供微服务的日志记录。Prometheus/App Dynamics 提供工业级监控。微服务世界中另一个非常重要的可观察性工具是 Tracing。通常,对一个微服务的一个 api 请求会导致对其他微服务的几个级联调用。要分析微服务系统的延迟,需要测量每个微服务的延迟。Zipkin/Jaeger 为微服务提供了出色的跟踪支持。
微服务架构告诉我们,对于一个微服务,采用最适合该微服务的编程语言和框架。这种说法不能照字面理解。有时,一个微服务可能需要一个新的技术栈,例如 CPU 密集 / 高性能任务,可能会选择如 c++ /Rust 之类的编程语言。如果微服务与机器学习一起工作,那么 Python 可能是更好的选择。但是在没有任何理由的情况下使用不同的编程语言 / 框架会导致过多的编程语言和框架而没有任何实际的好处。思考这么一个应用场景,一个微服务是使用 Spring Boot + Kotlin+ React + MySQL 开发的,另一个用的是 JakartaEE + Java + Angular + PostgreSQL,下一个是 Scala + Play Framework + VueJS + Oracle,则需要大量的工作去维持这些不同的编程语言、数据库、框架,而没有太多的收益。
微服务架构中最具挑战性的设计决策之一是服务之间如何通信和共享数据。当每个微服务都有自己的数据存储时,这一点就更为重要了。通常,一个微服务可以单独存在,但是它不能单独实现所有的业务目标。所有微服务为了实现业务目标而在一起工作,为了在一起工作,它们需要交换数据或触发其他微服务来执行任务。在微服务之间进行通信的最简单和最常见的方式是通过同步的 REST API,这是一种实用但临时的解决方案。如果服务 A 同步调用服务 B,服务 B 同步调用服务 C,服务 C 同步调用服务 D,那么延迟就会增加。此外,由于微服务主要是分布式系统,它们有可能会失败。通常,同步微服务会导致级联失败,即一个服务的失败会导致其他服务的失败。微服务之间的同步通信也导致了微服务之间的紧密耦合。对于长期解决方案,微服务应该异步通信。微服务之间的异步通信有很多方式:通过消息队列,例如 Kafka,通过异步的 REST (ATOM)或 CQRS。
许多专家认为,对于新项目,最好从松耦合的单体架构开始,因为微服务架构需要大量的初始工作来设置运维。在他们看来,一旦项目变得足够成熟,“漂亮的”设计就可以很容易地转化为微服务。然而,在我看来,这种方法在大多数情况下都会失败。实际上,实体内部的模块将是紧耦合的,这将使其很难转换成微服务。而且,一旦应用程序投入生产,在不破坏应用程序的情况下将其转换为微服务将变得更加困难。因此,我的建议是,如果最终有使用微服务架构的计划,那么就从微服务开始。
在微服务软件开发的早期,Netflix 主要使用 Java 编程来开发微服务。他们还开发了许多类库(Netflix 的 OSS 栈,包括 Hystrix、Zuul)。许多公司通过 Netflix 跟进并开始使用 Netflix OSS。后来,许多公司(包括 Netflix)发现,Java 实际上并不是开发微服务的语言,因为它体积庞大,而且冷启动问题严重。Netflix 后来转向 Polyglot 微服务范式,并决定不再进一步开发 Netflix OSS,这导致了追随者公司陷入困境。因此,与其大量投资于特定语言的类库(如基于 Java 的 Netflix OSS),不如使用框架(如服务网格、API 网关)。
大约 50 年前(1967 年),Melvin Conway 观察到公司的软件架构受到组织结构的限制(Conway 定律)。尽管这一观察发现已有 50 年历史,但麻省理工学院(MIT)和哈佛商学院(Harvard Business School)最近发现,这一法则在当今仍然有效。如果一个组织计划开发微服务架构,那么它应该使团队规模更为恰当(两个“美国”比萨团队:7±2 人)。此外,团队应该是跨职能的,最好有前端 / 后端开发人员、运维工程师和测试人员。微服务架构只有在高层管理者也相应地改变他们的观点和愿景的情况下才能发挥作用。
作者介绍:Md Kamaruzzaman,热情的软件架构师,终身学习者,热心的读者,偶尔也写写文章。
原文链接:Effective Microservices: 10 Best Practices
作为容器集群管理技术竞争的大赢家,Kubernetes已经和微服务紧密联系,采用Kubernetes的企业往往都开始了微服务架构的探索。然而不同企业不同阶段的微服务实践面临的问题千差万别,注定要在技术路线上产生分叉
微服务本身并没有一个严格的定义,不过从很多人的反馈来看,大家都达成了这样一个共识:微服务是一种简单的应用,大概有10到100行代码。我知道使用代码行数来比较实现其实很不靠谱,因此你能理解这个意思就行,不必过分拘泥于细节
「 调用链监控 」是在微服务兴起后才有的一种新流行的监控模式。因为在我们传统单体应用的项目中,不存在服务链/调用链的概念,所以也就根本没有调用链监控的需求了
在Medium,我们的技术堆栈始于2012年的单体Node.js应用程序。我们已经构建了几个卫星服务,但我们还没有制定一个系统地采用微服务架构的策略。 随着系统变得越来越复杂并且团队不断发展
新兴技术的下一波浪潮正向我们涌来,人工智能、可穿戴设备、物联网及更多技术变得普及开来。许多组织现面临着管理这些整体式应用程序这个难题。当下,速度和灵活性必不可少
微服务被认为是一种理想的架构模式,因此,Steven Lemon 所在公司的领导层决定从单体架构向微服务架构迁移,这让整个开发团队在随后的的日子里苦不堪言,七大现实问题摆在面前无法解决,微服务架构的好处也没有享受到
微服务,并不仅仅是一种代码构造方式。微服务概念一出现就引发了热烈讨论,很多文章都喜欢将其与整体式架构比较,乃至来自大型企业的用例等。然而,在说起微服务时,开发人员关注的往往是这场革命的技术意义
Web应用架构受系统用户量、开发人员组织方式影响严重。过去二十年互联网迅速发展,Web架构也从单体式演进出微服务,背后还有比如 Martin Fowler 提出的理论支撑。虽然每个人都听说过微服务,但是很多人并不太清楚为什么要这么做
近些年微服务架构大行其道,趁着最近有时间,来捣鼓捣鼓微服务是怎么一回事。微服务的概念由 Martin Fowler 于2014年3月提出:微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间相互协调
NGINX从一开始就参与了微服务运动。 NGINX的轻巧,高性能和灵活性非常适合微服务。NGINX Docker映像是Docker Hub上排名第一的应用程序映像,您今天在Web上找到的大多数微服务平台都包含一个演示
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!