springboot+nacos+seata14实现分布式

1
2
3
4
yaml复制代码版本:
Springboot:2.2.0
SpringCloud: 2020.0.3
Seata: 1.4

本文章demo地址:gitee.com/TZWw/spring…

1. 下载seata

1)地址:seata.io/zh-cn/blog/…
√
2)在conf文件夹修改file.conf文件
在这里插入图片描述

3)向本地数据库导入seata需要的表

  • 创建名字为seata的数据库
  • 新建表branch_table、global_table、lock_table
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
scss复制代码CREATE TABLE `branch_table` (
`branch_id` bigint NOT NULL,
`xid` varchar(128) NOT NULL,
`transaction_id` bigint DEFAULT NULL,
`resource_group_id` varchar(32) DEFAULT NULL,
`resource_id` varchar(256) DEFAULT NULL,
`lock_key` varchar(128) DEFAULT NULL,
`branch_type` varchar(8) DEFAULT NULL,
`status` tinyint DEFAULT NULL,
`client_id` varchar(64) DEFAULT NULL,
`application_data` varchar(2000) DEFAULT NULL,
`gmt_create` datetime DEFAULT NULL,
`gmt_modified` datetime DEFAULT NULL,
PRIMARY KEY (`branch_id`),
KEY `idx_xid` (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
r复制代码CREATE TABLE `global_table` (
`xid` varchar(128) NOT NULL,
`transaction_id` bigint DEFAULT NULL,
`status` tinyint NOT NULL,
`application_id` varchar(32) DEFAULT NULL,
`transaction_service_group` varchar(32) DEFAULT NULL,
`transaction_name` varchar(128) DEFAULT NULL,
`timeout` int DEFAULT NULL,
`begin_time` bigint DEFAULT NULL,
`application_data` varchar(2000) DEFAULT NULL,
`gmt_create` datetime DEFAULT NULL,
`gmt_modified` datetime DEFAULT NULL,
PRIMARY KEY (`xid`),
KEY `idx_gmt_modified_status` (`gmt_modified`,`status`),
KEY `idx_transaction_id` (`transaction_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
1
2
3
4
5
6
7
8
9
10
11
12
sql复制代码CREATE TABLE `lock_table` (
`row_key` varchar(128) NOT NULL,
`xid` varchar(96) DEFAULT NULL,
`transaction_id` mediumtext,
`branch_id` mediumtext,
`resource_id` varchar(256) DEFAULT NULL,
`table_name` varchar(32) DEFAULT NULL,
`pk` varchar(36) DEFAULT NULL,
`gmt_create` datetime DEFAULT NULL,
`gmt_modified` datetime DEFAULT NULL,
PRIMARY KEY (`row_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

seata数据库

4)修改registry.conf文件
在这里插入图片描述
在这里插入图片描述
5)将seata配置信息添加到nacos配置中心

1.启动本地的nacos服务
2.下载config.txt和nacos-config.sh两个文件
github.com/seata/seata…
github.com/seata/seata…
3.然后执行nacos-config.sh脚本

在这里插入图片描述

4.查看nacos中添加成功的配置

在这里插入图片描述

6)启动seata

进入bin目录下,执行
./seata-server.sh
出现下图即为启动成功

在这里插入图片描述

2. 服务间调用(服务one调用服务two)

1)创建one和two数据库,每个数据库都必须包含undo_log表

  • one数据库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
sql复制代码CREATE TABLE `count` (
`id` int NOT NULL AUTO_INCREMENT,
`count` int DEFAULT NULL COMMENT '库存',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8mb3;

CREATE TABLE `undo_log` (
`id` bigint NOT NULL AUTO_INCREMENT,
`branch_id` bigint NOT NULL,
`xid` varchar(100) NOT NULL,
`context` varchar(128) NOT NULL,
`rollback_info` longblob NOT NULL,
`log_status` int 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=20 DEFAULT CHARSET=utf8mb3;
  • two数据库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
sql复制代码CREATE TABLE `order` (
`id` int NOT NULL AUTO_INCREMENT,
`order_count` int DEFAULT NULL,
`product_id` bigint DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb3;

CREATE TABLE `undo_log` (
`id` bigint NOT NULL AUTO_INCREMENT,
`branch_id` bigint NOT NULL,
`xid` varchar(100) NOT NULL,
`context` varchar(128) NOT NULL,
`rollback_info` longblob NOT NULL,
`log_status` int 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=3 DEFAULT CHARSET=utf8mb3;

在这里插入图片描述

  1. 创建one和two服务

此处省略创建服务过程。。。

在这里插入图片描述

maven父工程依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
java复制代码<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<modules>
<module>serviceone</module>
<module>servicetwo</module>
<!-- common是公共类-->
<module>servicecommon</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo2</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2020.0.3</spring-cloud.version>
<spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.3.3.RELEASE</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<version>2.2.3.RELEASE</version>
</dependency>


<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>

<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2021.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
<type>pom</type>
<scope>import</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-log4j -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j</artifactId>
<version>1.3.8.RELEASE</version>
</dependency>

</dependencies>
</dependencyManagement>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>

</project>
  • one服务:

bootstrap.yml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
java复制代码# Spring
spring:
application:
# 应用名称
name: service-one
profiles:
# 环境配置
active: dev
main:
allow-bean-definition-overriding: true
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: localhost:8848
# namespace: 3d25ad9f-6b5a-4f1a-a4a7-0bbba90a00fa
group: SEATA_GROUP
config:
# 配置中心地址
server-addr: localhost:8848
namespace: 8221aa53-c648-4c6a-8a41-0c3a685ba58e
# # 配置文件格式
file-extension: yml
# # 共享配置
# shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
#
seata:
tx-service-group: my_test_tx_group
registry:
type: nacos
nacos:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
group: ${spring.cloud.nacos.discovery.group}
# namespace: 6c990727-93b2-4081-a8c6-6b015c56eda2
config:
type: nacos
nacos:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
group: ${spring.cloud.nacos.discovery.group}
# namespace: 6db428d4-e7a3-4dd3-be02-283960e0e704
service:
vgroup-mapping:
my_test_tx_group: default

在这里插入图片描述

nacos中one的配置(service-one-dev.yml):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
yaml复制代码# Spring
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/service-one?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 123456789

server:
port: 8085

# Mybatis配置
mybatis:
# 配置mapper的扫描,找到所有的mapper.xml映射文件
mapperLocations: classpath:mapper/**/*.xml

httpclient:
enabled: true

one服务依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
xml复制代码<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>

<!--nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alibaba-nacos-config -->
<!-- 不配置无法读取nacos配置 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
<!-- 升级spring cloud版本之后发现bootstrap.yml 失效了,阅读官方文档得知,需要新增一个引用来开启bootstrap.xml文件的读取,
新版spring cloud默认是关闭读取了。-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!-- 不引入,bootstrap.yml无法使用 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<version>3.0.2</version>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 添加feign -->
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.6.6</version>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j</artifactId>
</dependency>

<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
<!-- 在 pom 中添加依賴,解决使用get方式请求时出现的Request method 'POST' not supported-->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
</dependencies>

controller :

1
2
3
4
5
6
7
8
9
java复制代码    @GetMapping("/insertOpt")
public CommonResult insertOpt() {
try {
countService.insertOpt();
return new CommonResult(true, "成功", null);
} catch (Exception e) {
return new CommonResult(false, "失败", null);
}
}

serviceImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
java复制代码 	@Override
@GlobalTransactional(rollbackFor = Exception.class, name = "insertOpt")
public CommonResult insertOpt() {
Count count = new Count();
count.setCount(12);
int insert = this.countDao.insert(count);
if (insert == 0) {
throw new RuntimeException("first失败");
}
Order order = new Order();
order.setOrderCount(12);
order.setProductId(12L);
CommonResult commonResult = remoteServiceTwo.insertOne(order);
if (!commonResult.getBool()){
throw new RuntimeException("操作远程失败!");
}
Map<String, Object> map = new HashMap<>(16);
map.put("count", insert);
map.put("order", commonResult);
System.err.println("map===="+ map.toString());
return new CommonResult(true, "成功", map);
}

feign请求

1
2
3
4
5
6
7
java复制代码@FeignClient(value = "service-two")
public interface RemoteServiceTwo {

@PostMapping("/order/insertOne")
public CommonResult insertOne(Order order);

}
  • two服务

bootstrap.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
java复制代码# Spring
spring:
application:
# 应用名称
name: service-two
profiles:
# 环境配置
active: dev
main:
allow-bean-definition-overriding: true
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: localhost:8848
# namespace: 3d25ad9f-6b5a-4f1a-a4a7-0bbba90a00fa
group: SEATA_GROUP
config:
# 配置中心地址
server-addr: localhost:8848
namespace: 8221aa53-c648-4c6a-8a41-0c3a685ba58e
# # 配置文件格式
file-extension: yml
# # 共享配置
# shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}


seata:
tx-service-group: my_test_tx_group
registry:
type: nacos
nacos:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
group: ${spring.cloud.nacos.discovery.group}
# namespace: 6c990727-93b2-4081-a8c6-6b015c56eda2
config:
type: nacos
nacos:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
group: ${spring.cloud.nacos.discovery.group}
service:
vgroup-mapping:
my_test_tx_group: default

pom.xml 依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
java复制代码    <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>

<!--nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alibaba-nacos-config -->
<!-- 不配置无法读取nacos配置 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
<!-- 升级spring cloud版本之后发现bootstrap.yml 失效了,阅读官方文档得知,需要新增一个引用来开启bootstrap.xml文件的读取,
新版spring cloud默认是关闭读取了。-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>



<!-- 不引入,bootstrap.yml无法使用 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<version>3.0.2</version>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 添加feign -->
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.6.6</version>
</dependency>

<dependency>
<groupId>com.example</groupId>
<artifactId>servicecommon</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-log4j -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j</artifactId>
</dependency>

<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>


</dependencies>

nacos中two服务的配置service-two-dev.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
java复制代码# Spring
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/service-two?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 123456789

server:
port: 8086

# Mybatis配置
mybatis:
# 配置mapper的扫描,找到所有的mapper.xml映射文件
mapperLocations: classpath:mapper/**/*.xml

# 我使用的这个版本这一步可以忽略
httpclient:
enabled: true

two服务controller

1
2
3
4
5
6
7
8
9
10
java复制代码    @PostMapping("insertOne")
public CommonResult selectOne(@RequestBody Order order) {
try {
this.orderService.insert(order);
return new CommonResult(true, "成功", null);
} catch (Exception e) {
StaticLog.error("失败:======{}", e);
return new CommonResult(false, "失败", null);
}
}

serviceImpl

1
2
3
4
5
6
7
8
9
10
11
12
java复制代码    /**
* 新增数据
*
* @param order 实例对象
* @return 实例对象
*/
@Override
public Order insert(Order order) {
// int a = 1/0; // 此处是为了出现错误,看seata是否会回滚
this.orderDao.insert(order);
return order;
}

3. 查看结果

  • 插入成功操作

浏览器操作

在这里插入图片描述

serviceone的日志

在这里插入图片描述

servicetwo日志

在这里插入图片描述

数据库结果-插入成功 (清空数据库进行插入失败操作)

在这里插入图片描述

  • 插入失败操作
    1) 插入失败,进行回滚—在servicetwo业务代码上添加一个报错代码

在这里插入图片描述

浏览器操作

在这里插入图片描述

serviceone 日志(进行了回滚)

在这里插入图片描述

servicetwo 日志

在这里插入图片描述

数据库数据

在这里插入图片描述

4.成功~~~

我是Tz,想把我遇到的问题告诉你

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%