微服务的几种设计模式

举报
苏州程序大白 发表于 2022/03/21 14:21:26 2022/03/21
【摘要】 微服务的几种设计模式单体服务和微服务的对比,微服务包含的一些设计模式以及他们的概念和作用1.背景业务应用程序存在的问题业务不受管制的增长缺乏架构代码过长,像意大利面条隐藏的各种问题加上软件行业大爆发,移动互联网兴起,使得单体架构无法很好适应现代大规模互联网2.单体服务的局限性可扩展性不足开发速度慢,在单体服务中添加新功能改动很大,代码耦合程度高由于代码过于耦合,代码量增加后导致新人学习周期长...

微服务的几种设计模式

单体服务和微服务的对比,微服务包含的一些设计模式以及他们的概念和作用

1.背景

业务应用程序存在的问题

  • 业务不受管制的增长
  • 缺乏架构
  • 代码过长,像意大利面条
  • 隐藏的各种问题

加上软件行业大爆发,移动互联网兴起,使得单体架构无法很好适应现代大规模互联网

2.单体服务的局限性

  • 可扩展性不足
  • 开发速度慢,在单体服务中添加新功能改动很大,代码耦合程度高
  • 由于代码过于耦合,代码量增加后导致新人学习周期长,开发周期长,发布周期长
  • 当程序规模扩大后,单体架构的内部接口边界开始分崩离析

3.微服务的优缺点

定义:微服务架构是将软件系统分解为可独立部署的自治单元,这些单元通过轻量级、与语言无关的方式进行通信,并共同实现业务目标

优点:

  • 新技术的兴起,例如云计算、容器化(Docker、kubernetes)、DevOps、新兴语言(Golang、Rust)、敏捷软件开发、NoSQL等
  • 方便扩展
  • 开发速度快,每个人或团队负责一个微服务,共同开发
  • 发布周期短
  • 模块化,单体服务的边界是内部接口,微服务之间的边界是外部接口,所以具有高内聚、低耦合的特性
  • 每个微服务可以用不同语言编写,然后不同服务之间用同一的方式通信,如gRPC

缺点:

  • 设计复杂,微服务通常适用于较大型的系统,且解决方案众多,所以用对合适的方案很重要
  • 分布式系统复杂性,微服务是一个分布式系统,可能出现以下问题:整体系统延迟较高,网络故障或单个节点故障会导致整个系统崩溃,操作复杂性较高
  • 操作复杂,不同服务之间的日志记录、监控、追踪比单体服务更加复杂,所以基建工作所花费时间比单体服务更长
  • 安全性,同时保障多个服务之间的安全性具有一定挑战
  • 数据共享的数据一致性的保障困难

何时使用微服务

  • 网络规模的应用程序开发
  • 多个团队处理应用程序时的企业应用程序开发
  • 长期收益优于短期收益
  • 团队拥有能够设计微服务架构的软件架构师或高级工程师

4.微服务的设计模式

1.独享数据库

单体服务的时候一般是用一个大型中央数据库,但是到了微服务则不能所有服务都使用一个数据库,特别是在大规模系统中,这将导致微服务在数据库层严重耦合

更好的方法是为每个微服务提供自己的数据存储,这样数据库层的服务之间就没有强耦合,不同微服务可以共享同一个物理数据库,但它们应该使用单独的 Schema。

优点:

  • 数据由服务完全所有
  • 服务的开发团队之间耦合度降低

缺点:

  • 在服务之间共享数据变得具有挑战性
  • 提供应用程序范围的 ACID 事务保证变得更加困难

适用:

  • 在大型企业应用程序中
  • 当团队需要完全把控微服务以实现开发规模扩展和速度提升

不适用:

  • 小规模应用中

2.事件溯源(Event sourcing)

在传统数据库中,直接存储的是业务实体的当前“状态”,而在事件源中任何的“状态”更新事件、创建事件或其他重要事件,即快照,都会被存储起来,而不是直接存储数据实体本身,事件溯源是借鉴数据库事件日志的一种数据持久方式,在事件日志中记录导致状态变化的一系列领域事件,通过持久化记录改变状态的事件,重新播放获得状态改变的历史,事件回放可以返回系统到任何状态,使用事件溯源开发业务逻辑

优点:

  • 为高可伸缩系统提供原子性操作
  • 自动记录实体变更历史,包括时序回溯功能
  • 松耦合和事件驱动的微服务
  • 事件存储包括完整的审计跟踪,可以在需要严格监管的场景中派上用场。
  • 可以轻松地重建生产数据库。
  • 有多个为读优化的数据存储

缺点:

  • 从事件存储中读取实体成为新的挑战,通常需要额外的数据存储
  • 系统整体复杂性增加了,通常需要领域驱动设计

3.命令和查询职责分离(CQRS)

CQRS 建议将应用程序层分为两个方面,即命令端(Command)和查询端(Query)

查询端负责优化读取数据,从持久化获取数据,然后将它们映射到展现层表单,这些表单通常被标识为数据传输对象(DTO)

命令端关注优化写入数据,命令执行各种用例,修改实体状态并将其持久化

4.API网关(API Gateway)

客户端和微服务连通时,要面对如下挑战:

  • 一个客户端需要向多个微服务发送请求,则要多次往返服务器
  • 微服务中存在多种通信协议(gRpc、thrift、REST、AMQP 等),客户端很难所以协议都采取
  • 每一个微服务都有例如身份验证、授权、日志等功能

为了应对上述挑战,引入了一层网关层,位于客户端和服务器之间,主要有如下特性:

  • API网关提供了一个反向代理,将请求(第7层路由,通常是HTTP请求)重定向或路由到内部微服务
  • 聚合请求,将多个客户端对多个微服务的请求聚合到一个Gateway中,为客户端提供了与微服务系统进行通信提供了单一的入口,减少客户端和微服务之间的调用次数
  • 集中管理的横切关注点,整合边缘重复功能
    • 认证和授权,身份识别与访问管理(IAM)
    • 服务发现
    • 缓存响应结果
    • 重试策略、熔断器、服务质量(QoS)
    • 限速和节流
    • 负载均衡
    • log 日志、链路追踪、关联,集中式日志管理(服务之间的 transaction ID、错误日志等)
    • Header、query 字符串 以及 claims 转义
    • IP 白名单

缺点:

  • 单点故障
  • 额外的网络调用带来的延迟增加
  • 如果不进行扩展,它们很容易成为整个企业应用的瓶颈
  • 额外的维护和开发费用

5.面向前端的后端(BFF)

微服务架构中,前后端应用是分离和独立的服务,它们通过 API 或 GraphQL 连接,前端除了Web端还有移动端(ios,android……),因为移动客户端和 Web 客户端有不同的屏幕尺寸、显示屏、性能、能耗和网络带宽,它们的 API 需求不同。

BFF是 API 网关模式的一种变体,它提供了基于客户端的多个网关,而不是提供给客户端一个单一的入口点,目的是根据客户端的需求提供量身定制的 API,从而消除了为所有客户端制作通用 API 造成的大量的浪费,BFF 只是一种逻辑分层,而非一种技术。

如下图,每次访问该页面都需要发送 3 个请求,同时为了保障 Android,iOS,以及 Web 端的不同需求,需要为不同的平台写不同的 API 接口,而每当值发生一些变化时,需要 Android,iOS,Web 做出修改。与此同时,当我们需要对一个字符串进行处理,如限定 140 个字符的时候,我们需要在每一个客户端(Android,iOS,Web)分别实现一遍,这样的代价显然相当大。

加入 BFF 层,原本每次访问发送 3 请求页面,变成一个请求,有了 BFF 这一层时,就不需要考虑系统后端的迁移,后端发生的变化都可以在 BFF 层做一些响应的修改。

优点:

  • 分离 BFF 之间的关注点,使得可以优化不同的UI。
  • 提供更高的安全性。
  • 减少 UI 和下游微服务之间频繁的通信。

缺点:

  • BFF 之间代码重复。
  • 大量的 BFF 用于其他用户界面(例如,智能电视,Web,移动端,PC 桌面版)。
  • 需要仔细的设计和实现,BFF 不应该包含任何业务逻辑,而应只包含特定客户端逻辑和行为。

适用:

  • 如果应用程序有多个含不同 API 需求的 UI。
  • 出于安全需要,UI 和下游微服务之间需要额外的层。
  • 如果在 UI 开发中使用微前端。
  • 项目中时常存在一些需要缓存的临时数据,将该缓存操作放在 BFF 层,将与第三方的交互放在BFF层。
  • 服务中的权限控制,将所有服务中的权限控制集中在 BFF 层,使下层服务更加纯粹和独立。

6.断路器

在微服务架构中,微服务通过同步调用其他服务来满足业务需求。服务调用会由于瞬时故障(网络连接缓慢、超时或暂时不可用) 导致失败,这种情况重试可以解决问题。然而,如果出现了严重问题(微服务完全失败),那么微服务将长时间不可用,这时重试没有意义且浪费宝贵的资源(线程被阻塞,CPU 周期被浪费)。

在这种情况,可以使用断路器模式挽救,通过统计最近发生的故障数量,并使用它来决定是继续请求还是简单的直接返回异常,断路器可以有以下三种状态:

  • 关闭:断路器将请求路由到微服务,并统计给定时段内的故障数量,如果超过阈值,它就会触发并进入打开状态。
  • 打开:来自微服务的请求会快速失败并返回异常。在超时后,断路器进入半开启状态。
  • 半开:只有有限数量的微服务请求被允许通过并进行调用。如果这些请求成功,断路器将进入闭合状态。如果任何请求失败,断路器则会进入开启状态。

优点:

  • 提高微服务架构的容错性和弹性。
  • 阻止引发其他微服务的级联故障。

缺点:

  • 需要复杂的异常处理。
  • 日志和监控。
  • 应该支持人工复位。

7.外部化配置

每个业务应用都有许多用于各种基础设施的配置参数(例如,数据库、网络、连接的服务地址、凭据、证书路径),如果在微服务中把这些配置都内部化,当有数百个微服务的时候,改动配置将变得麻烦,还可能带来安全风险,更好的方法是将所有配置外部化,使得构建过程与运行环境分离,生产的配置文件只在运行时或通过环境变量使用,从而最小化了安全风险。

优点:

  • 生产配置不属于代码库,因而最小化了安全漏洞。
  • 修改配置参数不需要重新构建应用程序。
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。