《架构世界》2020微服务刊:微服务分布式事务实战
上QQ阅读APP看书,第一时间看更新

3.分布式事务实战

如何在项目中运用servicecomb-pack,需要进行以下步骤:

alpha-server配置

编译alpha-server

1.环境准备

JDK1.8

Maven3.x

2.源码获取

Github地址:https://github.com/apache/servicecomb-pack

$ git clone https://github.com/apache/servicecomb-pack.git

$ git checkout 0.4.0

3.修改配置文件

找到alpha-server/src/main/resource/application.yaml,修改datasource信息为本地信息即可

4.本地构建alpha-server

$ cd servicecomb-pack

$ mvn clean install -DskipTests-Pspring-boot-2

在执行玩命令之后,可在alpha/alpha-server/target/saga/alpha-server-${version}-exec.jar中找到alpha-server的可执行jar

5.初始化数据库

可在alpha\alpha-server\src\main\resources目录下找到schema-mysql.sqlschema-postgresql.sql两个sql文件,可自行根据所选数据库进行初始化即可。

6.启动alpha-server


java -Dspring.profiles.active=prd

-D"spring.datasource.url=jdbc:postgresql://${host_address}:5432/saga?useS

SL=false" -jar alpha-server-${saga_version}-exec.jar

注意:请在执行命令前将${saga_version}和${host_address}更改为实际值

至此,alpha-server全局事务管理器已经启动成功。

替换postgresqlmysql

目前alpha-server支持pgmysql两种数据库,默认为pg,如需改为mysql,需要进行如下操作:

1.安装并运行mysql

2.修改pom文件,添加依赖

alpha-server/pom.xml,添加mysql依赖


dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<scope>runtime</scope>

<version>8.0.15</version>

</dependency>

3.修改配置文件

找到alpha-server/src/main/resource/application.yaml,修改datasource信息为本地信息即可


spring:

profiles: mysql

datasource:

username: ${username}

password: ${password}

url: jdbc:mysql://${host_address}:${port}/${database_name}?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false

platform: mysql

continue-on-error: false

driver-class-name: com.mysql.cj.jdbc.Driver

注意:${username},${password},${host_address},${port},${database_name}需替换为实际值

4.本地构建alpha-server(和上面步骤一致)

5.启动alpha-server


java -Dspring.profiles.active=mysql -Dloader.path=./plugins

-D"spring.datasource.url=jdbc:mysql://${host_address}:3306/${database_name}?

serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF

-8&useSSL=false " -jar alpha-server-${saga_version}-exec.jar

注意:请在执行命令前将${saga_version}${host_address}更改为实际值

自此,alpha-server端已经配置编译完成

Omega配置

配置完alpha-server之后,就相当于分布式事务的协调器已经配置完成,剩下的就是omega的配置,也就是在实际开发中如何运用servicecomb-pack去处理分布式事务。本次讲解会结合一个实际案例:购物系统中的下单流程和删除产品流程来分别讲解saga模式和tcc模式如何使用的。

环境准备

本次案例:购物系统是采用分布式微服务架构,整体分为三个微服务应用:orderManage订单管理应用、productManage产品管理应用、stockManage库存管理应用

1.添加依赖

分别在三个应用的pom文件中添加Omega所需的依赖:


<dependency>

<groupId>org.apache.servicecomb.pack</groupId>

<artifactId>omega-spring-starter</artifactId>

<version>${servicecomb-pack.version}</version>

</dependency>

<dependency>

<groupId>org.apache.servicecomb.pack</groupId>

<artifactId>omega-transport-resttemplate</artifactId>

<version>${servicecomb-pack.version}</version>

</dependency>

<!--非必需 -->

<dependency>

<groupId>org.apache.servicecomb.pack</groupId>

<artifactId>omega-spring-cloud-consul-starter</artifactId>

<version>${servicecomb-pack.version}</version>

</dependency>

<dependency>

<groupId>org.apache.servicecomb.pack</groupId>

<artifactId>omega-spring-cloud-eureka-starter</artifactId>

<version>${servicecomb-pack.version}</version>

</dependency>

注意:请将${servicecomb-pack.version}更改为实际的版本号(推荐版本为0.4.0

注意:如需做集群,omega-spring-cloud-consul-starteromega-spring-cloud-eureka-starter二选一,视项目的注册中心而定。

2.修改配置文件

分别在三个应用的application.yml配置文件中添加alpha-server配置,具体配置如下:


#配置alpha-server地址

alpha:

cluster:

address: 10.15.15.172:8080

omega:

enabled: true

注意:application.name一定不要过长,因为instanceId的格式是application.name+IP,并且长度为36,否则alpha-server事务持久化会报错

以上两个属性配置为必填,因为alpha-server会依据application.name去查找对应的Omega,其他应用配置自行添加,address可根据alpha-server中的配置实际添加

自此,环境准备已经完毕,下面开始进行应用代码编写

saga模式代码编写

在本次案例中,我们以一个下单流程来讲解saga模式下代码是如何编写的。下单流程包括:点击下单、查询库存、支付、更新库存;订单应用作为起始服务,调用库存应用和产品应用,这两个应用对应的服务作为参与服务(子事务),在订单应用下单,订单应用使用rest template向产品应用发起调用校验产品库存,然后订单应用向库存应用发起支付请求(子事务1),支付成功后订单应用再向库存应用发起请求更新库存(子事务2)。

1.@SagaStart

首先需要在应用代码中描述出saga事务的边界,作为分布式事务的起始点,因此我们需要在订单应用中的createOrder()方法上添加该注解@SagaStart

2.@ Compensable

@Compensable所代表的是本地子事务,因此需要在创建支付和更新库存的方法上添加此注解来标注该逻辑为子事务,并且在CompensablecompensationMethod属性中描述补偿方法。注意补偿方法和本地事务方法的参数必须一致,否则Omega在系统启动进行参数检查的时候报找不到恢复方法的错误:

支付:

支付对应补偿方法:

更新库存:

更新库存补偿方法:

注意:实现的服务和补偿方法必须满足幂等的要求

注意:默认情况下,超时需要显示声明

注意:若全局事务起点与子事务重合,需同时声明@SagaStart和@Compensable注解

注意:补偿方法的入参必须与try方法入参一致,否则启动时会报错(alpha-server找不到补偿方法)

tcc模式代码编写

下面我们会以删除库存流程来讲解tcc模式是如何编写代码的。删除库存流程:由产品应用发起(分布式事务起始),调用库存应用删除对应产品的库存信息(tcc子事务).

本次调用使用的是feign的方式,因此需要在产品应用中的pom文件添加相应的依赖:

1.@TccStart

我们以产品应用中的delete方法作为分布式事务起始点,因此在该方法上添加注解@TccStart:

2.@ Participate

在子事务所处的方法上添加该注解,并通过confirmMethod以及cancelMethod属性定义相关确认以及取消方法名。这里需要注意的是这里提到的confirmcancel方法的参数必须和try方法的相同。

Confirm逻辑:

Cancel逻辑:

注意:confirmcancel方法的入参必须和try方法一致

目前tcc模式还不支持timeout

事件信息获取

默认情况下,8080端口用来处理Omega处发起的grpc请求,用来做事务上下文等操作;而8090端口则用于处理查询alpha处的事件信息。

1saga-事件信息查询api

http://${alpha-server.address:port}/saga/stats:统计所有事件状态

http://${alpha-server.address:port}/saga/recent:统计最近事件状态

http://${alpha-server.address:port}/saga/transactions:根据事件状态查询事件列表

http://${alpha-server.address:port}/saga/findTransactions:根据服务名称查询对应的分布式事件列表

2tcc-事件信息查询api

Tcc目前没有提供正式的查询接口。但是有测试接口,在AlphaTccEventController中,可自行根据测试接口修改源码,重新编译即可

目前alpha-server提供的事件查询api不多,若有其他需求,用户可自行编写接口对数据库进行查询。

以上就是分布式事务实战微课堂的整个内容,本次文章是基于华为servicecomb-pack来总结了一些使用心得和实际项目经验,希望能对正在分布式事务上摸索的同仁们提供一些帮忙。本文章所有观点都出自个人见解,疏漏、错误之处在所难免,欢迎大家指正,希望能够与大家一起交流和进步。

[i] 引用自:http://servicecomb.apache.org/cn/docs/distributed-transaction-of-services-1/

[ii] 引用自:http://servicecomb.apache.org/cn/docs/distributed-transaction-of-services-1/


推荐阅读

分布式及高可用元数据采集原理

一文读懂微服务监控之分布式追踪

分布式架构中数据一致性常见的几个问题


关于作者:花无缺,普元信息Java开发工程师,擅长微服务开发、网关拓展开发;曾参与普元EOS MS 5.0微服务产品开发。爱钻研的"技术控",微服务专家、分布式事务解决方案专家。