Seata服务端客户端配置搭建与使用,带你解决各种大坑问题(全网最新版本教程)

本文详细介绍了Seata的服务器端配置,包括下载、YAML配置、数据库设置、启动步骤,以及Nacos配置中的重要注意事项。客户端配置涉及依赖引入、数据源配置、Seata使用示例和事务失效解决方案,特别强调了OpenFeign调用中XID的处理。
摘要由CSDN通过智能技术生成

目录

1.服务端配置

1.1.下载seata

1.2.配置yml

1.3.配置seata数据库

1.4.启动

1.5.nacos配置(大坑重要!!!) 

2.客户端配置

2.1.导入依赖

2.3.配置数据源

2.4.使用

2.5.事物失效解决方案(大坑!!!) 


1.服务端配置

1.1.下载seata

我这里是新版本seata-service-1.7.0配置文件和旧版本不一样(下载中心 (seata.io)

1.2.配置yml

新版本是yml旧版本是config(最好搞个备份出来再配置)

配置文件application.yml(不懂的参数可以看官网Seata 参数配置⁤)

# 服务端口号
server:
  port: 7091
# 服务名称
spring:
  application:
    name: seata-server
# 服务日志
logging:
  config: classpath:logback-spring.xml
  file:
    path: ../runninglogs/logs/seata
  extend:
    logstash-appender:
      destination: 127.0.0.1:4560
    kafka-appender:
      bootstrap-servers: 127.0.0.1:9092
      topic: logback_to_logstash
# seata可视化界面登录的账号密码这里自己设置什么启动seata,到时候就用这个来登录(http://localhost:7091/#/sagastatemachinedesigner)
console:
  user:
    username: seata
    password: seata

# seata服务端配置
seata:
  service:
    vgroup-mapping:
         # 前面这个是组名(liuzigu-tx-group) :后面的是对应的集群名映射名(GZ) 这两个很重要到时候客户端要设置一致
         liuzigu-tx-group: GZ
    disable-global-transaction: true
  config:
    # 可设置的配置中心: nacos, consul, apollo, zk, etcd3
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      username: nacos
      password: nacos
  registry:
    # 可设置的注册中心: nacos, eureka, redis, zk, consul, etcd3, sofa
    type: nacos
    nacos:
      application: seata-server
      group: SEATA_GROUP
      server-addr: 127.0.0.1:8848
      cluster: GZ  # 这个参数在每个微服务seata时会用到这是集群参数
      username: nacos
      password: nacos
  store:
    # 可设置的数据源: file 、 db 、 redis
    mode: db
    db:
      datasource: druid
      db-type: mysql
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/seata?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC
      user: root
      password: 123456
      min-conn: 10
      max-conn: 100
      global-table: global_table
      branch-table: branch_table
      lock-table: lock_table
      distributed-lock-table: distributed_lock
      query-limit: 1000
      max-wait: 5000
# 将安全认证进行去除,因为可能会导致一定的问题
  security:
    secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
    tokenValidityInMilliseconds: 1800000
    ignore:
      urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login

上面数据库改成自己的数据库账号密码,我这里是是mysql8.0

先直接创建一个为seata的数据库

1.3.配置seata数据库

去到我们的seata目录下找到script/server/db/mysql.sql这个文件在seata数据库执行生成数据库表

1.4.启动

这里我们已经配置好,可以启动试一试 

没有报错就是启动完成,试一试是否启动成功可以去http://localhost:7091/#/sagastatemachinedesigner这里查看能不能打开这个网站 

 账号密码是你上面配置文件配置的账号密码

1.5.nacos配置(大坑重要!!!) 

去nacos配置中心添加一个配置(重要坑!!!

配置文件名称必须和上面application.yml里面配置的一样

然后组名必须为你配置文件的组名

还有TEXT内容也必须是你配置的内容,这个是找集群名的内容其实算是这个内容

注:这个一定要配置不然你客户端找不到集群和这个事物组名启动不了,这个配置实在是太坑了 

2.客户端配置

2.1.导入依赖

      <!-- seata相关的配置 这里的版本最好引入和seata下载服务版本一致的依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
            <version>2022.0.0.0-RC2</version>
            <exclusions>
           <!-- 排除原来的依赖原来的版本依赖不一定对 --> 
                <exclusion>
                    <groupId>io.seata</groupId>
                    <artifactId>seata-all</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
       <!-- 我服务端是1.7.0这里就引入1.7.0 -->
        <dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-all</artifactId>
            <version>1.7.0</version>
        </dependency>

2.2.配置yml

配置客户端application.yml

# 服务端口配置
server:
  port: 2003
# 应用程序配置
spring:
  application:
    name: seata-account-service  # 服务名称
  datasource: #这里被我们手动配置的数据源代替了
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/seata_account?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC
    username: root
    password: 123456
    #  cloud配置
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        group: SEATA_GROUP # 这里配置到哪个组主要看自己 这里没有强制性要求
        cluster-name: GZ # 这里配置到哪个集群要看自己 这里没有强制性要求
# seata配置
seata:
  tx-service-group: liuzigu-tx-group #事务组名称 必须一定和你服务端配置的一样 必须 必须 必须
  service:
    vgroup-mapping:
      default-tx-group: GZ  #事务组内容 须一定和你服务端配置的一样
      # 配置中心按照这个要求配置和服务端类似
  config:
    type: nacos
    nacos:
      group: SEATA_GROUP
      server-addr: 127.0.0.1:8848
      username: nacos
      password: nacos
      # 注册中心按照这个要求配置和服务端类似
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: localhost:8848
      username: nacos
      password: nacos
      cluster: GZ
      group: SEATA_GROUP

# mybatis-plus配置
mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true
  mapper-locations: classpath:mapper/*.xml

# 暴露应用程序指标配置
management:
  endpoints:
    web:
      exposure:
        include: '*'
 # 日志配置
logging:
  level:
    io:
      seata: info

2.3.配置数据源

配置seata代理数据源(这里要配置不配置seat代理的话事物不生效)

import com.alibaba.druid.pool.DruidDataSource;
import io.seata.rm.datasource.DataSourceProxy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;

/**
 * @author 刘子固
 * @create 2019-12-11 16:58
 * 使用Seata对数据源进行代理
 */
@Configuration
public class DataSourceProxyConfig {

    @Bean
    public DataSource druidDataSource() {
        // 其实这里的信息可以拿配置文件的,我这里写死了
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        druidDataSource.setUrl("jdbc:mysql://localhost:3306/seata_order?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true");
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("123456");
        // 这里就是把我们德鲁伊数据源交给seata代理
        DataSourceProxy dataSourceProxy = new DataSourceProxy(druidDataSource);
        return dataSourceProxy;
    }

}

2.4.使用

调用远程服务我这里用的是openFeign远程调用加@GlobalTransactional 注解开启分布式事物类似我们单机的Spring@Transactional注解

/**
 * @author 刘子固
 * @description 针对表【t_order】的数据库操作Service实现
 * @createDate 2023-10-08 13:53:35
 */
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Autowired
    AccountService accountService;
    @Autowired
    StorageService storageService;


    @Override
    @GlobalTransactional
    public void create(Order order) {
        System.out.println("seata全局事务id====================>"+ RootContext.getXID());
        // 1.创建订单
        log.info("--------------创建订单开始");
        baseMapper.create(order);
        // 2.扣减库存
        log.info("-------------调用微服务扣减---库存");
        storageService.decrease(order.getProductId(), order.getCount());
        // 3.扣减余额
        log.info("-------------调用微服务扣减---余额");
        accountService.decrease(order.getUserId(), order.getMoney());
        log.info("--------------创建订单初步结束");
        // 4.修改订单状态
        log.info("--------------修改订单状态");
        baseMapper.updateOrderStatus(order.getUserId(), 0);
        log.info("--------------修改订单状态完成");
    }
}

2.5.事失效解决方案(大坑!!!) 

如果用的远程调用是openFeign的话,或者事物不生效的情况下检查你其他服务的xid是不是为空或者不一致(其他远程调用框架也一样这样配置请求头加xid)

// 在订单模块服务的接口里打印
System.out.println("seata全局事务id--订单模块====================>"+ RootContext.getXID());
// 在仓库模块服务的接口里打印
System.out.println("seata全局事务id--仓库模块====================>"+ RootContext.getXID());
// 在支付模块服务的接口里打印
System.out.println("seata全局事务id--支付模块====================>"+ RootContext.getXID());

你的事物生效就是因为你远程调用的时候远程调用框架没有把xid在请求头传到对应的服务去,所以才会导致事物失效,因为想要事物生效一整个服务调用链必须保证xid是一样的。

这里openFeign远程调用的解决方法是这样的

openFeign配置类

import feign.RequestInterceptor;
import feign.RequestTemplate;
import io.seata.core.context.RootContext;

/**
 * openFeign配置类
 *
 * @author 刘子固
 * @version 1.0
 * @date 2023/10/9 17:25
 */

public class MultipartSupportConfig implements RequestInterceptor {

    /**
     * 解决服务直接调用请求头不传递的问题
     *
     * @param template
     */
    @Override
    public void apply(RequestTemplate template) {
        // 解决seata的xid未传递
        String xid = RootContext.getXID();
        template.header(RootContext.KEY_XID, xid);
    }
}

微服务调用接口

在@FeignClient这个注解加上configuration属性然后值为刚刚的配置类这样事物不生效的问题就解决啦

import java.math.BigDecimal;

/**
 * 库存微服务调用接口
 *
 * @author 刘子固
 * @version 1.0
 * @date 2023/10/8 14:18
 */
@FeignClient(name = "seata-account-service",configuration = MultipartSupportConfig.class)
public interface AccountService {
    /**
     * 扣余额
     *
     * @param userId 用户id
     * @param money     金额
     * @return 统一返回
     */
    @PostMapping(value = "/account/decrease")
    CommonResult decrease(@RequestParam("userId") Long userId, @RequestParam("money") BigDecimal money);
}

好了教程到这里就结束了,有什么不理解的地方可以私信博主哦!

给个关注吧!!!

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值