From a451fc554ed5021d2cf43579670e566cf33c4362 Mon Sep 17 00:00:00 2001 From: windwheel Date: Sun, 3 Jul 2022 15:42:08 +0800 Subject: [PATCH] add seata doc --- .../src/main/asciidoc-zh/seata.adoc | 63 +++++++++++++++++++ .../src/main/asciidoc/seata.adoc | 62 ++++++++++++++++++ .../seata-example/all.sql | 41 ++++++++++++ .../seata-example/business-service/pom.xml | 6 +- .../src/main/resources/application.properties | 10 ++- 5 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 spring-cloud-alibaba-docs/src/main/asciidoc-zh/seata.adoc create mode 100644 spring-cloud-alibaba-docs/src/main/asciidoc/seata.adoc create mode 100644 spring-cloud-alibaba-examples/seata-example/all.sql diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc-zh/seata.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/seata.adoc new file mode 100644 index 000000000..5a1643a36 --- /dev/null +++ b/spring-cloud-alibaba-docs/src/main/asciidoc-zh/seata.adoc @@ -0,0 +1,63 @@ +== Spring Cloud Alibaba Seata + +=== Seata 介绍 + +Seata是一个分布式事务框架, 用于保证在微服务架构下每个服务的数据一致性 + + +=== 如何使用seata + +如果要在您的项目中引入 Seata,使用 group ID 为 `com.alibaba.cloud` 和 artifact ID 为 `spring-cloud-starter-alibaba-seata` 的 starter。 + +```xml + + com.alibaba.cloud + spring-cloud-starter-alibaba-seata + +``` + +在运行[spring-cloud-alibaba-examples/seata-example](https://github.com/alibaba/spring-cloud-alibaba/tree/2021.x/spring-cloud-alibaba-examples/seata-example)之前,您需要完成以下步骤: + - 1.保证 本地已经运行```nacos-server ```在 ```8848```端口 + - 2.根据 ```spring-cloud-alibaba-examples/seata-example```下的 ```all.sql ```配置数据库 + - 3.根据选择的事务模式,创建[事务日志表](https://github.com/seata/seata/tree/develop/script/client) 比如默认为AT模式,则进入at/db下选择对应的数据库脚本执行 + - 4.创建 seata事务相关的[状态记录表](https://github.com/seata/seata/tree/develop/script/server/db) ```global_table```、```branch_table```、```lock_table```、```distributed_lock``` + - 5.创建```spring-cloud-alibaba-examples/seata-example```所需的数据库表 + - 6.启动```seata-server``` + + - 7.创建```spring-cloud-alibaba-examples/seata-example```中的Nacos配置,data id: seata.properties, Group: SEATA_ Group(Seata 1.5.1 默认组) 配置导入nacos配置在seata属性中添加示例中需要 的如下事务组配置 + ```txt + 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 + ``` + - 8.根据seata官方提供的[seata-server.jar](https://seata.io/zh-cn/docs/ops/deploy-guide-beginner.html) 启动Seata Server + - 9.在本地启动 ```spring-cloud-alibaba-examples/seata-example```文件夹下的子服务 ``` business-service```, ```order-service ```, ```storage-service ```,最后启动全局事务控制服务 ``` account-service``` + +=== Seata Dashboard + +Seata 1.5.1支持Seata控制台本地访问控制台地址: ```http://127.0.0.1:7091``` +通过Seata控制台可以观察到正在执行的事务信息和全局锁信息,并且在事务完成时删除相关信息。 + + +=== 如何验证分布式事务的成功? +### Xid信息是否传输成功 +在四个服务的```Controller```中```account-service```,```order-service```,```business-service```,```storage-service``` 首先```storage-service```执行的逻辑是输出```RootContext```中的```Xid```信息。如果看到输出了正确的```Xid```信息,每次都在变化,同一个调用中所有服务的```Xid```是一致的。这表明```Seata```的```Xid```的转移和恢复是正常的。 + +### 数据库中数据的一致性 + +在这个例子中,我们模拟一个用户购买商品的场景,StorageService 负责扣除库存数量,OrderService 负责保存订单,BusinessService 负责扣除用户账户余额,AccountService 负责更新账号的余额,并作为全局事务控制入口。 +为了演示示例,我们在 OrderService 和 AcountService 中使用了 Random。NextBoolean() 随机抛出异常,模拟调用服务时随机发生异常的场景。 + +如果分布式事务是有效的,那么下面的等式应该是正确的 + + - 用户原始金额(1000)=用户现有金额+商品单价(2)*订单数量*每个订单的商品数量(2) + + - 初始商品数量 (100) = 现有商品数量 + 订单数量 * 每个订单的商品数量 (2) + +=== Spring Cloud 支持点 + - 通过 Spring MVC 提供服务的服务提供者在收到 HTTP 请求时,可以自动恢复 Seata 上下文,该请求在 header 中包含 Seata 信息。 + - 当服务调用者通过 RestTemplate 调用时,支持自动传递 Seata 上下文。 + - 当服务调用者通过 FeignClient 调用时,支持自动传递 Seata 上下文。 + - 支持同时使用 SeataClient 和 Hystrix 的场景。 + - 支持 SeataClient 和 entinel 使用的场景。 \ No newline at end of file diff --git a/spring-cloud-alibaba-docs/src/main/asciidoc/seata.adoc b/spring-cloud-alibaba-docs/src/main/asciidoc/seata.adoc new file mode 100644 index 000000000..4e30d4f0f --- /dev/null +++ b/spring-cloud-alibaba-docs/src/main/asciidoc/seata.adoc @@ -0,0 +1,62 @@ +== Spring Cloud Alibaba Seata + +=== Introducing Seata + +Seata is a distributed transaction framework to ensure the data consistency of each service under the microservice architecture + + +=== How to use seata + +To include Seata in your project, use the starter with group ID `com.alibaba.cloud` and artifact ID `spring-cloud-starter-alibaba-seata`. + +````xml + + com.alibaba.cloud + spring-cloud-starter-alibaba-seata + +```` + +Running [spring-cloud-alibaba-examples/seata-example](https://github.com/alibaba/spring-cloud-alibaba/tree/2021.x/spring-cloud-alibaba-examples/seata-example) Before, you need to complete the following steps: + - 1. Ensure that ```nacos-server ``` is running locally on the ```8848``` port + - 2. Configure the database according to ```all.sql ``` under ```spring-cloud-alibaba-examples/seata-example``` + - 3. According to the selected transaction mode, create a [transaction log table] (https://github.com/seata/seata/tree/develop/script/client) For example, the default is AT mode, then enter at/db and select the corresponding The database script executes + - 4. Create a [status record table] related to seata transactions (https://github.com/seata/seata/tree/develop/script/server/db) ```global_table```, ```branch_table`` `, ```lock_table```, ```distributed_lock``` + - 5. Create the database tables required by ```spring-cloud-alibaba-examples/seata-example``` + - 6. Start ```seata-server``` + + - 7. Create the Nacos configuration in ```spring-cloud-alibaba-examples/seata-example```, data id: seata.properties, Group: SEATA_ Group (Seata 1.5.1 default group) Configuration import nacos configuration in Add the following transaction group configuration required in the example to the seata attribute + ```txt + 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 + ``` + - 8. Start Seata Server according to the official [seata-server.jar](https://seata.io/zh-cn/docs/ops/deploy-guide-beginner.html) provided by seata + - 9. Start the sub-services under the ```spring-cloud-alibaba-examples/seata-example``` folder locally ``` business-service```, ```order-service ```, ` ``storage-service ```, and finally start the global transaction control service ``` account-service``` + +=== Seata Dashboard + +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. + + +=== How to verify the success of a distributed transaction? +### Whether the Xid information is successfully transmitted +In the ````Controller``` of the four services ````account-service```, ```order-service```, ```business-service```, ```storage-service` `` First of all, the logic executed by ````storage-service``` is to output the ```Xid``` information in ```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 the same. This indicates that the transfer and recovery of the ```Xid``` of ```Seata``` is normal. +### Consistency of data in the database + +In this example, we simulate a scenario in which a user purchases goods. StorageService is responsible for deducting the inventory quantity, OrderService is responsible for saving orders, BusinessService is responsible for deducting the user's account balance, and AccountService is responsible for updating the account balance, which is used as a global transaction control entry. +To demonstrate the example, we use Random in OrderService and AcountService. NextBoolean() throws an exception randomly, simulating a scenario where an exception occurs randomly when calling a service. + +If distributed transactions are efficient, then the following equation should be true + + - User's original amount (1000) = user's existing amount + product unit price (2) * order quantity * product quantity per order (2) + + - Initial Item Quantity (100) = Existing Item Quantity + Order Quantity * Item Quantity per Order (2) + +=== Spring Cloud Support Points + - Service providers that provide services through Spring MVC can automatically restore the Seata context when they receive an HTTP request that includes Seata information in the header. + - Supports automatic passing of Seata context when service caller calls via RestTemplate. + - Supports automatic passing of Seata context when service caller calls via FeignClient. + - Supports scenarios using SeataClient and Hystrix at the same time. + - Support for scenarios used by SeataClient and entinel. \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/seata-example/all.sql b/spring-cloud-alibaba-examples/seata-example/all.sql new file mode 100644 index 000000000..259c5e4f6 --- /dev/null +++ b/spring-cloud-alibaba-examples/seata-example/all.sql @@ -0,0 +1,41 @@ +CREATE TABLE `account_tbl` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` varchar(255) DEFAULT NULL, + `money` int(11) DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +CREATE TABLE `storage_tbl` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `commodity_code` varchar(255) DEFAULT NULL, + `count` int(11) DEFAULT '0', + PRIMARY KEY (`id`), + UNIQUE KEY `commodity_code` (`commodity_code`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +CREATE TABLE `order_tbl` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` varchar(255) DEFAULT NULL, + `commodity_code` varchar(255) DEFAULT NULL, + `count` int(11) DEFAULT '0', + `money` int(11) DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +CREATE TABLE `undo_log` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `branch_id` bigint(20) NOT NULL, + `xid` varchar(100) NOT NULL, + `context` varchar(128) NOT NULL, + `rollback_info` longblob NOT NULL, + `log_status` int(11) NOT NULL, + `log_created` datetime NOT NULL, + `log_modified` datetime NOT NULL, + `ext` varchar(100) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; \ No newline at end of file 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 0ae95db73..ce933932a 100644 --- a/spring-cloud-alibaba-examples/seata-example/business-service/pom.xml +++ b/spring-cloud-alibaba-examples/seata-example/business-service/pom.xml @@ -46,6 +46,10 @@ com.alibaba.cloud spring-cloud-starter-alibaba-sentinel - + + mysql + mysql-connector-java + 8.0.16 + \ 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 index bc40bece3..a108f6f54 100644 --- 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 @@ -2,7 +2,15 @@ server.port=18081 spring.application.name=business-service spring.cloud.nacos.discovery.server-addr=localhost:8848 # The following configuration can be omitted. - +spring.datasource.name="businessDataSource" +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 #feign.hystrix.enabled=true #feign.sentinel.enabled=true feign.client.config.default.connectTimeout=10000