软件工程无银弹。

模式名称

微服务本质上是一种架构风格。和单体(巨石架构)架构类似。

微服务架构模式。

需求

微服务是指将大型复杂软件应用拆分成多个简单应用,每个简单应用描述着一个小业务,系统中的各个简单应 用可被独立部署。 各个微服务之间是松耦合的,可以独立地对每个服务进行升级、部署、扩展和重新启动等流程, 从而实现频繁更新而不会对最终用户产生任何影响。相比传统的单体架构,微服务架构具有降低系统复杂度、独立部署、独立扩展、跨语言编程等特点。

与此同时,架构的灵活、开发的敏捷同时带来了运维的挑战。微服务框架作为微服务开发和运行治理的必要支 撑,帮助实现微服务注册、发现、治理等能力,目前,在微服务技术架构实践中主要有侵入式架构和非侵入式架构 两种实现形式。侵入式架构是指服务框架嵌入程序代码,实现类的继承,其中以 Spring Cloud 最为常见。非侵入式 架构,如 Istio ,则是以代理的形式,与应用程序部署在一起,接管应用程序的网络且对其透明。

模式描述

当前架构的设计模式描述。 使用模式语言进行描述。

微服务架构的示意图

微服务架构下,应用程序由许多独立的可替换的小型服务构成,每个服务实现单个业务功能,服务间松散耦合,通过 API 网关完成调用。

image.png

  • 什么是服务?服务是单一的,可以独立部署的软件组件,它实现的特定的功能。
  • 服务大小的粒度切割很关键,它是架构中的「架构量子」。
  • 微服务的本质:服务的分解和定义
  • 单体系统 v.s. 微服务化的架构设计差异
    • 单体地狱的理解
      • 软件组织分工问题
      • 单体随着业务复杂度的增加,会过度复杂,比如 SOA 架构,开发的速度也会成为问题
      • 难以扩展,随着体系结构的放大
    • 微服务的架构设计往往意味着每个服务有独立的数据库

实现关注

微服务的拆分思路 & 策略

  • 适度选择微服务的架构风格:分层、六边形风格
  • 一般的拆分过程:功能需求 => 领域模型 => 定义系统操作 & 业务能力 => 拆分服务
  • 充分使用领域驱动设计中提供的服务拆分概念,连接:领域模型(DomainModel)、界限上下文(BoundingContext)等设计约束去做服务拆分
  • 充分利用面向对象设计原则,比如 OCP、SRP 原则

微服务进程之间的通信策略

  • 单机通信:关注主流的 IPC 机制
  • 服务之间同步通信:使用主流的 RPC 机制
    • 关注 RPC 的性能:序列化、传输性能 …
    • 关注 RPC 传输数据格式:JSON、Protobuf、XML …
    • 关注 API 的设计风格:RESTful、GraphQL 等
  • 服务之间使用异步事件
    • 消息中间件的选型策略
    • 关注:支持编程语言、消息标准、消息排序、持久性、耐久性、可扩展性、延迟、竞争性 …
    • 关注:并发消息的处理策略、重复消息的幂等性、事务性质的消息处理

微服务之间的事务处理

  • Paxos 作为分布式算法的基石
  • 充分考虑 AICD 刚性事务(本地事务)的设计风格
  • 多服务保持一致性的分布式事务:SAGA 事务

微服务的业务逻辑设计

  • 使用 DDD 指导设计,建立团队之间的设计原则
    • 只引用聚合根
    • 聚合之间使用主键进行引用
    • 单个事务只能够进行单个聚合更新
    • 控制聚合的粒度,做合理切分
    • 使用领域事件
  • 使用事务脚本
  • 使用事件溯源的模式开发业务逻辑
  • 微服务架构之中的查询设计两者选型的利弊需要权衡。
    • API 组合模式
      • 客户端组合
      • 服务端组合
        • BFF
        • GraphQL
    • 命令查询职责隔离模式(CQRS)
      • 使用领域事件维护另一个数据视图变更(数据库)
      • 让查询库(Q)和更新库(CUD)分离职责
  • 外部 API 模式
    • API Gateway 模式
      • Ingress 就是一套网关架构
      • BFF 网关也是类似的架构模式
        • 模式:Schema 机制驱动查询
    • API Gateway 也可以承载服务发现的能力

微服务的持续集成 & 测试

  • 单元测试
  • 集成测试
  • 组件 & 服务测试
  • E2E(端到端测试)

必须在 DevOPS 流程中得到淋漓尽致的展现。

面向生产的微服务架构关注点

  • 关注 流量治理 的机制
    • 服务容错:常见的容错策略(摘录自凤凰架构)
      • 故障转移 Failover:一个副本失败之后,尝试转移请求到别的副本
      • 快速失败 Failfast:对于幂等的服务,可以使用该策略,直接舍弃请求,抛出异常
      • 安全失败 FailSafe:主路和旁路的失败,分开治理
      • 沉默失败 FailSilent:请求失败之后,将节点挂置一段时间之后再恢复服务
      • 故障恢复 Failback:故障后重启失败的节点,恢复服务
      • 并行调用 Forking:触发多个节点,双重保险
      • 广播调用 Brodcast:触发多个节点,谁快谁上
    • 流量控制
      • 理解流量统计的指标:每秒事务数(TPS)、每秒请求数(HPS)、每秒查询数(QPS)
      • 限流的设计模式:流量计数、滑动时间(Sliding Window Algorithm)、漏桶模式(Traffic Shaping)、令牌漏桶模式
      • 分布式限流:存入集中式缓存(Redis)等在集群内实现流量分发和共享
  • 关注 可靠通信 的机制
    • 安全机制
    • 0 信任网络
  • 关注 可观测性 的机制
    • 日志系统
    • 追踪系统
  • 使用 服务网格 来隔离微服务治理与业务逻辑
    • 边车代理模式 SideCarProxy
    • 关注数据平面、控制平面
    • 关注主要的 ServiceMesh 相关的生态

部署微服务策略

  • 应用打包和制件机制
  • 虚拟化技术 & 虚拟化容器
    • 指令集虚拟化(ISA):指令集虚拟化
    • 硬件抽象层虚拟化(HAL):VMVare 等桌面端虚拟机
    • 操作系统层虚拟化(OSL):Docker
    • 容器虚拟化(本质上是不同维度的封装)
      • 隔离文件技术:chroot
      • 隔离访问技术:Linux Namespace
      • 隔离资源技术:cgroups
      • 封装系统:LXC
      • 封装应用:Docker
      • 封装集群:Kubernate
    • 以容器构建系统
      • 隔离 & 协作:K8S 提出了 Container ⇒ Pod(容器组) ⇒ Node(集群中的单台物理机) ⇒ Cluster(集群) ⇒ Federation(多个集群组建的可以用于区域多活、跨地域容灾等诉求) 的不同粒度的结构分离
      • 韧性 & 弹性:自动扩容、回滚更新、故障恢复等特征关注。
    • 以应用为中心的封装:
      • Kustomize:用配置文件来配置配置文件
      • Helm & Chart:封装 K8S 应用涉及的所有资源,后提以类型 Linux 的包管理机制做安装
      • Operator & CRD:封装、部署和管理 K8S 应用的方法。
  • 容器编排体系
  • 使用 Serverless 相关的技术,0 关注运维模式
    • FaaS

实现结果

当前架构期望达到的目的 & 实现的效果。

微服务架构中的小型服务具有以下特点:

  • 单个服务规模小、相互独立且松散耦合,可以由小团队来完成开发和维护,并通过自动化流程部署和发布。
  • 每个服务的代码库都是独立的,可以单独进行集中式管理。服务支持独立的自动化部署,更新时无需重新部署整个应用程序。
  • 每个服务负责维护自己的数据和状态,不同于N层架构,没有单独的数据层负责数据持久性。单个服务很容易被替换。
  • 服务之间通过HTTP、REST API 或其他标准的轻量级通信协议进行通信,每个服务内部的实现细节均对其他服务隐藏。服务之间不需要使用相同的技术栈、库或框架。

微服务架构实现之后重要的特征:

  • 围绕业务能力构建 Organized around business capability
  • 分散治理 Decentralized Governance
  • 通过服务来实现独立的组件 Componentization via Service
  • 产品化思维 Product not project
  • 数据去中心化 Decentralized Data Management
  • 强终端弱管道 Smart EndPoint and DumbPipe
  • 容错性设计 Design for fault
  • 渐进式设计 Evolutionary Design
  • 基础设施自动化 Infrastructure Atuomation

相关架构模式

  • 单体架构
  • 事件驱动的架构
  • SOA 风格
  • 微内核架构

评价

微服务架构的优点

  • 敏捷:支持细粒度的独立迭代和发布,速度快。在很多传统应用程序中,如果在应用程序的一个组件中发现缺陷,整改发布流程都会被阻塞,需要等缺陷修复后才能进行集成、测试和发布,造成新功能发布延期。由于微服务架构中的每个小型服务是独立部署的,您可以轻松地对单个服务进行缺陷修复或者特性变更,无需重新部署整个应用程序,一旦发现缺陷立刻回滚服务。
  • 支持更小型、更专注的团队。单个小型服务仅需要一个小的开发团队就可以完成开发、测试和部署工作。相比之下,更大的团队通常意味着更低的沟通效率、更高的管理开销和更低的工作效率。
  • 支持更小型的代码库。在应用程序中,代码依赖项往往会随着时间的推移而变得繁杂。当您需要更新功能时,对应的可能要更新多处代码。由于微服务的代码库和数据存储都是独立的,所以可以最大程度地简化代码依赖,降低更新工作量。
  • 允许多种技术混搭,技术栈不受限制。您可以为每种服务选择最合适的技术,支持混合技术栈。
  • 故障隔离。在系统中出现问题时,例如内存泄露、数据库连接未关闭等情况,将仅仅只会影响单个微服务,不一定导致整个应用程序的中断。
  • 数据隔离。对于传统架构的应用程序,数据可能会被不同的服务调用,数据模式的升级风险很高。对于微服务架构,仅有单个服务受到影响,数据模式的升级风险较低。
  • 可伸缩性、扩展性和可维护性高。每个服务都支持独立水平扩展,无需扩展整个应用程序,资源的利用率高,扩展快速。每个微服务都可以独立地进行服务升级更新,结合持续集成工具可以进行持续发布,快速完成服务升级发布流程。

微服务架构的挑战

微服务架构虽然解决了很多问题,但使用起来也有自己的挑战:

  • 复杂性。与传统架构的应用程序相比,微服务架构的组件更多:每个独立的小型服务更简单,但是整个系统整体来讲更复杂了。服务数量多,也意味着部署和管理的工作量更大。同时,您可能还需要考虑分布式系统的复杂性和分布式事务处理难度。
  • 开发、测试、部署难度。开发依赖于其他独立服务的小型服务时,需要的方法与编写传统应用程序不同,现有工具并非总是能够处理好服务间的依赖关系。此外,服务拆分后,几乎所有功能都会涉及多个服务。原本单个程序的测试会变为服务间调用的测试、模块与模块之间的联调测试,测试会变得更复杂 。
  • 运维难度。由于在开发过程中可能采用了许多不同的语言和框架,应用程序可能会变得难以维护。此外,服务数量变多,会导致有服务出现故障的概率增大,而整个应用分散成多个服务,也会导致问题定位更加困难。这种情况下,建议您充分使用各种 链路追踪 和日志分析组件,提升可维护性。
  • 网络拥塞和延迟。使用大量小型服务可能会增加服务间的通信量。此外,如果服务间的依赖关系链过长,可能会进一步增加延迟。
  • 保证数据完整性和一致性的难度。每个小型服务都仅负责自己的数据持久性,因此,不同服务间的数据一致性很难保证。
  • 版本控制难度。 由于服务相对独立,更新某个服务时不必中断依赖于它的服务,更新时间随意且频度高,可能会导致服务间的兼容性问题。
  • 考验组织的成熟度,并非所有组织形态和合作模式都适合微服务架构。

微前端架构的借鉴

关注视角 微服务架构 微前端架构
康威定律:组织和软件架构
研发团队松散耦合(耦合度)
小而自治、跨功能型团队

- 服务拆解
- 独立的研发流程
- 独立的技术栈

- 应用拆解(代码拆解,杜绝寡头应用)
- 独立的研发流程
- 独立的技术栈
服务拆分
- 粒度控制(架构量子)
- DDD 方法论指导设计

- 微前端应用的结构拆解
- 按照业务应用 or 页面拆解
服务之间进程通信
- RPC 系统
- gRPC
- JSONWeb
- 通信格式
- JSON、XML、Protobuf
- RESTful 设计

- window.postMessage
- Virtual API 机制
- 直接 API 访问
- Shared Namespace
- …
隔离机制
- Pod(虚拟机制)
- Docker 容器

- JS 沙箱系统设计
- CSS 沙箱系统设计(ShadowDOM)
- ThreadWorker 机制设计
- iFrame 隔离机制(0 信任机制)
单元可以独立扩展
- SPI
- 服务整体替换(服务路由)

- 控制反转和依赖注入系统做扩展
- 子模块模式(可替换模式)
单元可独立部署、研发和交付
- DevOps 过程

- DevOPS 过程
单元之间具备更好的容错性
- 服务治理中关于「服务容错」

- 灰度方案
- 降级方案:天然支持 故障隔离
- A / B Test
独立可测试性
- 单元 / 集成 / 组件 / E2E 测试

- 单元测试 / 集成测试 / E2E 测试
独立可观测性
- 日志
- 分布式追踪

- 宿主和子应用的监控机制
- 故障链路 Trace 机制
服务治理(网格治理)
- 健康检查
- 日志聚合
- 分布式追踪
- 异常追踪
- 审计
- 流量控制

- 前端应用的体验、性能大盘(宿主、微应用)
- 灰度状态 & A|B Test 效果
分布式一致性保证
- ACID
- 事务一致性
不考虑
部署模式
- 容器化
- 容器编排 K8S
- Serverless

- CDN 模式
- 随服务端部署(专有云 or 混合云模式)
服务安全
- 认证协议
- 0 信任网络

- 验权机制
- iFrame 机制

连接