2.2 使用非侵入模式接入 DTM
2.2.4 ServiceComb 接入 DTM
需要分别在bankA和bankB数据库中创建dtm_tran_info事务表。
2.2.3.5 定义全局事务发起者
在需要保证事务一致性的方法上使用注解:
@DTMTxBegin(appName = "xx")
其中,appName是全局事务的唯一标识。
说明
appName需要保证全局唯一。
DTM全局事务发起者定义为transfer方法,该方法调用bankA转入服务和bankB转出服 务,同时概率抛出异常。在该方法内一旦发生异常,会导致bankB转出失败,DTM会 帮助bankA回滚转入操作,从而保证数据的一致性。
// com.huawei.bankcenter.controller.BankCenterController.java
@GetMapping(value = "transfer")
@DTMTxBegin(appName = "noninvasive-transfer-SpringCloudHW")
public String transfer(@RequestParam(value = "id") int id, @RequestParam(value = "money") int money,
@RequestParam(value = "errRate") int errRate) {
LOGGER.info("Bank-center start invoke bankA and bankB");
bankOperator.transfer(id, money, errRate);
return "ok";
}// bankOperator有两个实现类,下面以FeignOpImpl的实现类为例 // com.huawei.bankcenter.impl.FeignOpImpl.java
public String transfer(int userId, int money, int errRate) { LOGGER.info("Start transfer---feign");
bankAIntf.transfer(userId, money, errRate);
bankBIntf.transfer(userId, money, errRate);
return "ok";
}
2.2.4 ServiceComb 接入 DTM
本章节讲解ServiceComb框架如何通过非侵入模式接入DTM,使用DTM提供的分布式 事务处理能力,同时结合ServiceComb接入DTM样例指南讲解接入的实现。
2.2.4.1 版本获取及引入依赖
步骤1 DTM使用Maven获取项目版本,根据样例中的settings文件设置Maven远程仓库地址 等配置。
步骤2 同时在项目的“pom.xml”文件中引入依赖,即可引入DTM Client的SDK。
<properties>
<!--以最新版本号为准-->
<dtm.version>3.0.4</dtm.version>
</properties>
<dependency>
<groupId>com.huawei.middleware.dtm</groupId>
<artifactId>dtm-servicecomb-starter</artifactId>
<version>${dtm.version}</version>
</dependency>
----结束
2.2.4.2 ServiceComb handler 链中添加 DTM
修改ServiceComb的handler链配置,在Consumer中增加dtm-consumer,Provider中 增加dtm-provider。
以ServiceComb样例为例,handler链的配置如下所示:
servicecomb:
...
handler:
chain:
Consumer:
default: loadbalance,bizkeeper-consumer,dtm-consumer Provider:
default: dtm-provider
2.2.4.3 数据源配置
在业务数据库上增加数据源DTMDataSource,从而实现DTM对业务数据的保护。
@Bean(name = "dataSource") public DataSource dtmDataSource() { //用DTM数据源来封装业务数据源
return new DTMDataSource(datasource);
}
在bankA服务中增加数据源DTMDataSource如下所示:
// com.huawei.banka.config.DataSourceConfig.java;
@Bean(name = "BankADataSource")
@ConfigurationProperties(prefix = "spring.datasource.banka") public DataSource bankADataSource() {
return new DTMDataSource(datasource);
}
在bankB服务中增加数据源DTMDataSource如下所示:
// com.huawei.bankb.config.DataSourceConfig.java
@Bean(name = "BankBDataSource")
@ConfigurationProperties(prefix = "spring.datasource.bankb") public DataSource bankBDataSource() {
return new DTMDataSource(datasource);
2.2.4.4 添加客户端配置文件
在项目根目录中(jar包同级目录)新建dtm-config文件夹,并在dtm-config文件夹中 添加配置文件dtmClientConfig.properties。配置文件内容如下:
auto-create-table-dtm-tran-info=on dtm-app-name=xxxx
sc-server-address=xxxx rpc-ssl-switch=off
配置项说明如表2-4所示。
表2-4 dtmClientConfig.properties 配置文件参数详解
参数 说明
auto-create-table-dtm-tran-info 是否自动创建DTM事务表dtm_tran_info,用来记录事务信 息。
● on:自动创建事务表,可跳过业务库中创建事务表。
● off:手动创建事务表,可参考业务库中创建事务表方 式二。
dtm-app-name 该配置项可从“应用管理与运维平台”控制台“分布式事 务管理 DTM > 引擎实例”界面中“服务发现与配置”模 块“应用名称”得到。
sc-server-address 该配置项可从“应用管理与运维平台”控制台“分布式事 务管理 DTM > 引擎实例”界面中“服务发现与配置”模 块“服务中心地址”得到。
rpc-ssl-switch 该配置项可从“应用管理与运维平台”控制台“分布式事 务管理 DTM > 引擎实例”界面中“服务发现与配置”模 块“SSL开关”得到。
● on:开启SSL
● off:关闭SSL
2.2.4.5 业务库中创建事务表
在业务库中创建DTM事务表dtm_tran_info,用来记录事务信息。创建有以下两种方 式,推荐通过修改DTM配置信息,自动创建DTM事务表。
● 方式一:自动创建,修改dtm配置文件dtmClientConfig.properties中auto-create-table-dtm-tran-info参数为on,开启自动创建。
auto-create-table-dtm-tran-info=on
● 方式二:手动创建,在原有基础上再创建事务数据库表。
a. 如果数据库使用MySQL或GaussDB(for MySQL),执行下面的SQL:
CREATE TABLE dtm_tran_info ( branch_id bigint(20) NOT NULL, global_id bigint(20) NOT NULL, tran_info longblob NOT NULL, info_status int(11) NOT NULL, info_created datetime(0) NOT NULL,
ext varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (branch_id) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3571 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
b. 如果数据库使用PostgreSQL或GaussDB(openGauss),执行下面的SQL:
CREATE TABLE dtm_tran_info (
branch_id bigint NOT NULL primary key , global_id bigint NOT NULL,
tran_info text NOT NULL, info_status int NOT NULL,
info_created timestamp NOT NULL, ext varchar(100)
)
需要分别在bankA和bankB数据库中创建dtm_tran_info事务表。
2.2.4.6 定义全局事务发起者
在需要保证事务一致性的方法上使用注解:
@DTMTxBegin(appName = "xx")
其中appName是全局事务的唯一标识。
说明
appName需要保证全局唯一。
DTM全局事务发起者定义为transfer方法,该方法调用bankA转入服务和bankB转出服 务,同时概率抛出异常。在该方法内一旦发生异常,会导致bankB转出失败,DTM会 帮助bankA回滚转入操作,从而保证数据的一致性。
com.huawei.bankcenter.controller.BankCenterController
@GetMapping(value = "transfer")
@DTMTxBegin(appName = "noninvasive-transfer-ServiceComb")
public String transfer(@RequestParam(value = "id") int id, @RequestParam(value = "money") int money, @RequestParam(value = "errRate") int errRate) {
LOGGER.info("Bank-center start invoke bankA and bankB");
restInvoker.getForObject(
String.format(BANKA_TRANSFER, id, money, errRate), String.class);
restInvoker.getForObject(
String.format(BANKB_TRANSFER, id, money, errRate), String.class);
return "ok";
}