读书笔记-SpringCloudAlibaba微服务原理与实战-谭锋-【未完待续】

SpringCloudAlibaba微服务原理与实战 谭锋 电子工业出版社

ISBN-9787121388248

仅供参考, 自建索引, 以备后查

 

 

一、应用架构演进、微服务发展史

 

 

 

 

 

 

 

二、SpringCloud简介

 

 

 

 

 

 

 

三、SpringBoot、自动装配、自定义Starter

 

 

 

 

 

 

 

四、ZooKeeper、 Dubbo (Dubbo、Apache Dubbo、Dubbo Spring Cloud)

 

 

 

 

 

 

 

五、Nacos服务注册发现

 

 

 

 

 

 

 

 

六、Nacos配置管理

 

 

 

 

 

 

 

 

七、Sentinel微服务限流及熔断

 

 

 

 

 

 

 

 

八、分布式事务

数据库事务:从事务开始到结束的所有数据库操作,要么同时成功,要么同时失败。

ACID:原子性 Atomicity 一致性 Consistency 隔离性 Isolation 持久性 Durability

分布式事务应用场景:单体数据库纵向拆分为多个平行的数据库后,由于数据库事务仅支持单个数据库,当需要对多库实现事务时,需用到分布式事务

分布式事务问题也叫 分布式数据一致性问题,实际应用中,就尽可能从设计层避免分布式事务问题


X/Open 分布式事务模型 2PC

X/Open DTP (X/Open Distributed Transaction Processing Reference Model)

两阶段提交(2PC, Two-Phase-Commit),包含有三种角色:

  1. AP:Application 用户应用程序
  2. RM:Resource Manager 资源管理器,即数据库等
  3. TM:Transaction Manager 事务管理器,事务协调者,为AP提供编程接口管理RM等。类似于 Spring 中 Transaction Manager

RM 注册到 TM,AP 从 TM 申请 RM 连接,生成全局事务并获取 XID。之后 AP 加入 XID 参数执行操作,事务结束,TM 通知事务结束并根据 RM 执行结果执行提交或回滚操作。TM 与 多个 RM 之间的事务控制是基于 XA (XA Specification) 协议来完成的,Oracle、MySQL、DB2 实现了此 XA 协议接口。

两阶段提交 2PC:

  1. 准备阶段:TM 通知 RM 准备分支事务,记录事务日志,反馈准备结果
  2. 提交/回滚阶段:任何一个 RM 执行失败则回滚,全部成功才提交

缺点:

  • 同步阻塞:所有参与者 RM 阻塞等待下一步指令
  • 过于保守:任何一个 RM 结点失败就回滚
  • TM单点故障:若 TM 故障则所有 RM 参与者会一直锁定
  • 数据不一致:多个 RM 在最后提交阶段出现局部故障

三阶段提交(加入超时机制,避免资源永久锁定)

  1. CanCommit 询问阶段:TM 询问 RM 是否可以执行指令
  2. PreCommit 准备阶段:TM 向 RM 发起 PreCommit 请求,RM 执行操作并写入 redo 和 undo 日志,等待下一步指令
  3. DoCommit 提交/回滚阶段:根据上一阶段执行结果告知 RM 执行 提交或回滚 操作

CAP定理

CAP定理,又名 布鲁乐定理。 简单来说指:在分布式系统中不能同时满足 一致性 Consistency、可用性 Availability 和 分区容错性 Partition Tolerance,最多同时满足两个,如满足 CP 或 AP,不可能实现 CAP 或 CA。原因是 网络通信 不是绝对可靠,网络延时、网络异常时常发生。

  • C:数据在多个副本中保持强一致,如主从数据库
  • A:系统对外提供访问,任何时候都能获得响应
  • P:分布式系统中遇到分区故障,系统仍能正常对外提供服务

CP 模式:两阶段与三阶段提交就是采用这种方案,可能导致用户完成操作需要等待较长时间的问题

AP 模式:放弃强一致,运用其它技术实现最终一致,AP 模式是解决分布式数据一致性问题的主要选择


BASE理论

基于CAP中CA模式不可实现而衍生的新思想,通过牺牲数据一致性获得高可用性,有以下有三个特性:

  1. Basically Available 基本可用:分布式系统出现故障时,允许损失部分功能的可用性,保证核心功能可用
  2. Soft State 软状态:允许数据存在中间状态,不影响系统可用性,就是数据副本同步之间允许存在延时
  3. Eventually Consistent 最终一致性:数据中间状态或延时,经过一段时间最终 数据一致

分布式事务问题常见解决方案 TCC补偿方案 (两阶段提交)

TCC (Try-Confirm-Cancel) 比较成熟的分布式数据一致性解决方案,把完整业务拆分为三个步骤:

  • Try:对数据校验或资源预留
  • Confirm:执行任务,只操作 Try 阶段的资源
  • Cancel:取消执行,释放 Try 阶段的资源

分布式事务问题常见解决方案 基于可靠性消息的最终一致性方案

互联网公司常用的方案,主要利用消息中间件 (Kafka RocketMQ RabbitMQ) 的可靠性机制来实现数据一致性。


分布式事务问题常见解决方案 最大努力通知型

与基于可靠性消息类似,适用于对数据一致要求不高的场景,如支付宝支付,用户支付之后,支付宝服务器会在一定时间内不停的通知用户程序,并提供交易结果查询接口。


分布式事务框架 Seata

开源分布式事务解决方案,主要针对微服务分布式事务,提供 AT、TCC、Saga 和 XA 事务模式。

Seata AT 模式 (两阶段提交)

Seata 主推方案,基于 XA 演进而来,分为 TM、RM 和 TC 三大模块。TM 与 RM作为 Seata 客户端与业务系统交互,TC 则作为 Seata 服务端独立部署。

Seata Saga 模式(多事务,若失败则挨个回滚)

又称长事务解决方案,主要用于在没有两阶段的情况下使用。核心思想是:跨多个数据库的业务流程拆分为多个本地短事务,之后若出现回滚操作,则对已提交的事务进行补偿。例如:对增加值的进行减法操作(对某些资源会出现一定的问题)

Seata 安装

独立安装、Docker、Kubernetes、Helm 等方式。

Linux/Mac 下启动

# sh seata-server.sh

# sh seata-server.sh -p 8091 -h 192.168.0.120 -m file   指定机器端口及file存储模式

可以使用 -m db 来使用 db 模式存储相关数据,并在文件 \conf\file.conf 中配置数据库连接

全局事务 globaltable 、分支事务 branchtable、全局锁 lock_table

\conf\registry.conf

其中 registry 表示使用的注册中心组件,如 nacos、zookeeper,默认情况是 file 可快速集成 Seata,但 file 模式不具备注册中心的动态发现与动态配置功能;

而 config 则用于配置 Seata 服务端,通过此项设置 Seata 服务端的加载的配置文件,支持从远程配置中心读取或本地读取,远程读取设置的设置方式与 registry 相同。

\conf\file.conf

存储 Seata 服务端的配置信息,包含 transport、server、metrics 分别表示 协议配置、服务端配置、监控

配置中心加载配置信息

使用 Nacos 作为配置中心


Seata AT 模式集成 Dubbo 

示例:订单服务、库存服务、账户服务、公共服务、业务REST接口服务;服务之间相互调用

分布式数据库:seata_order、seata_repo、seata_account 共三个

每个服务创建单独 module 并引用相关依赖

逐个启动服务并访问 业务REST接口服务 对外的接口

添加Seata分布式事务

引用Seata的Starter组件依赖

application.yml中添加Seata配置项

在各个数据库中添加 回滚日志表

添加全局事务控制 @GlobalTransactional

Spring Cloud Alibaba 集成 Seata AT 模式

添加 Spring Cloud Alibaba Seata 依赖,由于不支持 yml 形式,只能用 file.conf 与 registry.conf 来配置。

在访问数据库中的服务中,添加配置类,设置 数据源代理DataSourceProxy、初始化GlobalTransactionalScanner装载到Spring IOC容器

注意 @SpringBootApplication(exclude=GlobalTransactionalAutoConfiguration.class)


Seata AT 模式实现原理

AT模式从XA事务模型演进而来,也是一个 改进版的两阶段提交协议

修改前修改后的数据存入 undo_log 表中,之后释放本地事务锁定的资源,若之后阶段出现异常,则根据 undo_log 进行回滚。

在 XA 中则会一直锁定资源到最后阶段,这是最大的不同点。

TC收到所有事务分支的事务状态汇报后,来决定提交或回滚。

若提交:清理 undo_log 的回滚数据即可,毕竟之前一步中,所有分支事务都已经提交了。

若回滚:根据 undo_log 的数据进行补偿,只要各个分支事务回滚成功,数据一致性就得到保证了。

ACID中的隔离性,指的是:多个用户并发访问数据库时,多个并发事务之间要相互隔离,互不干扰。

AT模式中,多个全局事务操作同一张表时,事务隔离性是基于全局锁来实现的,

写隔离:(针对同一张表同一字段的更新)分布式事务分为本地锁(数据库锁)和全局锁(分布式锁),本地锁获取后只要是全局锁获取不成功,最终不会提交,会回滚。因此就算多个事务同时执行,仍不会发生脏写;

读隔离:Read Uncommitted 读取未提交内容、Read Committed 读取提交内容、Repeatable Read 可重读、Serialiable 可串行化

 

 

 

九、RocketMQ 分布式消息通信

多个服务之间相互通信 即 系统间通信协作通常有两种:

HTTP/RPC 通信实时,但耦合性高;

消息通信 降低耦合,提高系统处理能力,但非实时

RocketMQ 是分布式消息中间件(消息队列),阿里巴巴经多年双11难的一个低延迟、高可靠、可伸缩、易于使用的消息框架,提供顺序消息、事务消息、定时消息、消息重试和追踪等功能。应用场景:削峰填谷(解决突发的大量请求)、异步解耦(主要业务完成后附加业务异步通知执行)、顺序收发(各个子业务之间需要先后执行,如先扣款再发货之后收货等)、分布式事务一致性(交易系统与支付系统要最终数据一致)、大数据分析、分布式缓存(各服务器缓存数据,接收通知更新缓存)。

安装:依赖JDK1.8及以上,分三种集群部署模式,可源码安装或w使用安装包。

发消息Spring Cloud Alibaba 已集成 RocketMQ,使用 Spring Cloud Stream 即可。

引入依赖、配置连接信息等、编码使用Binder发送消息

@EnableBinding({Source.class}) 绑定配置文件中名称为 output 的消息通道,output 在 Source 类中定义。

可以自定义消息通道,参考 Source,使用 @Output("order_output") 即可定义一个 order_output 消息通道;当然,需要在配置文件中配置 order_output 的配置项。

接收消息:引入依赖、配置连接信息等、编码监听消息

@EnableBinding({Sink.class}) 默认存在 input 的消息通道,使用 @StreamListener(value=Sink.INPUT) 标记方法用于接收消息。

同样可以自定义,参考  Sink,使用 @Input("order_input") 即可定义 order_input 消息通道;同样需要进行配置 order_input 配置项。


Spring Cloud Stream:用于简化 Spring Cloud 应用程序中消息业务的开发。

应用程序通过注入输入通道 input 和 输出通道output 与 消息中间件Middleware通信,输入输出通道通过绑定器 Binder 连接到外部代理。

此框架基于 发布/订阅 机制,

核心由四部分构成: SpringFramework 中的 Spring Messaging 和 Spring Integration,以及 Spring Cloud Stream 中的 Binders 和 Bindings。

Spring Messaging:Spring Framework 中的统一消息编程模型 

Message(消息对象,包含消息头Header和消息体Payload)、

MessageChannel(消息通道接口,用于接收发送消息)、

MessageHandler(消息处理接口)

Spring Integration:Spring Framework 中用于支持企业集成的扩展机制,对 Spring Messaging 进行扩展

MessageDispatcher(消息分发接口,用于分发消息和添加删除消息处理器)

MessageRouter(消息路由接口,定义默认输出消息通道)

Filter(消息过滤注解,配置消息过滤表达式)

Aggregator(消息聚合注解,用于多条消息合并)

Splitter(消息分割,一条消息拆分为多条)

Binders:目标绑定器,负责与消息中间件集成

doBindProducer(绑定消息中间件发送消息模块)

doBindConsumer(绑定消息中间件接收消息模块)

Bindings:外部消息中间件系统与应用程序的生产者和消费者(由Binders创建)之间的桥梁


Spring Cloud Alibaba RocketMQ 架构图 

读书笔记-SpringCloudAlibaba微服务原理与实战-谭锋-【未完待续】_第1张图片

MessageChannerl(output)、MessageChannel(input) 为消息通道,用于发送订阅消息,Spring Cloud Stream标准接口

Binder bindProducer、Binder bindConsumer 目标通道绑定器,与RocketMQ消息服务器交换消息,即发布与接收消息,

由 Spring Cloud Alibaba 按照 Spring Cloud Stream 标准协议实现


Spring Cloud Stream 消息发送流程

读书笔记-SpringCloudAlibaba微服务原理与实战-谭锋-【未完待续】_第2张图片

业务代码调用 MessageChannel send();

org.springframework.integration.channel.AbstractMessageChannel 是接口 MessageChannel 的抽象实现类,定义发送、接收消息的公用方法;

消息传递到 org.springframework.integration.channel.AbstractSubscribableChannel 类,执行 doSend(),方法中 获取 MessageDispatcher 的实现类 UnicastingDispatcher;

调用 org.springframework.integration.dispatcher.UnicastingDispatcher dispatcher() 把消息分发给所有的 MessageHandler;

MessageHandler 执行 handleMessage() 处理消息。

注册 MessageHandler 是通过 org.springframework.cloud.stream.binder.AbstractMessageChannelBinder 在初始化 Binding 时执行 doBindProducer 调用 AbstractSubscribableChannel subscribe() 设置的。

AbstractMessageChannelBinder 的初始化则由 org.springframework.cloud.stream.binding.AbstractBindingLifecycle 在 Spring 容器加载 Bean 完成初始化后执行的。


RocketMQ Binder 集成消息发送 

同时 AbstractMessageChannelBinder 提供了创建 MessageHandler 的规范,即调用 abstract 方法 createProducerMessageHandler(),而 com.alibaba.cloud.stream.binder.rocketmq.RocketMQMessageChannelBinder 则是实现了此方法并创建了 com.alibaba.cloud.stream.binder.rocketmq.integration.RocketMQMessageHandler 实例,是 MessageHandler 的 RocketMQ 具体实现,在 RocketMQBinder 中实现转化消息格式并发送消息。

RocketMQMessageHandler 中有 org.apache.rocketmq.spring.core.RocketMQTemplate 对象,是对 RocketMQ 客户端API的封装,SpringBoot支持RocketMQTemplate,SpringCloudStream对其同样兼容。

DefaultMQProducer 是 RocketMQ 客户端提供的 API,用于将消息发送到 RocketMQ 消息服务器。

RocketMQMessageHandler 则对 Message 进行解析,根据参数设置调用不同实现。如根据Header属性决定发送普通消息、事务消息、定时消息或顺序消息。


RocketMQ Binder 集成消息订阅

AbstractMessageChannelBinder createConsumerEndpoint() 用于创建 MessageProducer ,在初始化Binder时调用。

RocketMQMessageChannelBinder 具体实现了 createConsumerEndpoint() 并创建了 com.alibaba.cloud.stream.binder.rocketmq.integration.RocketMQInboundChannelAdapter 对象,此类是接口 MessageProducer 的实现类,其适配了 SpringFramework的重试和回调机制,用于在 RocketMQ Binder 中订阅消息并转化消息格式。

com.alibaba.cloud.stream.binder.rocketmq.consuming.RocketMQListenerBindingContainer 是接口 RocketMQListenerContainer 的实现,通过 setupMessageListener() 方法设置 RocketMQListener 来消费消息。DefaultMessageListenerOrderly 与 DefaultMessageListenerConcurrently 是 MessageListener 的两种实现,顺序消费和并发消息。在 consumeMessage() 执行时会调用 RocketMQListener onMessage() 来调用业务代码处理消息。


Spring Cloud Stream 消息订阅流程

读书笔记-SpringCloudAlibaba微服务原理与实战-谭锋-【未完待续】_第3张图片

企业Binder 收到订阅消息,发送到 MessageChannel,再通过 Dispatcher 调用 MessageHandler,最后调用 @StreamListener 注解标记的方法调用业务方法。

RocketMQInboundChannelAdapter extends MessageProducerSupport 调用 sendMessage() 发送消息。 

方法内部调用 getOutputChannel 得到初始化 RocketMQ Binder 时传入的 DirectChannel 通道。

MessagingTemplate extends GenericMessagingTemplate 执行 send() 再次发送消息,通过 DirectChannel 通道获取 MessageDispatcher 的实现类 UnicastingDispatcher;

之后进行消息分发,传递消息给 MessageHandler。

DirectChannel 对应的消息处理器是 StreamListenerMessageHandler ,此处理器会调用使用 @StreamListener 注解标记的业务方法。

StreamListenerAnnotationBeanPostProcessor 扫描类找到使用 @StreamListener 标记的 Method,并创建 StreamListenerHandlerMethodMapping 对象,保存了映射关系。

映射关系为 StreamListener 到 HandlerMethod。因此在 StreamListenerMessageHandler 处理器中可以调用 @StreamListener 的业务方法。


RocketMQ 集群管理

分布式服务SOA中,中间件和应用不允许单点存在,服务发现机制因此是必备的。

RocketMQ 是淘宝中间件团队参考 Kafka 重新设计用 Java 编写出来的,因此概念会有 Kafka 相似。

Kafka、RabbitMQ、RocketMQ 等都是基于 发布/订阅 机制,消息发送方Producer 发送消息到 消息服务器,消息接收方Consumer 从 消息服务器订阅消息。 发送方与接收方为客户端,消息服务器是服务端,客户端与服务端需要通过 注册中心 来感知对方。

RocketMQ 架构四大组件

Producer:消息提供者,发送消息到 Broker,支持分布式集群方式部署

Consumer:消息接收者,负责从 Broker 订阅消费消息,同样支持分布式集群方式部署

Broker:消息存储角色,用于消息存储、投递和查询,具有服务高可用保证,支持分布式部署

NameServer:服务管理角色,负责管理 Broker 集群的路由信息,支持分布式集群方式部署。 简单Topic模式的路由注册中心,类似于Dubbo中的Zookeeper、Nacos,支持 Broker 动态注册与发现。包含 服务注册(接收Broker注册信息,保存并启动心跳检查) 和 路由信息管理(提供给客户端查询Broker接口,因此客户端可以与Broker进行消息发送与接收)。

基本概念:

Message:消息,传输信息的物理载体,生产和消费数据的最小单位。必须关联一个Topic,且拥有唯一MessageID,并可携带具有业务标识的Key

Topic:主题,一类消息的集合,包含若干消息,Topic是RocketMQ进行消息订阅的基本单位

Queue:消息队列,组成Topic的最小单元。默认情况是一个Topic对应多个Queue。Topic是逻辑概念,Queue是物理概念。消费Topic消息实际是拉取Queue消息。

Tag:区分同一个主题下不同类型的消息,优化RocketMQ的消息查询系统,且可以根据Tag实现不同的处理逻辑,扩展性更好

UserProperties:用户自定义属性,属于Message一部分

ProducerGroup:同类Producer集合,发送消息逻辑一致的一组服务器。当某台消息提供者出问题,则Broker从组内选取其它一台进行交互

ConsumerGroup:同类Consumer集合,接收消息后的处理逻辑一致的一组服务器,订阅了相同的Topic消息

ZooKeeper VS NameServer

Kafka服务注册与发现通常用ZooKeeper来完成,在Kafka中,Topic是逻辑概念,分区(Partition)是物理概念。1个Topic可以设置多个分区,每个分区又可以设置多个副本(Replication),即1 Master - N Slave 模式。 Master是经过选举得出的,Broker实例具有Master/Slave双重身份,就看选举结果如何了。

RocketMQ使用NameServer,Topic也是逻辑概念,队列(Queue)是物理概念(与kafka的分区对应),同样 1 Master - N Slave 模式。Master与Slave是预告设置的。

本人根据书中介绍得到的是,Kafka中,Master和其对应的Slave在同一个进程中进行管理,而Rocket则用不同进程来管理Master与Slave。有其它见解或者实际研究过的欢迎来更正、来打扰


顺序消息 :业务流程需要先后次序时使用,实现类似对列FIFO的效果;分为 局部有序 和 全局有序

局部有序:发送到同一队列的消息有序,发送时需指定队列。

发送:设置输出通道的 sync=true     e.g. spring.cloud.stream.rocketmq.bindings.output.producer.sync=true;消息发送时,指定Header头信息  MessageBuilder.withPayload(message).setHeader(BinderHeaders.PARTITION_HEADER,0);

接收:设置接收通道的 orderly=true    e.g. spring.cloud.stream.rocketmq.bindings.input.consumer.orderly=true。

全局有序:设置Topic指定全局有序,性能差,不推荐使用

发送方式:同步、异步、单向

同步:发送请求后等待Broker服务器返回,支持失败重试,适用较重要的场景

异步:异步发送消息,不阻塞进程,不支持失败重试,适用响应时间要求高的场景

单向:与异步一致,但不支持回调,应用于时间要求超高,可靠性要求不高的场景

 

 

 

 

 

 

 

十、Spring Cloud Gateway

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(Java)