说明:
之所以只用nacos进行了注册与发现,因为seata使用nacos后进行配置中心的化,需要往nacos中导入py脚本生成配置,还需要在服务端多加两个配置,过程比较繁琐,容易出问题,不太适合对这个框架理解不是很深的开发者
关于集成之后出现与mybatisplus冲突问题,插件失效,自动填充失效等问题,请看本人seata分类下另一篇文章
版本说明:
mysql 5.7
seata 1.4
springboot:2.3.7
springcloud:Hoxton.SR12
springcloudAlibaba: 2.2.6.RELEASE
服务端搭建及配置
-
下载seata 下载地址:下载中心 (seata.io)
-
上传至虚拟机/服务器/本地
解压该文件:解压后
-
进入conf目录
-
修改registry.conf文件
对应配置:
registry { # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa type = "nacos" loadBalance = "RandomLoadBalance" loadBalanceVirtualNodes = 10 nacos { application = "seata-server" serverAddr = "192.168.3.160:8848" group = "SEATA_GROUP" namespace = "" cluster = "default" username = "" password = "" } file { name = "file.conf" } } config { # file、nacos 、apollo、zk、consul、etcd3 type = "file" nacos { serverAddr = "127.0.0.1:8848" namespace = "" group = "SEATA_GROUP" username = "" password = "" } file { name = "file.conf" } } -
修改file.config文件
对应配置:
## transaction log store, only used in seata-server store { ## store mode: file、db、redis mode = "db" ## database store property db { ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc. datasource = "druid" ## mysql/oracle/postgresql/h2/oceanbase etc. dbType = "mysql" driverClassName = "com.mysql.jdbc.Driver" url = "jdbc:mysql://127.0.0.1:3306/seata" user = "root" password = "123456" minConn = 5 maxConn = 100 globalTable = "global_table" branchTable = "branch_table" lockTable = "lock_table" queryLimit = 100 maxWait = 5000 } } -
因为我们这里配置的持久化方式为mysql,在第六步中也有体现,这里需要将第六步配置的数据库创建出来
-
创建数据库库名为seata
-
导入SQL脚本,脚本为:
/* Navicat Premium Data Transfer Source Server : Mysql3.160 Source Server Type : MySQL Source Server Version : 50732 Source Host : 192.168.3.160:3306 Source Schema : seata Target Server Type : MySQL Target Server Version : 50732 File Encoding : 65001 Date: 13/12/2021 14:33:52 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for branch_table -- ---------------------------- DROP TABLE IF EXISTS `branch_table`; CREATE TABLE `branch_table` ( `branch_id` bigint(20) NOT NULL, `xid` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `transaction_id` bigint(20) NULL DEFAULT NULL, `resource_group_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `resource_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `branch_type` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `status` tinyint(4) NULL DEFAULT NULL, `client_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `application_data` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `gmt_create` datetime(6) NULL DEFAULT NULL, `gmt_modified` datetime(6) NULL DEFAULT NULL, PRIMARY KEY (`branch_id`) USING BTREE, INDEX `idx_xid`(`xid`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of branch_table -- ---------------------------- -- ---------------------------- -- Table structure for global_table -- ---------------------------- DROP TABLE IF EXISTS `global_table`; CREATE TABLE `global_table` ( `xid` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `transaction_id` bigint(20) NULL DEFAULT NULL, `status` tinyint(4) NOT NULL, `application_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `transaction_service_group` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `transaction_name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `timeout` int(11) NULL DEFAULT NULL, `begin_time` bigint(20) NULL DEFAULT NULL, `application_data` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `gmt_create` datetime NULL DEFAULT NULL, `gmt_modified` datetime NULL DEFAULT NULL, PRIMARY KEY (`xid`) USING BTREE, INDEX `idx_gmt_modified_status`(`gmt_modified`, `status`) USING BTREE, INDEX `idx_transaction_id`(`transaction_id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of global_table -- ---------------------------- -- ---------------------------- -- Table structure for lock_table -- ---------------------------- DROP TABLE IF EXISTS `lock_table`; CREATE TABLE `lock_table` ( `row_key` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `xid` varchar(96) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `transaction_id` bigint(20) NULL DEFAULT NULL, `branch_id` bigint(20) NOT NULL, `resource_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `table_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `pk` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `gmt_create` datetime NULL DEFAULT NULL, `gmt_modified` datetime NULL DEFAULT NULL, PRIMARY KEY (`row_key`) USING BTREE, INDEX `idx_branch_id`(`branch_id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of lock_table -- ---------------------------- SET FOREIGN_KEY_CHECKS = 1; -
导入后样子:
-
-
至此服务端配置配置完成,cd目录到bin目录通过以下命令进行启动,-h 127.0.0.1 可替换为真实的虚拟机地址,最好指定真实的,否则可能出现无法预估的错误
nohup sh seata-server.sh -p 8091 -h 127.0.0.1 -m file > catalina.out 2>&1 &
客户端配置
-
引入seata依赖
<!--seata--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-seata</artifactId> <version>2021.1</version> </dependency> <!--mybatis-plus 因为需要替换mybatisplus的数据源,所以引入了这个依赖--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <scope>provided</scope> </dependency> -
在resources下添加两个文件,分别为file.conf和registry.conf
registry.conf内容为
内容为:
registry { # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa type = "nacos" loadBalance = "RandomLoadBalance" loadBalanceVirtualNodes = 10 nacos { application = "seata-server" serverAddr = "192.168.3.160:8848" group = "SEATA_GROUP" namespace = "" cluster = "default" username = "" password = "" } file { name = "file.conf" } } config { # file、nacos 、apollo、zk、consul、etcd3 type = "file" nacos { serverAddr = "192.168.3.160:8848" namespace = "" group = "SEATA_GROUP" username = "" password = "" } file { name = "file.conf" } } file.conf内容为:此处需注意vgroupMapping这里进行了修改,原为vgroup_mapping,不改为驼峰会出现ip:port这个错误,导致项目起不来
内容如下:
transport { # tcp udt unix-domain-socket type = "TCP" #NIO NATIVE server = "NIO" #enable heartbeat heartbeat = true #thread factory for netty thread-factory { boss-thread-prefix = "NettyBoss" worker-thread-prefix = "NettyServerNIOWorker" server-executor-thread-prefix = "NettyServerBizHandler" share-boss-worker = false client-selector-thread-prefix = "NettyClientSelector" client-selector-thread-size = 1 client-worker-thread-prefix = "NettyClientWorkerThread" # netty boss thread size,will not be used for UDT boss-thread-size = 1 #auto default pin or 8 worker-thread-size = 8 } } service { #vgroup->rgroup vgroupMapping.from-sys_tx_group = "default" #only support single node default.grouplist = "192.168.3.160:8091" #degrade current not support enableDegrade = false #disable disable = false } ## transaction log store, only used in seata-server store { ## store mode: file、db、redis mode = "db" ## database store property db { ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc. datasource = "druid" ## mysql/oracle/postgresql/h2/oceanbase etc. dbType = "mysql" driverClassName = "com.mysql.jdbc.Driver" url = "jdbc:mysql://192.168.3.160:3306/seata" user = "root" password = "123456" minConn = 5 maxConn = 30 globalTable = "global_table" branchTable = "branch_table" lockTable = "lock_table" queryLimit = 100 maxWait = 5000 } } application.yml需配置以下内容:
内容如下:
spring: #---------------数据库连接配置-------------- datasource: type: com.alibaba.druid.pool.DruidDataSource # 连接url url: jdbc:mysql://192.168.3.160:3306/from-sys?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true # 驱动名称 driver-class-name: com.mysql.jdbc.Driver username: root password: 123456 initialSize: 5 minIdle: 5 maxActive: 20 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: SELECT user() testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true connection-properties: druid.stat.mergeSql:true;druid.stat.slowSqlMillis:5000 # -------------- nacos配置--------------- cloud: nacos: discovery: server-addr: 192.168.3.160:8848 alibaba: seata: tx-service-group: ${spring.application.name}_tx_group seata: registry: type: nacos nacos: server-addr: 192.168.3.160:8848 group: "SEATA_GROUP" namespace: "" username: "nacos" password: "nacos" server: port: 9001 servlet: context-path: /sys/ -
配置代理数据源
package com.from.seata.config; import com.alibaba.druid.pool.DruidDataSource; import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties; import com.baomidou.mybatisplus.core.MybatisConfiguration; import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean; import io.seata.rm.datasource.DataSourceProxy; import org.mybatis.spring.transaction.SpringManagedTransactionFactory; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import javax.sql.DataSource; @Configuration @EnableConfigurationProperties({MybatisPlusProperties.class}) public class DataSourcesProxyConfig { @Bean @ConfigurationProperties(prefix = "spring.datasource") public DataSource druidDataSource() { return new DruidDataSource(); } //创建代理数据源 @Primary//@Primary标识必须配置在代码数据源上,否则本地事务失效 @Bean public DataSourceProxy dataSourceProxy(DataSource druidDataSource) { return new DataSourceProxy(druidDataSource); } private MybatisPlusProperties properties; public DataSourcesProxyConfig(MybatisPlusProperties properties) { this.properties = properties; } //替换SqlSessionFactory的DataSource @Bean public MybatisSqlSessionFactoryBean sqlSessionFactory(DataSourceProxy dataSourceProxy) throws Exception { // 这里必须用 MybatisSqlSessionFactoryBean 代替了 SqlSessionFactoryBean,否则 MyBatisPlus 不会生效 MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean(); mybatisSqlSessionFactoryBean.setDataSource(dataSourceProxy); mybatisSqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory()); mybatisSqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver() .getResources("classpath:/mapper/**/*.xml")); //注意:!!!!这个如果写的有sql,需有该配置,try cach以下,不配置造成sql找不到,打开不捕获异常的化,没sql会报错 MybatisConfiguration configuration = this.properties.getConfiguration(); if(configuration == null){ configuration = new MybatisConfiguration(); } mybatisSqlSessionFactoryBean.setConfiguration(configuration); return mybatisSqlSessionFactoryBean; } }至此seata的分布式事务就配置完成了,可以优化为seata单独抽成一个模块,当我们服务需要使用分布式事务时候,引入seata模块的依赖,进行相同的配file,registry,yml配置即可,只需修改以下下内容,其他配置不变即可
你可能遇到的bug:
-
1.Failed to get available servers: endpoint format should like ip:port
file.conf中的vgroupMapping你用的可能是vgroup_mapping -
0101 can not connect to 127.0.0.1:8091 cause:can not register RM,err:can not connect to services-server. nacos注册发现的情况下:则是由于yml里面没有配置seata的注册发现造成的
-
0101 can not connect to 远程地址:8091 cause:can not register RM,err:can not connect to services-server.
由于你的启动seata服务时候没有指定IP端口造成的,导致你注册到nacos上的seata服务地址跟你客户端预想的seata地址不一致造成的,修改为真实的你的服务器地址