项目技术

SpringCloudAlibaba Nacos Seata Mysql Feign

代码地址

这个代码我是基于 图灵学院 的项目改的, 原来的项目代码演示下单,扣库存,扣账户金额,一系列的业务代码,我感觉太臃肿了,其实分布式事务无外乎就是多个服务分别进行写操作多个mysql库,要么同时写入成功要么同时写入失败.
我把业务代码都删了,直接用最简单的方式演示多个微服务分别操作不同的数据库,要么同时insert成功,要么触发异常都不会写进数据,不会出现一个库insert进去数据,一个库没有insert进去数据的情况.

代码地址:
​​​https://gitee.com/zjj19941/ZJJ_Neaten5.10/tree/master/ZJJ_Seata/springcloud-nacos-feign-seata​

代码说明

执行sql脚本

项目里面有个db.sql文件,自己自行创建两个数据库,然后根据下面图片去执行sql脚本, 在seata_storage库里面创建undo_log表和storage_tbl表, 在 seata_order库里面创建undo_log表和order_tbl表

SpringCloudAlibaba整合Seata入门demo_spring

registry.conf

registry {
type = "nacos"
nacos {
serverAddr = "zjj101:8848"
namespace = ""
cluster = ""
group = "SEATA_GROUP"
}
}

config {
type = "nacos"
nacos {
serverAddr = "zjj101:8848"
namespace = "7c475dad-93cb-4740-941f-1a6636addd93"
group = "SEATA_GROUP"
}
}

seata 注册中心配置

registry 的type直接选nacos,代表从nacos连接Seata-Server,我都nacos上的public组里面有一个seata-searver,分组名称是SEATA_GROUP,所以 namespace 直接配置"" ,或者删掉不配置也行,serverAddr 指向的是你nacos服务的地址,我这里是zjj101:8848, 我不是集群模式 cluster 直接是"",或者不配置cluster 也行, group配置SEATA_GROUP要和nacos控制面板的seata的分组名称保持一致,不然找不到seata服务.

nacos {
serverAddr = “zjj101:8848”
namespace = “”
cluster = “”
group = “SEATA_GROUP”
}
SpringCloudAlibaba整合Seata入门demo_微服务_02

seata的config配置

config {
type = “nacos”
nacos {
serverAddr = “zjj101:8848”
namespace = “7c475dad-93cb-4740-941f-1a6636addd93”
group = “SEATA_GROUP”
}

type=nacos代表seata从nacos上面读取配置, 问这里seata配置单独是放在了seata组里面的,不然配置放到public里面的话,太多了,有100多条,里面就是一些配置,这些配置是导进来的,如果没有导进来就看 ​​https://www.yuque.com/docs/share/d13e525b-1e1b-4a42-8907-e0c9e7e00acb?#​​​ 《将seata默认配置导入到nacos配置列表中》 这个帖子,

SpringCloudAlibaba整合Seata入门demo_数据_03

nacos {
serverAddr = “zjj101:8848”
namespace = “7c475dad-93cb-4740-941f-1a6636addd93”
group = “SEATA_GROUP”
}

serverAddr = “zjj101:8848” 不用说了,就是配置nacos配置中心的地址
namespace 这个配置的参数就是配置中心的seata组的uuid串儿,SpringCloudAlibaba整合Seata入门demo_微服务_04

group = "SEATA_GROUP" 这个配置就是要和配置中心的Group配置保持一致

SpringCloudAlibaba整合Seata入门demo_微服务_05

事务组配置

在 ​​org.springframework.cloud:spring-cloud-starter-alibaba-seata​​​的​​org.springframework.cloud.alibaba.seata.GlobalTransactionAutoConfiguration​​​类中,默认会使用 ​​${spring.application.name}-seata-service-group​​​作为服务名注册到 Seata Server上,如果和service.vgroup_mapping配置不一致,会提示 ​​no available server to connect​​错误

也可以通过配置 ​​spring.cloud.alibaba.seata.tx-service-group​​​修改后缀,但是必须和​​file.conf​​​中或者nacos配置中心的配置保持一致
SpringCloudAlibaba整合Seata入门demo_spring cloud_06

SpringCloudAlibaba整合Seata入门demo_微服务_07自定义事务组名称需要与seata-server中的对应,具体事务组的作用,回来我稍后研究研究再补上,其实事务组概念我也不是太明白,我觉得就是类似于nacos的Group概念,就是资源隔离的概念,每个事务组可以配置不同的参数,这样更细化,我是这么理解的,如果理解有问题,你们指出来.

调用入口要有@GlobalTransactional注解

调用的地址是: ​​http://localhost:8020/order/test01​​ ​

SpringCloudAlibaba整合Seata入门demo_微服务_08
com.tuling.order.service.impl.OrderServiceImpl#test01 方法是最上层的入口service方法,需要在这个方法上添加@GlobalTransactional注解,不然会出现分布式事务失效.
SpringCloudAlibaba整合Seata入门demo_spring_09

启动项目

直接启动OrderServiceApplication和StorageServiceApplication 这两个启动类,

启动完毕,发现nacos多了这两个服务

SpringCloudAlibaba整合Seata入门demo_java_10

开始测试

正确的请求

Postman执行 post请求 : ​​http://localhost:8020/order/test01​​​ ,参数是{“count”:1}

SpringCloudAlibaba整合Seata入门demo_java_11

执行成功,查看数据库.

发现两个库的表插入成功了,uuid都是ca835d04-8362-48f1-9b44-1e62acd5e0821643795815143
SpringCloudAlibaba整合Seata入门demo_spring_12

失败的请求

OrderService服务会先执行插入数据到order_tbl表操作,然后再调用StorageService服务准备插入数据到storage_tbl表操作, 在插入之前会触发下面的箭头指向的错误代码,.会抛出来ByZero异常出来

模拟业务失败,当count不是1的时候,这里会抛出ByZero异常出来,
SpringCloudAlibaba整合Seata入门demo_数据_13

此时数据库里面没有数据,之前测试的数据我已经清掉了
SpringCloudAlibaba整合Seata入门demo_java_14

postman执行 post请求: ​​http://localhost:8020/order/test01​​​ 参数是:{“count”:2}

SpringCloudAlibaba整合Seata入门demo_spring_15

执行完了发现报错

SpringCloudAlibaba整合Seata入门demo_spring cloud_16

查看两个库的两张表,发现并没有新的数据,说明分布式事务发挥作用了

SpringCloudAlibaba整合Seata入门demo_数据_17