From 34f7de1c84f9a04d540bae3171fa6b4c3e02f264 Mon Sep 17 00:00:00 2001 From: zhangqian Date: Tue, 21 Jun 2022 14:31:00 +0800 Subject: [PATCH] Upgrade to Seata 1.5.1. --- spring-cloud-alibaba-examples/pom.xml | 1 + .../seata-example/account-service/pom.xml | 3 +- .../src/main/resources/application.properties | 30 --- .../src/main/resources/application.yml | 53 +++++ .../seata-example/business-service/pom.xml | 7 +- .../src/main/resources/application.properties | 29 --- .../src/main/resources/application.yml | 45 ++++ .../seata-example/order-service/pom.xml | 3 +- .../src/main/resources/application.properties | 29 --- .../src/main/resources/application.yml | 50 +++++ .../seata-example/readme-zh.md | 129 ++++++++++-- .../seata-example/readme.md | 195 +++++++++++++----- .../seata-example/storage-service/pom.xml | 3 +- .../cloud/examples/StorageApplication.java | 1 + .../{ => config}/DatabaseConfiguration.java | 2 +- .../{ => controller}/StorageController.java | 2 +- .../src/main/resources/application.properties | 30 --- .../src/main/resources/application.yml | 52 +++++ 18 files changed, 462 insertions(+), 202 deletions(-) delete mode 100644 spring-cloud-alibaba-examples/seata-example/account-service/src/main/resources/application.properties create mode 100644 spring-cloud-alibaba-examples/seata-example/account-service/src/main/resources/application.yml delete mode 100644 spring-cloud-alibaba-examples/seata-example/business-service/src/main/resources/application.properties create mode 100644 spring-cloud-alibaba-examples/seata-example/business-service/src/main/resources/application.yml delete mode 100644 spring-cloud-alibaba-examples/seata-example/order-service/src/main/resources/application.properties create mode 100644 spring-cloud-alibaba-examples/seata-example/order-service/src/main/resources/application.yml rename spring-cloud-alibaba-examples/seata-example/storage-service/src/main/java/com/alibaba/cloud/examples/{ => config}/DatabaseConfiguration.java (97%) rename spring-cloud-alibaba-examples/seata-example/storage-service/src/main/java/com/alibaba/cloud/examples/{ => controller}/StorageController.java (97%) delete mode 100644 spring-cloud-alibaba-examples/seata-example/storage-service/src/main/resources/application.properties create mode 100644 spring-cloud-alibaba-examples/seata-example/storage-service/src/main/resources/application.yml diff --git a/spring-cloud-alibaba-examples/pom.xml b/spring-cloud-alibaba-examples/pom.xml index 35df4923d..d0b90f521 100644 --- a/spring-cloud-alibaba-examples/pom.xml +++ b/spring-cloud-alibaba-examples/pom.xml @@ -31,6 +31,7 @@ seata-example/order-service seata-example/storage-service seata-example/account-service + seata-example/seata-server rocketmq-example/rocketmq-comprehensive-example rocketmq-example/rocketmq-orderly-consume-example rocketmq-example/rocketmq-broadcast-example/rocketmq-broadcast-producer-example diff --git a/spring-cloud-alibaba-examples/seata-example/account-service/pom.xml b/spring-cloud-alibaba-examples/seata-example/account-service/pom.xml index 3f54a457f..bfdb2fb9f 100644 --- a/spring-cloud-alibaba-examples/seata-example/account-service/pom.xml +++ b/spring-cloud-alibaba-examples/seata-example/account-service/pom.xml @@ -44,7 +44,6 @@ mysql mysql-connector-java - 8.0.16 log4j @@ -52,4 +51,4 @@ 1.2.17 - \ No newline at end of file + diff --git a/spring-cloud-alibaba-examples/seata-example/account-service/src/main/resources/application.properties b/spring-cloud-alibaba-examples/seata-example/account-service/src/main/resources/application.properties deleted file mode 100644 index d67018432..000000000 --- a/spring-cloud-alibaba-examples/seata-example/account-service/src/main/resources/application.properties +++ /dev/null @@ -1,30 +0,0 @@ -spring.application.name=account-service -server.port=18084 -spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 - -spring.datasource.name="accountDataSource" -spring.datasource.type=com.alibaba.druid.pool.DruidDataSource -spring.datasource.driver-class-name=com.mysql.jdbc.Driver -spring.datasource.url=jdbc:mysql://xxx:3306/seata?useSSL=false&serverTimezone=UTC -spring.datasource.username=xxx -spring.datasource.password=xxx -spring.datasource.druid.max-active=20 -spring.datasource.druid.min-idle=2 -spring.datasource.druid.initial-size=2 - -seata.enabled=true -spring.cloud.alibaba.seata.tx-service-group=account-service -seata.service.vgroup-mapping.account-service=default -seata.service.grouplist.default=127.0.0.1:8091 -seata.service.disable-global-transaction=false - -## if use registry center -#seata.registry.type=nacos -#seata.registry.nacos.cluster=default -#seata.registry.nacos.server-addr=localhost -# -## if use config center -#seata.config.type=apollo -#seata.config.apollo.apollo-meta=http://192.168.1.204:8801 -#seata.config.apollo.app-id=seata-server - diff --git a/spring-cloud-alibaba-examples/seata-example/account-service/src/main/resources/application.yml b/spring-cloud-alibaba-examples/seata-example/account-service/src/main/resources/application.yml new file mode 100644 index 000000000..086b2de51 --- /dev/null +++ b/spring-cloud-alibaba-examples/seata-example/account-service/src/main/resources/application.yml @@ -0,0 +1,53 @@ +base: + config: + mdb: + hostname: #your mysql server ip address + dbname: #your database name for test + port: #your mysql server listening port + username: #your mysql server username + password: #your mysql server password + +server: + port: 18084 + +spring: + cloud: + nacos: + discovery: + server-addr: 127.0.0.1:8848 + application: + name: account-service + main: + allow-bean-definition-overriding: true + datasource: + name: storageDataSource + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://${base.config.mdb.hostname}:${base.config.mdb.port}/${base.config.mdb.dbname}?useSSL=false&serverTimezone=UTC + username: ${base.config.mdb.username} + password: ${base.config.mdb.password} + druid: + max-active: 20 + min-idle: 2 + initial-size: 2 + +seata: + enabled: true + application-id: ${spring.application.name} + + tx-service-group: ${spring.application.name}-tx-group + config: + type: nacos + + nacos: + serverAddr: 127.0.0.1:8848 + dataId: "seata.properties" + username: "nacos" + password: "nacos" + registry: + type: nacos + nacos: + application: seata-server + server-addr: 127.0.0.1:8848 + username: "nacos" + password: "nacos" diff --git a/spring-cloud-alibaba-examples/seata-example/business-service/pom.xml b/spring-cloud-alibaba-examples/seata-example/business-service/pom.xml index 350f6c495..c34d4d376 100644 --- a/spring-cloud-alibaba-examples/seata-example/business-service/pom.xml +++ b/spring-cloud-alibaba-examples/seata-example/business-service/pom.xml @@ -42,6 +42,9 @@ com.alibaba.cloud spring-cloud-starter-alibaba-sentinel - + + org.springframework + spring-tx + - \ No newline at end of file + diff --git a/spring-cloud-alibaba-examples/seata-example/business-service/src/main/resources/application.properties b/spring-cloud-alibaba-examples/seata-example/business-service/src/main/resources/application.properties deleted file mode 100644 index a0f6550ab..000000000 --- a/spring-cloud-alibaba-examples/seata-example/business-service/src/main/resources/application.properties +++ /dev/null @@ -1,29 +0,0 @@ -server.port=18081 -spring.application.name=business-service -spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 -# The following configuration can be omitted. - -#feign.hystrix.enabled=true -#feign.sentinel.enabled=true -feign.client.config.default.connectTimeout=10000 -feign.client.config.default.readTimeout=10000 - -logging.level.io.seata=debug - -seata.enabled=true -spring.cloud.alibaba.seata.tx-service-group=business-service -seata.service.vgroup-mapping.business-service=default -seata.service.grouplist.default=127.0.0.1:8091 -seata.service.disable-global-transaction=false - -spring.cloud.loadbalancer.ribbon.enabled=true - -## if use registry center -#seata.registry.type=nacos -#seata.registry.nacos.cluster=default -#seata.registry.nacos.server-addr=localhost -# -## if use config center -#seata.config.type=apollo -#seata.config.apollo.apollo-meta=http://192.168.1.204:8801 -#seata.config.apollo.app-id=seata-server diff --git a/spring-cloud-alibaba-examples/seata-example/business-service/src/main/resources/application.yml b/spring-cloud-alibaba-examples/seata-example/business-service/src/main/resources/application.yml new file mode 100644 index 000000000..78d363f08 --- /dev/null +++ b/spring-cloud-alibaba-examples/seata-example/business-service/src/main/resources/application.yml @@ -0,0 +1,45 @@ +server: + port: 18081 + +spring: + cloud: + nacos: + discovery: + server-addr: 127.0.0.1:8848 + loadbalancer: + ribbon: + enabled:true + application: + name: business-service + +seata: + enabled: true + application-id: ${spring.application.name} + + tx-service-group: ${spring.application.name}-tx-group + config: + type: nacos + nacos: + serverAddr: 127.0.0.1:8848 + dataId: "seata.properties" + username: "nacos" + password: "nacos" + registry: + type: nacos + nacos: + application: seata-server + server-addr: 127.0.0.1:8848 + username: "nacos" + password: "nacos" + +feign: + client: + config: + default: + connectTimeout: 10000 + readTimeout: 10000 +logging: + level: + io: + seata: debug + diff --git a/spring-cloud-alibaba-examples/seata-example/order-service/pom.xml b/spring-cloud-alibaba-examples/seata-example/order-service/pom.xml index 7fbd38baa..f52eff4ef 100644 --- a/spring-cloud-alibaba-examples/seata-example/order-service/pom.xml +++ b/spring-cloud-alibaba-examples/seata-example/order-service/pom.xml @@ -43,7 +43,6 @@ mysql mysql-connector-java - 8.0.16 log4j @@ -52,5 +51,5 @@ - + diff --git a/spring-cloud-alibaba-examples/seata-example/order-service/src/main/resources/application.properties b/spring-cloud-alibaba-examples/seata-example/order-service/src/main/resources/application.properties deleted file mode 100644 index 4fef9e1b4..000000000 --- a/spring-cloud-alibaba-examples/seata-example/order-service/src/main/resources/application.properties +++ /dev/null @@ -1,29 +0,0 @@ -spring.application.name=order-service -server.port=18083 -spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 - -spring.datasource.name="orderDataSource" -spring.datasource.type=com.alibaba.druid.pool.DruidDataSource -spring.datasource.driver-class-name=com.mysql.jdbc.Driver -spring.datasource.url=jdbc:mysql://xxx:3306/seata?useSSL=false&serverTimezone=UTC -spring.datasource.username=xxx -spring.datasource.password=xxx -spring.datasource.druid.max-active=20 -spring.datasource.druid.min-idle=2 -spring.datasource.druid.initial-size=2 - -seata.enabled=true -spring.cloud.alibaba.seata.tx-service-group=business-service -seata.service.vgroup-mapping.business-service=default -seata.service.grouplist.default=127.0.0.1:8091 -seata.service.disable-global-transaction=false - -## if use registry center -#seata.registry.type=nacos -#seata.registry.nacos.cluster=default -#seata.registry.nacos.server-addr=localhost -# -## if use config center -#seata.config.type=apollo -#seata.config.apollo.apollo-meta=http://192.168.1.204:8801 -#seata.config.apollo.app-id=seata-server diff --git a/spring-cloud-alibaba-examples/seata-example/order-service/src/main/resources/application.yml b/spring-cloud-alibaba-examples/seata-example/order-service/src/main/resources/application.yml new file mode 100644 index 000000000..07b533745 --- /dev/null +++ b/spring-cloud-alibaba-examples/seata-example/order-service/src/main/resources/application.yml @@ -0,0 +1,50 @@ +base: + config: + mdb: + hostname: #your mysql server ip address + dbname: #your database name for test + port: #your mysql server listening port + username: #your mysql server username + password: #your mysql server password +server: + port: 18083 + +spring: + cloud: + nacos: + discovery: + server-addr: 127.0.0.1:8848 + application: + name: order-service + main: + allow-bean-definition-overriding: true + datasource: + name: storageDataSource + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://${base.config.mdb.hostname}:${base.config.mdb.port}/${base.config.mdb.dbname}?useSSL=false&serverTimezone=UTC + username: ${base.config.mdb.username} + password: ${base.config.mdb.password} + druid: + max-active: 20 + min-idle: 2 + initial-size: 2 + +seata: + enabled: true + application-id: ${spring.application.name} + tx-service-group: ${spring.application.name}-tx-group + config: + type: nacos + nacos: + serverAddr: 127.0.0.1:8848 + dataId: "seata.properties" + username: "nacos" + password: "nacos" + registry: + type: nacos + nacos: + application: seata-server + server-addr: 127.0.0.1:8848 + username: "nacos" + password: "nacos" diff --git a/spring-cloud-alibaba-examples/seata-example/readme-zh.md b/spring-cloud-alibaba-examples/seata-example/readme-zh.md index 2723de586..e1a290f8b 100644 --- a/spring-cloud-alibaba-examples/seata-example/readme-zh.md +++ b/spring-cloud-alibaba-examples/seata-example/readme-zh.md @@ -15,34 +15,43 @@ 1. 配置数据库 -1. 创建 UNDO_LOG 表 - -1. 创建 示例中 业务所需要的数据库表 - -1. 启动 Seata Server +2. 创建 UNDO_LOG 表 +3. 创建 示例中 业务所需要的数据库表 +4. 创建示例中Nacos data-id: `seata.properties` , Group: `SEATA_GROUP`(seata 1.5.1 默认分组) ,导入 [Nacos 配置](https://github.com/seata/seata/blob/1.5.0/script/config-center/config.txt) + 在seata.properties中增加示例中需要的如下[事务群组配置](https://seata.io/zh-cn/docs/user/configurations.html) +``` + service.vgroupMapping.order-service-tx-group=default + service.vgroupMapping.account-service-tx-group=default + service.vgroupMapping.business-service-tx-group=default + service.vgroupMapping.storage-service-tx-group=default +``` +5. 启动 Seata Server + Seata 1.5.1 支持seata控制台 本地访问控制台地址:http://127.0.0.1:7091 + 通过seata控制台可以观察正在执行的事务信息和全局锁信息,事务执行结束即删除相关信息。 ### 配置数据库 首先,你需要有一个支持 InnoDB 引擎的 MySQL 数据库。 **注意**: 实际上,Seata 支持不同的应用使用完全不相干的数据库,但是这里为了简单地演示一个原理,所以我们选择了只使用一个数据库。 -将 `account-server`、`order-service`、`storage-service` 这三个应用中的 resources 目录下的 `application.properties` 文件中的如下配置修改成你运行环境中的实际配置。 +将 `account-server`、`order-service`、`storage-service` 这三个应用中的 resources 目录下的 `application.yml` 文件中的如下配置修改成你运行环境中的实际配置。 ``` -mysql.server.ip=your mysql server ip address -mysql.server.port=your mysql server listening port -mysql.db.name=your database name for test - -mysql.user.name=your mysql server username -mysql.user.password=your mysql server password - +base: + config: + mdb: + hostname: your mysql server ip address + dbname: your database name for test + port: your mysql server listening port + username: your mysql server username + password: your mysql server password ``` ### 创建 undo_log 表 -[Seata AT 模式]() 需要使用到 undo_log 表。 +Seata AT 模式 需要使用到 undo_log 表。 ``` $sql -- 注意此处0.3.0+ 增加唯一索引 ux_undo_log @@ -60,7 +69,83 @@ CREATE TABLE `undo_log` ( UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; ``` - +### 导入 seata-server db模式所需要的数据库表 +在数据库中初始化[global_table、branch_table、lock_table、distributed_lock](https://github.com/seata/seata/blob/1.5.0/script/server/db/mysql.sql) +```$sql +-- -------------------------------- The script used when storeMode is 'db' -------------------------------- +-- the table to store GlobalSession data +CREATE TABLE IF NOT EXISTS `global_table` +( + `xid` VARCHAR(128) NOT NULL, + `transaction_id` BIGINT, + `status` TINYINT NOT NULL, + `application_id` VARCHAR(32), + `transaction_service_group` VARCHAR(32), + `transaction_name` VARCHAR(128), + `timeout` INT, + `begin_time` BIGINT, + `application_data` VARCHAR(2000), + `gmt_create` DATETIME, + `gmt_modified` DATETIME, + PRIMARY KEY (`xid`), + KEY `idx_status_gmt_modified` (`status` , `gmt_modified`), + KEY `idx_transaction_id` (`transaction_id`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4; + +-- the table to store BranchSession data +CREATE TABLE IF NOT EXISTS `branch_table` +( + `branch_id` BIGINT NOT NULL, + `xid` VARCHAR(128) NOT NULL, + `transaction_id` BIGINT, + `resource_group_id` VARCHAR(32), + `resource_id` VARCHAR(256), + `branch_type` VARCHAR(8), + `status` TINYINT, + `client_id` VARCHAR(64), + `application_data` VARCHAR(2000), + `gmt_create` DATETIME(6), + `gmt_modified` DATETIME(6), + PRIMARY KEY (`branch_id`), + KEY `idx_xid` (`xid`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4; + +-- the table to store lock data +CREATE TABLE IF NOT EXISTS `lock_table` +( + `row_key` VARCHAR(128) NOT NULL, + `xid` VARCHAR(128), + `transaction_id` BIGINT, + `branch_id` BIGINT NOT NULL, + `resource_id` VARCHAR(256), + `table_name` VARCHAR(32), + `pk` VARCHAR(36), + `status` TINYINT NOT NULL DEFAULT '0' COMMENT '0:locked ,1:rollbacking', + `gmt_create` DATETIME, + `gmt_modified` DATETIME, + PRIMARY KEY (`row_key`), + KEY `idx_status` (`status`), + KEY `idx_branch_id` (`branch_id`), + KEY `idx_xid_and_branch_id` (`xid` , `branch_id`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4; + +CREATE TABLE IF NOT EXISTS `distributed_lock` +( + `lock_key` CHAR(20) NOT NULL, + `lock_value` VARCHAR(20) NOT NULL, + `expire` BIGINT, + primary key (`lock_key`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4; + +INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('AsyncCommitting', ' ', 0); +INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryCommitting', ' ', 0); +INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryRollbacking', ' ', 0); +INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('TxTimeoutCheck', ' ', 0); +``` ### 创建 示例中 业务所需要的数据库表 ```$sql @@ -94,11 +179,12 @@ CREATE TABLE `account_tbl` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ``` -### 启动 Seata Server - -点击这个页面 [https://github.com/seata/seata/releases](https://github.com/seata/seata/releases),下载最新版本的 Seata Server 端. +### 启动 Seata Server 这里介绍SpringBoot 和下载server两种方式 +1.运行 seata-server 启动Seata server +示例中采用nacos 作为配置,注册中心 存储模式为:db 采用mysql +2.或点击这个页面 [Seata 官网Github](https://github.com/seata/seata/releases),下载最新版本的 Seata Server 端. 进入解压之后的 bin 目录,执行如下命令来启动, 所有启动参数为可选项。 ```$shell @@ -106,10 +192,10 @@ sh seata-server.sh -p $LISTEN_PORT -m $MODE(file or db) -h $HOST -e $ENV ``` -p seata-server 监听服务端口号 -m 存储模式,可选值:file、db。file 用于单点模式,db用于ha模式,当使用db存储模式,需要修改配置中store配置节点的数据库配置,同时在数据库中初始化[global_table、branch_table和 -lock_table](https://github.com/seata/seata/blob/develop/server/src/main/resources/db_store.sql) +lock_table](https://github.com/seata/seata/blob/1.5.0/script/server/db/mysql.sql) -h 用于解决seata-server和业务侧跨网络问题,其配置的host值直接显示到注册中心的服务可用地址host,当跨网络时这里需要配置为公网IP或NATIP,若都在同一局域网则无需配置 -e 用于解决多环境配置中心隔离问题 -在这个示例中,采用如下命令来启动 Seata Server +采用如下命令来启动 Seata Server ```$shell sh seata-server.sh -p 8091 -m file @@ -122,12 +208,13 @@ sh seata-server.sh -p 8091 -m file 分别运行 `account-server`、`order-service`、`storage-service` 和 `business-service` 这三个应用的 Main 函数,启动示例。 -启动示例后,通过 HTTP 的 GET 方法访问如下两个 URL,可以分别验证在 `business-service` 中 通过 RestTemplate 和 FeignClient 调用其他服务的场景。 +启动示例后,通过 HTTP 的 GET 方法访问如下 URL,可以分别验证在 `business-service` 中 通过 RestTemplate 和 FeignClient 调用其他服务的场景。 ```$xslt http://127.0.0.1:18081/seata/feign http://127.0.0.1:18081/seata/rest + ``` ## 如何验证分布式事务成功? diff --git a/spring-cloud-alibaba-examples/seata-example/readme.md b/spring-cloud-alibaba-examples/seata-example/readme.md index 915131489..d572b74a7 100644 --- a/spring-cloud-alibaba-examples/seata-example/readme.md +++ b/spring-cloud-alibaba-examples/seata-example/readme.md @@ -3,49 +3,60 @@ ## Project Instruction -This project demonstrates how to use Seata Starter to complete distributed transaction access for Spring Cloud applications. +This project demonstrates how to use Seata starter to complete the distributed transaction access of spring cloud applications. -[Seata](https://github.com/seata/seata) is Alibaba's open source distributed transaction middleware that solves distributed transaction problems in microservice scenarios in an efficient and 0-intrusive way. +[Seata](https://github.com/seata/seata) It is Alibaba open source distributed transaction middleware, which solves the distributed transaction problem in the microservice scenario in an efficient and non-invasive way. -## Preparation +## Preparations -Before running this example, you need to complete the following preparation steps. +Before running this example, you need to complete the following steps: 1. Configure the database -2. Create the `UNDO_LOG` table +2. Create UNDO_ LOG table -3. Create the database tables required by the business in the example - -4. Start Seata Server +3. Create the database tables needed by the business in the example +4. Create the Nacos configuration in the example, data id: `seata.properties` , Group: `SEATA_ Group` (Seata 1.5.1 default group) configuration import [nacos configuration](https://github.com/seata/seata/blob/1.5.0/script/config-center/config.txt) + At seata Add the following [transaction group configuration](https://seata.io/zh-cn/docs/user/configurations.html) required in the example to properties +``` + service.vgroupMapping.order-service-tx-group=default + service.vgroupMapping.account-service-tx-group=default + service.vgroupMapping.business-service-tx-group=default + service.vgroupMapping.storage-service-tx-group=default +``` +5. Start Seata Server + Seata 1.5.1 supports Seata console local access console address: http://127.0.0.1:7091 + Through the Seata console, you can observe the executing transaction information and global lock information, and delete the relevant information when the transaction is completed. -### Configure the database +### Configuration database -First, you need to have a MySQL database that supports the `InnoDB` engine. +First, you need a MySQL database that supports the InnoDB engine. -**Note**: Seata actually supports different applications using completely unrelated databases, but here we have chosen to use only one database in order to simply demonstrate a principle. +**NOTE**: In fact, Seata supports different applications that use totally unrelated databases, but here we chose to use only one database for a simple demonstration of one principle. -Change the following configuration in the `application.properties` file in the `resources` directory of the `account-server`, `order-service`, and `storage-service` applications to the actual configuration in your runtime environment. +Will application in the resources directory of the `account-server`, `order-service`, `storage-service` three applications. The following configuration in the yml file is modified to the actual configuration in your running environment. ``` -mysql.server.ip=your mysql server ip address -mysql.server.port=your mysql server listening port -mysql.db.name=your database name for test - -mysql.user.name=your mysql server username -mysql.user.password=your mysql server password +base: + config: + mdb: + hostname: your mysql server ip address + dbname: your database name for test + port: your mysql server listening port + username: your mysql server username + password: your mysql server password ``` -### Create `undo_log` table +### Create undo_ Log table -The [Seata AT schema]() needs to use the undo_log table. +Seata AT Mode Need to use undo_ Log table. ``` $sql --- Note that here 0.3.0+ adds unique index `ux_undo_log` +-- Notice here that 0.3.0+ increases the unique index ux_ Undo_ Log CREATE TABLE `undo_log` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `branch_id` bigint(20) NOT NULL, @@ -60,8 +71,84 @@ CREATE TABLE `undo_log` ( UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; ``` - -### Create the database tables required by the business in the example +### Database tables needed to import seata-server DB schema +Initialize in database [global_table、branch_table、lock_table、distributed_lock](https://github.com/seata/seata/blob/1.5.0/script/server/db/mysql.sql) +```$sql +-- -------------------------------- The script used when storeMode is 'db' -------------------------------- +-- the table to store GlobalSession data +CREATE TABLE IF NOT EXISTS `global_table` +( + `xid` VARCHAR(128) NOT NULL, + `transaction_id` BIGINT, + `status` TINYINT NOT NULL, + `application_id` VARCHAR(32), + `transaction_service_group` VARCHAR(32), + `transaction_name` VARCHAR(128), + `timeout` INT, + `begin_time` BIGINT, + `application_data` VARCHAR(2000), + `gmt_create` DATETIME, + `gmt_modified` DATETIME, + PRIMARY KEY (`xid`), + KEY `idx_status_gmt_modified` (`status` , `gmt_modified`), + KEY `idx_transaction_id` (`transaction_id`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4; + +-- the table to store BranchSession data +CREATE TABLE IF NOT EXISTS `branch_table` +( + `branch_id` BIGINT NOT NULL, + `xid` VARCHAR(128) NOT NULL, + `transaction_id` BIGINT, + `resource_group_id` VARCHAR(32), + `resource_id` VARCHAR(256), + `branch_type` VARCHAR(8), + `status` TINYINT, + `client_id` VARCHAR(64), + `application_data` VARCHAR(2000), + `gmt_create` DATETIME(6), + `gmt_modified` DATETIME(6), + PRIMARY KEY (`branch_id`), + KEY `idx_xid` (`xid`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4; + +-- the table to store lock data +CREATE TABLE IF NOT EXISTS `lock_table` +( + `row_key` VARCHAR(128) NOT NULL, + `xid` VARCHAR(128), + `transaction_id` BIGINT, + `branch_id` BIGINT NOT NULL, + `resource_id` VARCHAR(256), + `table_name` VARCHAR(32), + `pk` VARCHAR(36), + `status` TINYINT NOT NULL DEFAULT '0' COMMENT '0:locked ,1:rollbacking', + `gmt_create` DATETIME, + `gmt_modified` DATETIME, + PRIMARY KEY (`row_key`), + KEY `idx_status` (`status`), + KEY `idx_branch_id` (`branch_id`), + KEY `idx_xid_and_branch_id` (`xid` , `branch_id`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4; + +CREATE TABLE IF NOT EXISTS `distributed_lock` +( + `lock_key` CHAR(20) NOT NULL, + `lock_value` VARCHAR(20) NOT NULL, + `expire` BIGINT, + primary key (`lock_key`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4; + +INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('AsyncCommitting', ' ', 0); +INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryCommitting', ' ', 0); +INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryRollbacking', ' ', 0); +INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('TxTimeoutCheck', ' ', 0); +``` +### Create the database tables needed by the business in the example ```$sql DROP TABLE IF EXISTS `storage_tbl`; @@ -94,67 +181,69 @@ CREATE TABLE `account_tbl` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ``` -### Start Seata Server +### Start Seata Server This describes SpringBoot and download server in two ways -Click on this page [https://github.com/seata/seata/releases](https://github.com/seata/seata/releases) to download the latest version of Seata Server. +1.Run seata-server to start Seata server +The example uses Nacos as the configuration and the registry storage mode is: DB uses MySQL - -Go to the bin directory after unpacking and execute the following command to start it, all startup parameters are optional. +2. Or click on this page GitHub, the official website of [Seata](https://github.com/seata/seata/releases ), download the latest version of Sata Server. +Enter the bin directory after unzipping and execute the following command to start with all the startup parameters optional. ```$shell sh seata-server.sh -p $LISTEN_PORT -m $MODE(file or db) -h $HOST -e $ENV ``` -`-p` seata-server listen to the service port number -`-m` storage mode, optional values: file, db. file is used for single point mode, db is used for ha mode, when using db storage mode, you need to modify the database configuration of the store configuration node in the configuration, and also initialize [global_table, branch_table and -lock_table](https://github.com/seata/seata/blob/develop/server/src/main/resources/db_store.sql) -`-h` is used to solve the `seata-server` and business side of the cross-network problem, its configuration of the host value directly to the service available in the registration center host, when the cross-network here need to be configured as a public IP or NATIP, if all in the same LAN is not required to configure -`-e` is used to solve the multi-environment configuration center isolation problem - -In this example, the following command is used to start Seata Server +-p seata-server listening service port number +-m storage mode, optional values: file, db. File is for single-point mode and DB is for HA mode. When using DB storage mode, you need to modify the database configuration of the store configuration node in the configuration and initialize [global_table, branch_table, and +Lock_ Table](https://github.com/seata/seata/blob/1.5.0/script/server/db/mysql.sql ) +-h is used to solve seata-server and business side cross-network problems. The configured host value is displayed directly to the registry service available address host, which needs to be configured as public network IP or NATIP when cross-network. If both are in the same local area network, no configuration is required +-e for multi-environment configuration center isolation +Start Seata Server with the following command ```$shell sh seata-server.sh -p 8091 -m file ``` -**Note** If you have modified the endpoint and the registry uses the default file type, remember to change the value of grouplist in the `file.conf` file in each example project (the registry.type or config.type in registry.conf will be read when it is file). If the type is not file, the data will be read directly from the registration configuration center of the corresponding metadata of the configuration type), it is recommended to use nacos as the configuration registration center. - +**Note** If you modified the endpoint and the registry uses the default file type, remember the file you need in each of the sample projects. In the conf`file, modify the value of grouplist (when registry.type or config.type in registry.conf is file, the file name in the internal file node is read; if type is not file, the data is read directly from the registry configuration center for the corresponding metadata of the configuration type), Nacos is recommended as the configuration registry. -## Run example +## Run Example -Run the Main function of `account-server`, `order-service`, `storage-service` and `business-service` respectively to start the example. +Run the Main functions of the three applications `account-server`, `order-service`, `storage-service` and `business-service`, respectively, to start the example. -After starting the example, access the following two URLs via the `GET` method of HTTP to verify the scenario of calling other services in `business-service` via RestTemplate and FeignClient, respectively. +After launching the example, the following URLs are accessed through the GET method of HTTP to validate scenarios where other services are invoked through RestTemplate and FeignClient in `business-service` respectively. ```$xslt http://127.0.0.1:18081/seata/feign http://127.0.0.1:18081/seata/rest + ``` -## How to verify the success of a distributed transaction? +## How do I verify the success of a distributed transaction? + +### Whether Xid information was successfully transmitted -### Check if the Xid information was passed successfully +In the Controller of the three services `account-server`, `order-service` and `storage-service`, the first logic executed is to output the Xid information in the RootContext. If you see that the correct Xid information is output, it changes every time and the Xid of all services in the same call is consistent. This indicates that the transfer and restore of Seata's Xid are normal. +### Consistency of data in database -In the Controller of `account-server`, `order-service` and `storage-service` services, the first logic executed is to output the Xid information in the RootContext, and if we see that the correct Xid information is output, i.e., it changes every time and the Xid of all services in the same. If you see that the correct Xid information is output, i.e., it changes every time and the Xid of all services in the same call is the same. If you see that the Xid information in the RootContext is correct, i.e., it changes every time, and the Xid of all the services in the same call is the same, then the Xid of Seata is passed and restored properly. +In this example, we simulate a scenario where a user purchases goods, StorageService is responsible for deducting the inventory quantity, OrderService is responsible for saving the order, and AccountService is responsible for deducting the user account balance. -### Check if the data in the database is consistent +To demonstrate the sample, we used Random in OrderService and AcountService. NextBoolean () randomly throws exceptions, simulating a scenario in which exceptions occur randomly when a service is invoked. -In this example, we simulate a scenario where a user purchases goods, the StorageService is responsible for deducting the inventory quantity, the OrderService is responsible for saving the order, and the AccountService is responsible for deducting the user's account balance. +If the distributed transaction is valid, then the following equation should be true -To demonstrate the sample, we use Random.nextBoolean() in OrderService and AccountService to throw a random exception, simulating a random exception occurring during a service call. -If the distributed transaction is in effect, then the following equation should hold +- User Original Amount (1000) = User Existing Amount + Goods Unit Price (2) * Order Quantity * Goods Quantity per Order (2) -- `Original amount of the user (1000)` = `existing amount of the user` + `unit price of the goods (2)` * `number of orders` * `number of goods per order (2)` +- Initial Quantity of Goods (100) = Existing Quantity of Goods + Order Quantity * Quantity of Goods per Order (2) -- `Initial quantity of goods (100)` = `existing quantity of goods` + `number of orders` * `number of goods per order (2)` +## Support points for Spring Cloud -## Compatible with the Spring Cloud ecosystem +- Service providers that provide services through Spring MVC can automatically restore the Seata context when they receive HTTP requests with Seata information in the header. -- Service providers that provide services through `Spring MVC` can automatically restore `Seata` context when they receive an HTTP request with `Seata` information in the header. +- Support for automatic delivery of Seata context when service callers invoke through RestTemplate. -- Support for service callers to automatically pass `Seata` contexts when called via RestTemplate. +- Supports automatic delivery of the Seata context when a service caller invokes through a FeignClient. -- Supports automatic passing of `Seata` context when called by a service caller via FeignClient. +- Supports scenarios where both SeataClient and Hystrix are used. -- Supports scenarios where `SeataClient` and `Sentinel` are used together. +- Supports scenarios used by both SeataClient and entinel. diff --git a/spring-cloud-alibaba-examples/seata-example/storage-service/pom.xml b/spring-cloud-alibaba-examples/seata-example/storage-service/pom.xml index 2f98ad9aa..f7c5ca141 100644 --- a/spring-cloud-alibaba-examples/seata-example/storage-service/pom.xml +++ b/spring-cloud-alibaba-examples/seata-example/storage-service/pom.xml @@ -42,7 +42,6 @@ mysql mysql-connector-java - 8.0.16 log4j @@ -50,4 +49,4 @@ 1.2.17 - \ No newline at end of file + diff --git a/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/java/com/alibaba/cloud/examples/StorageApplication.java b/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/java/com/alibaba/cloud/examples/StorageApplication.java index 91e6c46cd..8f15a499a 100644 --- a/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/java/com/alibaba/cloud/examples/StorageApplication.java +++ b/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/java/com/alibaba/cloud/examples/StorageApplication.java @@ -26,6 +26,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; public class StorageApplication { public static void main(String[] args) { + SpringApplication.run(StorageApplication.class, args); } diff --git a/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/java/com/alibaba/cloud/examples/DatabaseConfiguration.java b/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/java/com/alibaba/cloud/examples/config/DatabaseConfiguration.java similarity index 97% rename from spring-cloud-alibaba-examples/seata-example/storage-service/src/main/java/com/alibaba/cloud/examples/DatabaseConfiguration.java rename to spring-cloud-alibaba-examples/seata-example/storage-service/src/main/java/com/alibaba/cloud/examples/config/DatabaseConfiguration.java index b358cdc1d..2ba77c4f4 100644 --- a/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/java/com/alibaba/cloud/examples/DatabaseConfiguration.java +++ b/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/java/com/alibaba/cloud/examples/config/DatabaseConfiguration.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.alibaba.cloud.examples; +package com.alibaba.cloud.examples.config; import javax.sql.DataSource; diff --git a/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/java/com/alibaba/cloud/examples/StorageController.java b/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/java/com/alibaba/cloud/examples/controller/StorageController.java similarity index 97% rename from spring-cloud-alibaba-examples/seata-example/storage-service/src/main/java/com/alibaba/cloud/examples/StorageController.java rename to spring-cloud-alibaba-examples/seata-example/storage-service/src/main/java/com/alibaba/cloud/examples/controller/StorageController.java index 31bf0607b..6e37d5ca0 100644 --- a/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/java/com/alibaba/cloud/examples/StorageController.java +++ b/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/java/com/alibaba/cloud/examples/controller/StorageController.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.alibaba.cloud.examples; +package com.alibaba.cloud.examples.controller; import io.seata.core.context.RootContext; import org.slf4j.Logger; diff --git a/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/resources/application.properties b/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/resources/application.properties deleted file mode 100644 index c9671852f..000000000 --- a/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/resources/application.properties +++ /dev/null @@ -1,30 +0,0 @@ -spring.application.name=storage-service -server.port=18082 -spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 - -spring.datasource.name="storageDataSource" -spring.datasource.type=com.alibaba.druid.pool.DruidDataSource -spring.datasource.driver-class-name=com.mysql.jdbc.Driver -spring.datasource.url=jdbc:mysql://xxx:3306/seata?useSSL=false&serverTimezone=UTC -spring.datasource.username=xxx -spring.datasource.password=xxx -spring.datasource.druid.max-active=20 -spring.datasource.druid.min-idle=2 -spring.datasource.druid.initial-size=2 - - -seata.enabled=true -spring.cloud.alibaba.seata.tx-service-group=business-service -seata.service.vgroup-mapping.business-service=default -seata.service.grouplist.default=127.0.0.1:8091 -seata.service.disable-global-transaction=false - -## if use registry center -#seata.registry.type=nacos -#seata.registry.nacos.cluster=default -#seata.registry.nacos.server-addr=localhost -# -## if use config center -#seata.config.type=apollo -#seata.config.apollo.apollo-meta=http://192.168.1.204:8801 -#seata.config.apollo.app-id=seata-server diff --git a/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/resources/application.yml b/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/resources/application.yml new file mode 100644 index 000000000..2464cd09d --- /dev/null +++ b/spring-cloud-alibaba-examples/seata-example/storage-service/src/main/resources/application.yml @@ -0,0 +1,52 @@ +base: + config: + mdb: + hostname: #your mysql server ip address + dbname: #your database name for test + port: #your mysql server listening port + username: #your mysql server username + password: #your mysql server password + +server: + port: 18082 + +spring: + cloud: + nacos: + discovery: + server-addr: 127.0.0.1:8848 + application: + name: storage-service + main: + allow-bean-definition-overriding: true + datasource: + name: storageDataSource + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://${base.config.mdb.hostname}:${base.config.mdb.port}/${base.config.mdb.dbname}?useSSL=false&serverTimezone=UTC + username: ${base.config.mdb.username} + password: ${base.config.mdb.password} + druid: + max-active: 20 + min-idle: 2 + initial-size: 2 + +seata: + enabled: true + application-id: ${spring.application.name} + tx-service-group: ${spring.application.name}-tx-group + config: + type: nacos + nacos: + serverAddr: 127.0.0.1:8848 + dataId: "seata.properties" + username: "nacos" + password: "nacos" + registry: + type: nacos + nacos: + application: seata-server + server-addr: 127.0.0.1:8848 + username: "nacos" + password: "nacos" +