热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

微服务架构与实践笔记(三)微服务关键技术之服务接入

本文参考文献----《微服务架构与实践(第2版)》电子工业出版社出版 王磊 等著


服务接入

  • 边缘服务:边缘服务的作用是简化外部消费者对系统的调用。它可以是纯前端的页面,用于获取多个服务的数据后提供给消费者,也可以是聚合类服务,将结果进行聚合后返回给消费者。

    边缘服务的典型场景是支撑多样化的消费者,这种情况有时候也称作 BFF(Backend for Frontend)。譬如在支撑多种终端设备的应用中,通常会对服务的结果做必要的聚合或者裁剪,然后提供给不同的设备,如 PC 端或者其他设备等。Netflix 在其微服务的实现中,通过 BFF 为几十种设备提供不同的视频数据。

  • API 网关(API Gateway):同边缘服务类似,API 网关的存在也是为了简化消费者对系统的调用。不过它更关心的是将请求有效路由到服务,而非业务逻辑的聚合。

    API 网关的主要功能如下所示:

    1. 请求路由。API 网关位于服务的外层,消费者端先将请求发送到网关,网关再路由至各服务。
    2. 协议转换。对于某些场景,服务内部实现的接口可能与消费者端期望的接口不一致。如内部使用 RPC 或私有协议,而消费者端期望 REST 接口。此时就需要通过网关完成协议的转换。
    3. 公共功能。因为 API 网关是微服务系统中的集中化部分(它同所有服务交互)。因此在实际落地过程中,可以将服务内部所需的一些公共功能,如认证、鉴权、限流、流量统计等,移至 API 网关实现,降低修改和升级成本。

    API网关的实现如下:
    微服务架构与实践笔记(三)微服务关键技术之服务接入
    另外,在某些系统中,会将 API 网关作为聚合服务使用。不过笔者建议,避免将复杂的聚合逻辑放在网关内。主要原因是:

    1. 确保网关职责单一,聚焦于请求路由等功能,而非复杂逻辑的实现。
    2. 降低其替换成本。网关是服务系统中的支撑组件,随着技术的演进,应持续演进并使用更有效的技术替换。

    使用 API 网关,具有如下明显的优势:

    1. 屏蔽服务的接口变化。API 网关的存在,使消费者端使用的接口与服务内部的接口隔离开。当服务内部的接口发生变化时,可以通过网关屏蔽对消费者端的影响。
    2. 降低公共功能的维护成本。对于某些微服务系统的公共功能,如认证、授权、SSL、流量统计、流控等,通过在网关内统一处理,降低了维护成本。

    虽然 API 网关有如上所述的优点,但它也会带来新的问题:API 网关是对外的唯一入口,其发生故障将导致整个系统的不可用,API 网关性能下降会导致所有服务的性能下降。因此,需要做好 API 网关的无状态、可用性设计,并对 API 网关进行性能实测,保障具备足够的应对突发流量的能力。

  • 数据一致性
    分布式系统与数据一致性:单体应用通常会使用单一的关系型数据库来存储数据,事务的 ACID 机制会保障数据的一致性。

    • 原子性(Atomic):一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
    • 一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
    • 隔离性(Isolation):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(serializable)。
    • 持久性(durability):事务处理结束后,对数据的修改就是永久的,即便系统有故障时也不会丢失。

    微服务架构的分布式特性带来了数据一致性问题。通常在微服务架构中,每个服务可能拥有独立的数据库。当服务间调用引发数据的修改时,如果中间的步骤出错,就会出现数据不一致的情况。

    CAP 原则是指在分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错(Partition Tolerance)三者不可兼得,只能选择其中两个。

    • 一致性:对于同样的请求,访问到不同的节点时,返回的结果是相同的。数据一致性还包括强一致性和弱一致性。强一致性是指,更新完成后,任何后续的请求都返回更新过的值,这需要牺牲可用性。弱一致性是指,在写入完成后,不保证后续访问都会返回更新过的值。
    • 可用性:在任何时候,节点都能对请求做出响应。
    • 分区容错:当网络出现问题时,系统整体仍然可以工作。

    虽然上面提到 CAP 原则是三选二,但并不是说另外一个维度就无法满足需求。以 Google 的 Spanner 为例,它是满足「C」和「P」的系统,但其可用性依然可以达到 5 个 9。

    最终一致性及实现方式:基于 CAP 理论以及互联网一些产品的分布式实践,技术人员发现,在无法实现强一致性的情况下,可以采用适当的方法达到最终一致性。于是出现了 BASE 理论,即基本可用(Basically Available)、软状态(Soft State)和最终一致性(Eventual Consistency)。

    • 基本可用。在分布式系统出现故障时,允许系统的可用性下降或者部分可用,譬如因为网络故障导致延迟的增加,或者当请求过多时,系统提供熔断或降级的功能。
    • 软状态。系统中的数据可以存在中间状态。在不影响整体可用性的情况下,可以容忍数据的同步延迟。
    • 最终一致性。系统在没有后续更新的前提下,返回上一次更新后的值,保证最终返回数据的一致性。

    最终一致性的实现方式包括 2PC(2 Phase Commitment Protocol,两阶段提交协议)、3PC(3 Phase Commitment Protocol,三阶段提交协议)、TCC(Try-Confirm-Cancel,尝试-确认-取消)以及 Sagas(补偿交易)。

    • 两阶段提交:两阶段提交引入协调服务(协调者),其根据所有参与者反馈内容决定是提交事务操作,还是中止事务操作。分布式系统中的节点(参与者)虽然知道自己的操作状态(成功或者失败),但是无法知道其他节点的操作结果。为了保证数据的一致性,需要引入协调的组件来统一协调节点的操作结果,并最终指明节点是否要把操作结果进行真正的提交(比如将更新后的数据写入数据库)。两阶段提交,顾名思义就是分为两个阶段:准备阶段和提交阶段。

      在准备阶段,协调者查询所有参与者(数据库),确认是否准备好事务提交(将事务执行到准备提交的阶段),协调者只有在收到肯定的回答后才进入下一个阶段。

      在提交阶段,协调者通知参与者执行提交,每个参与者执行提交,并释放事务占用的锁和资源,返回成功的确认。协调者收到所有的参与者成功的确认后,才认为本次分布式事务完成。

      如果在准备阶段出错,协调者通知所有参与者回滚事务,释放事务的资源和锁,并返回确认结果。如果所有回滚都成功,则协调者回滚此次事务。

      两个阶段提交的原理和实现比较容易理解。实际上,在两阶段提交中可能存在一些挑战:首先,协调者存在单点故障问题,一旦协调者失败,参与者的事务将会处于阻塞状态,妨碍参与者对外提供服务。参与者的提交都需要通过协调者调度,中间处于同步阻塞状态,效率比较低。此外,两阶段提交不能完全解决数据一致性问题,因为在提交阶段如果出现网络问题,某些参与者可能由于没有收到提交的消息而阻塞。两个阶段的提交示意图,如下图所示。
      微服务架构与实践笔记(三)微服务关键技术之服务接入

    • 三阶段提交:针对两阶段提交的问题,主要是协调者失败引发的问题,三阶段提交进一步将准备阶段又划分为两个阶段,并引入了超时策略来缓解阻塞的问题。所以三阶段提交就变成了:确认能否进行事务操作、预提交和提交。

      在事务执行的确认阶段,协调者发送查询请求,如果参与者拒绝或者返回超时,则协调者认为事务失败,给所有参与者发送取消的消息。反之,参与者进入预提交阶段的准备状态。预提交阶段和 2PC 的准备阶段区别不大,如果收到协调者的取消事务消息,好预提交失败或者等待超时,参与者都会取消操作。如果收到协调者发来的预提交消息,则参与者返回确认(成功/失败),并等待最终协调者发送的提交的消息。如果协调者出现错误、超时或者收到参与者否定的消息,协调者取消事务并给所有参与者发送取消消息。反之则发送提交的消息给所有参与者。

      提交阶段,如果协调者在等待参与者的确认消息时超时,会取消事务。参与者收到预提交消息后,如果协调者超时或者失败,参与者继续完成提交的操作。

      3PC 虽然解决了 2PC 中同步阻塞的问题,以及在协调者和部分参与者失败的情况下出现的数据不一致的问题,但是如果在提交阶段,参与者因为网络原因没有收到取消事务的消息,在超时的情况下继续提交,仍然会出现数据不一致的情况。三个阶段的提交示意图
      微服务架构与实践笔记(三)微服务关键技术之服务接入

    • TCC模式:在微服务的分布式场景下,业务运行流程可能较长,采用传统 ACID 的事务方式会造成运行等待时间过长。除了前面提到的 2PC/3PC 的事务处理方式,还可以采用事务补偿的方式,即先执行正常的业务逻辑,当出现问题时,如流程中某些环节出错,再执行补偿的动作,即取消或者重试。TCC(Try-Cancel-Confirm)就是补偿交易的一种方式,它通过对业务逻辑的调度实现分布式事务。整个过程分为两个阶段:Try、Cancel 或者 Confirm

      第一阶段,执行正常流程中的业务尝试操作(Try),并在协调者中注册所有的操作,即确认操作(Confirm)和取消操作(Cancel),同时修改子业务在数据库中的状态

      第二阶段,如果第一阶段的操作都成功,则协调者执行各子业务的确认操作。反之如果失败或者超时,则执行取消操作。这一阶段的操作应该是幂等的,以保证在操作出错、超时的时候可以重试
      微服务架构与实践笔记(三)微服务关键技术之服务接入

    • Sagas模式:Sagas 是一种失败管理模式,用来解决运行时间较长的事务,如分布式事务的问题。

      Sagas 模式基于 Hector Garcia-Molina 等发表于 1987 的论文Sagas。Sagas 由子事务的集合组成,每个子事务(称为 Saga,或者请求)都具有事务补偿的功能(撤销操作)。子事务要么全部执行成功,要么因为某些子事务执行失败,会导致所有子事务回滚,这里对于回滚操作的要求是满足幂等性。

      Sagas 损失了事务的原子性,但保证了分布式系统的可用性。Sagas 可以解决 2PC 在分布式系统场景下扩展性不足的问题。以出行场景为例,一个行程规划的事务就相当于一个 Saga,其中包含四个子事务:机票预订、租车、酒店预订、支付,如下图所示。根据上面的 Sagas 运行原理,可以定义出行程中关联事务以及相应的补偿,如下表所示。
      微服务架构与实践笔记(三)微服务关键技术之服务接入
      Sagas 中的事务相互关联,应作为(非原子)单位执行。任何未完全执行的 Saga 是不满足要求的——如果产生事务,必须得到补偿。要修正未完全执行的部分,每个 Saga 子交易 T1 应提供对应补偿事务 C1。当每个 Saga 子事务 T1,T2,…,Tn 都有对应的补偿定义 C1,C2,…,Cn-1 时,在最佳情况下 Saga 系统可以保证子事务序列 T1,T2,…,Tn完成,或者完成序列 T1,T2,…,Tj,Cj,…,C2,C1,0微服务架构与实践笔记(三)微服务关键技术之服务接入
      通过上述定义的事务/补偿,Sagas 可以保证数据的一致性,并满足如下业务规则:

      • 所有预定都被执行成功,如果任何一个执行失败,都会被取消
      • 如果最后一步付款失败,所有预订也将被取消

      Saga适用的场景如下:

      • 嵌套调用。如在网上购物时,会依次经过下单、支付服务和第三方支付这几个子事务,其中下单依赖于支付服务的返回状态,而支付服务也包含了多种可选的支付方式,并依赖于具体支付方式返回的结果。通过 Saga 可以清晰地看到一个完整事务中各个服务之间的关系,在异常时也能快速定位出现问题的子事务
      • 高并发。如在秒杀场景下,在成功扣除库存和完成支付后方可认为秒杀成功,若成功扣除库存但支付失败,则自动进行补偿(即恢复库存)。鉴于 Saga 只有提交和补偿两种状态,在成功场景下只需对每个子事务进行一次调用即可,因此可以在高并发下保持高性能。
      • 调用时间长。如在线上购买电影票,选好座位后一般会有 15 分钟的支付时间。Saga 仅在子事务的提交阶段对资源进行短暂的锁定,且通过超时机制确保事务超时后能自动补偿,即在规定时间内没有支付成功就自动释放锁定的座位,极大地简化了业务出现异常时的处理逻辑。

      Saga 的解决方案比两阶段提交更易扩展。在事务可补偿的情况下,Saga 相比 TCC 对业务逻辑几乎没有改动,性能更高。集中式的 Saga 设计解耦了服务与数据一致性逻辑及其持久化设施,并更容易排查事务中的问题。

      Saga 目前已经有一些成功使用的案例,比如微软的大型在线射击游戏 Halo。Saga 的实现通常需要 SEC(Saga Execution Coordinator)来协调子事务的执行和回滚,还需要 Saga Log (类似 Mysql 数据库的 bin log)记录子事务执行的记录。SEC 将操作写入 Saga Log,应用每个 Saga 的子事务(请求),并且在需要的时候回滚事务。Saga Log 可以是分布式的,使用类似 Kafka 的消息队列工具实现。子事务最多执行一次,但是补偿事务至少执行一次。在所有子事务完成时或者子事务开始回滚时,如果 SEC 本身失败,并不会对最终结果有影响。在其他场景下,SEC 失败则认为事务失败,并且可以根据 Saga Log 的记录来回滚操作。

    解决方案对比分析:
    微服务架构与实践笔记(三)微服务关键技术之服务接入


上一篇 微服务架构与实践笔记(二)微服务关键技术之服务划分与实现


推荐阅读
  • 云原生应用最佳开发实践之十二原则(12factor)
    目录简介一、基准代码二、依赖三、配置四、后端配置五、构建、发布、运行六、进程七、端口绑定八、并发九、易处理十、开发与线上环境等价十一、日志十二、进程管理当 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
  • 一句话解决高并发的核心原则
    本文介绍了解决高并发的核心原则,即将用户访问请求尽量往前推,避免访问CDN、静态服务器、动态服务器、数据库和存储,从而实现高性能、高并发、高可扩展的网站架构。同时提到了Google的成功案例,以及适用于千万级别PV站和亿级PV网站的架构层次。 ... [详细]
  • MySQL数据库锁机制及其应用(数据库锁的概念)
    本文介绍了MySQL数据库锁机制及其应用。数据库锁是计算机协调多个进程或线程并发访问某一资源的机制,在数据库中,数据是一种供许多用户共享的资源,如何保证数据并发访问的一致性和有效性是数据库必须解决的问题。MySQL的锁机制相对简单,不同的存储引擎支持不同的锁机制,主要包括表级锁、行级锁和页面锁。本文详细介绍了MySQL表级锁的锁模式和特点,以及行级锁和页面锁的特点和应用场景。同时还讨论了锁冲突对数据库并发访问性能的影响。 ... [详细]
  • Sleuth+zipkin链路追踪SpringCloud微服务的解决方案
    在庞大的微服务群中,随着业务扩展,微服务个数增多,系统调用链路复杂化。Sleuth+zipkin是解决SpringCloud微服务定位和追踪的方案。通过TraceId将不同服务调用的日志串联起来,实现请求链路跟踪。通过Feign调用和Request传递TraceId,将整个调用链路的服务日志归组合并,提供定位和追踪的功能。 ... [详细]
  • 基于事件驱动的并发编程及其消息通信机制的同步与异步、阻塞与非阻塞、IO模型的分类
    本文介绍了基于事件驱动的并发编程中的消息通信机制,包括同步和异步的概念及其区别,阻塞和非阻塞的状态,以及IO模型的分类。同步阻塞IO、同步非阻塞IO、异步阻塞IO和异步非阻塞IO等不同的IO模型被详细解释。这些概念和模型对于理解并发编程中的消息通信和IO操作具有重要意义。 ... [详细]
  • 解决VS写C#项目导入MySQL数据源报错“You have a usable connection already”问题的正确方法
    本文介绍了在VS写C#项目导入MySQL数据源时出现报错“You have a usable connection already”的问题,并给出了正确的解决方法。详细描述了问题的出现情况和报错信息,并提供了解决该问题的步骤和注意事项。 ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • 本文介绍了OpenStack的逻辑概念以及其构成简介,包括了软件开源项目、基础设施资源管理平台、三大核心组件等内容。同时还介绍了Horizon(UI模块)等相关信息。 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了软件测试知识点之数据库压力测试方法小结相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 上图是InnoDB存储引擎的结构。1、缓冲池InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。因此可以看作是基于磁盘的数据库系统。在数据库系统中,由于CPU速度 ... [详细]
  • 本文总结了初学者在使用dubbo设计架构过程中遇到的问题,并提供了相应的解决方法。问题包括传输字节流限制、分布式事务、序列化、多点部署、zk端口冲突、服务失败请求3次机制以及启动时检查。通过解决这些问题,初学者能够更好地理解和应用dubbo设计架构。 ... [详细]
  • ejava,刘聪dejava
    本文目录一览:1、什么是Java?2、java ... [详细]
author-avatar
沈畅棉多多_574
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有