随着软件行业的快速发展,传统的单体应用架构逐渐暴露出其固有的问题,比如部署困难、扩展性差、维护成本高等,而微服务架构作为一种新的架构模式,逐渐成为企业内解决这些问题的最佳实践方案。
微服务的起源可以追溯到 2005 年的云计算博览会(Web Services Edge 2005),当时被称为 Micro-Web-Service。作为对 SOA 的轻量级补救方案,微服务最初并没有受到广泛关注,因为它被认为只是对 SOA 的修修补补,难以激发技术人员的兴趣。然而,在最近过去的十年中,微服务经历了思考和演变。
2012 年,Thoughtworks 首席咨询师 James Lewis 在波兰克拉科夫的 33d Degree Conference 上的《Microservices - Java,the Unix Way》主题演讲中,强调了微服务的原则,如单一服务职责、康威定律、自动扩展和领域驱动设计。这标志着微服务开始摆脱对 SOA 的依赖,呼吁重拾 Unix 设计哲学。
真正的崛起发生在 2014 年,由 Martin Fowler 和 James Lewis 合著的文章《Microservices:a definition of this new architectural ter》中,首次明确了微服务的定义。微服务被定义为通过多个小型服务的组合构建单个应用的架构风格,这些服务围绕业务能力而非特定技术标准构建,可以采用不同的编程语言、数据存储技术,运行在不同的进程中。这一定义成为微服务的真正起源。
那微服务架构到底是什么?我们先来对他做一个明确的定义:
微服务架构是一种将大型复杂软件系统应用划分为一组小的、独立的服务模块的方法,每个服务运行在其独立的进程中,并通过轻量级的通信机制相互通信。这些服务围绕业务场景构建,并通过自动化部署机制独立地开发、测试、部署和扩展。
微服务强调康威定律的重要性,即团队的结构、规模和能力将产生对应的产品结构、规模和能力。团队和产品磨合稳定后,将拥有一致的结构,避免了跨团队沟通和高成本的跨团队边界。
微服务倡导谁负责谁治理,开发团队直接对服务运行质量负责,不受外界干预,可以选择和其他服务异构的技术来实现自己的服务。强调对技术栈的选择权,并不强迫统一。
强调通过服务而不是类库来构建组件,因为服务是进程外组件,通过远程调用提供功能,带来隔离与自治的能力。服务的独立性是通过远程调用的代价来实现的。
微服务要求将架构看作是一种持续改进和提升的过程,避免将软件研发视为完成某种功能的任务。开发团队应为整个软件产品的生命周期负责,强调软件的持续改进和用户反馈。
微服务提倡将数据按领域分散管理、更新、维护和存储。不同服务对同一数据实体的抽象形态可能是不同的,避免了中心化存储导致的服务互相影响和失去独立性的问题。
微服务倡导简单直接的通信方式,强调弱管道(Dumb Pipes)机制机制,反对过于复杂的通信机制,比如 SOAP 、 BPM 等。通过类似于 Unix 过滤器的简单通信方式,比如 RESTful 风格,实现服务之间的通信。
微服务接受服务总会出错的现实,要求在设计中考虑自动故障检测、隔离和服务恢复的机制。容错性设计的目的是防止一两个服务的崩溃引发雪崩效应。可靠系统完全可以由会出错的服务来组成,这也是微服务架构最大的价值所在。
微服务设计应该能够被淘汰,而不是期望服务的长期存在。良好的设计应该是可演进的,不可更改和无可替代的服务反映了系统设计的脆弱性。微服务强调独立自治,鼓励设计能够随着需求的变化而演进。
微服务架构下,基础设施的自动化(如 CI/CD)降低了构建、发布、运维的复杂性。面对微服务的数量级增长,团队更加依赖基础设施的自动化来应对挑战。
从上面对微服务的演进史,核心特征的说明,以及现在微服务架构模式的风靡,它是有着独特的优势的:
当然,微服务虽然好,它的广泛应用降低了软件研发的复杂性,但它依旧有着很大的挑战。对于开发者而言,微服务提供了友好的开发体验,但对架构师则提出了史无前例的要求。架构师需要具备广泛的知识面,以便在面临选择时能够权衡利弊。
首先,微服务架构需要处理分布式系统的复杂性,比如数据一致性、分布式事务、网络延迟等,这些在微服务架构中依旧是比较高的复杂度,对架构师有着很大的挑战。
其次,微服务架构没有统一的规范和约束,各种中间件层出不穷,服务注册发现、负载均衡、认证授权等问题需要根据具体情况选择适当的解决方案。比如,在服务间通信方面,存在多种解决方案如 RMI、Thrift、Dubbo、gRPC、Motan2、Finagle、brpc、Arvo、JSON-RPC、REST 等。对于服务发现,可选的方案有 Eureka、Consul、Nacos、ZooKeeper、etcd、CoreDNS 等。微服务时代的中间件百花齐放,架构师需要具备对这些工具和框架的熟悉程度,以便做出明智的选择。
再者,微服务架构模式的企业需要建立成熟的自动化部署和监控机制,无形之中增加了运维的难度和成本。
总体而言,微服务架构为开发者提供了更灵活的开发和部署方式,但对于架构师来说,需要面对更高的决策难度和挑战。
微服务时代的演进既为软件架构带来了新的活力,也要求从业者不断学习和适应。
在微服务架构中,每个微服务应该只关注一个特定的业务功能或者能力,并保持其职责的单一性。这有助于降低服务的复杂性,提高可维护性和可测试性。
在微服务架构中,每个微服务应该具有自己独立的数据库和数据魔性,实现服务的自治性,这就意味着每个服务都可以独立地管理其数据和业务逻辑,降低了服务之间的耦合度。
在微服务架构中,要求微服务之间应该保持松耦合的关系,通过定义清晰的接口来进行通信。同时,每个服务内部应该实现强內聚,将相关的功能和数据紧密地组织在一起,提高服务的可维护性和可扩展性。
在架构演变史中我有讲到单体架构并非大恶,它有着自己的特点和适用场景,微服务也并非放之四海而皆准的。接下来我就和大家一起看看这两个架构在不同方面的对比分析。
在单体架构中,所有的功能都集中在一个应用中,通常适用单一的技术栈、单一的数据库和数据魔性,部署为一个整体,所有的功能同时上线/下线。
在微服务架构中,所有的功能被拆分为多个独立的服务,每个服务可以使用不同的技术栈,每个服务有自己的数据库和数据模型,服务可以独立地开发、测试、部署和扩展。
在单体架构模式下,所有开发人员都在同一个代码库上工作,协同开发相对简单,但是代码库可能会变得庞大且难以管理。而且每次代码更新都需要重新编译和部署整个应用,即使只是一个小功能的修改。
在微服务架构模式下,每个服务由一个研发团队独立开发,可以适用最适合自己团队的技术栈和框架,提高了开发的效率和创新性。而且每个服务都可以独立部署,无需等待其他服务的更新,实现了持续集成和持续交付。
在单体架构模式下,所有的功能都运行在同一个进程中,资源利用率可能不高。同时由于代码高度耦合,一个小的改动都有可能影响到整个应用,维护成本比较高。
在微服务架构模式下,每个服务都运行在自己的进程中,可以根据实际需求进行扩展,提高了资源的利用率。同时服务之间通过明确的接口通信,降低了耦合度,易于维护和扩展。
在单体架构模式下,通信方式是内部函数调用或者内部方法调用。通过数据库事务保证数据一致性。
在微服务架构模式下,通过 RESTful API、消息队列、RPC 或者其他通信协议来进行跨服务的通信。在针对数据一致性的问题,是比较复杂的,需要采用分布式事务、事件驱动等方式来保证数据一致性。
单体架构模式适用于小型项目或者初期阶段的项目,开发周期短、团队规模小,对系统的可扩展性和可维护性要求不高。
适用于大型复杂的项目,需要快速响应市场变化,团队规模大,对系统的可扩展性和可维护性有较高要求,同时,微服务架构需要更多的基础设施和运维支持,因此成本相对较高。
理论上讲,单体架构和微服务架构无论优劣,各有优缺点,选择哪种架构模式取决于实际需求和团队的实际情况,在评估时,需要综合考虑项目的规模、复杂性、开发周期、团队规模和技术能力的因素。
在微服务架构模式中,通信机制一般包括同步通信和异步通信两种,我们逐一解读。
本文关于同步通信机制,我会介绍 RESTful API 和 RPC 这两种,比较常见,其他的各位自行查阅。
RESTful API 是微服务架构中最常用的同步通信方式,它基于 HTTP/HTTPS 协议,通过请求/响应模式进行通信,每个微服务可以暴露一个或者多个 API 接口,给其他服务或者客户端调用,具有轻量级、跨平台、可扩展性强的特点。
以一个用户服务和一个订单服务的交互来看看整个调用过程:用户创建订单,此时订单服务通过用户服务提供的 RESTful API 来获取用户信息。
RPC 之前有过详细介绍的部分,可查看之前的文章内容。RPC 是一种远程过程调用协议,允许一个程序/客户端调用另一个地址控制的过程或者函数,与 RESTful API 相比,RPC 更加轻量级,通常适用自定义的二进制协议进行通信,性能更高。
以在分布式系统中,使用 gRPC 框架,有两个微服务 A 和 B,A 需要调用 B 的一个服务,通过 gRPC 进行通信。
异步通信机制主要介绍消息队列,关于消息队列的具体内容前面也已经详细讲解过,可自行查阅。消息队列是一种异步通信机制,允许微服务之间通过发送和接收消息进行通信,通常提供可靠的消息传递、高吞吐量和分布式处理能力。
以 RabbitMQ 为例,假设有两个微服务 A 和 B,A 需要将一些数据发送给 B 进行处理,可以通过 RabbitMQ 进行异步通信。
微服务架构中的通信机制是实现服务间协同工作的关键,同步通信提供了请求/响应的交互方式,适用于实时性要求较高的场景,而异步通信提供了松耦合、高吞吐量的通信方式,适用于处理大量数据或者需要异步处理的场景,在实际应用中,可以根据具体需求选择合适的通信机制来实现微服务之间的有效协作。