Seata 1.2.0的配置以及踩坑记录

首先Seata1.2.0版本不在自带sql,且在file.conf文件中没有了vgroup_mapping.fsp_tx_group =“default” 这项配置

数据库SQL

  • seata数据库

    drop table if exists `global_table`;
    create table `global_table` (
      `xid` varchar(128)  not null,
      `transaction_id` bigint,
      `status` tinyint not null,
      `application_id` varchar(32),
      `transaction_service_group` varchar(32),
      `transaction_name` varchar(128),
      `timeout` int,
      `begin_time` bigint,
      `application_data` varchar(2000),
      `gmt_create` datetime,
      `gmt_modified` datetime,
      primary key (`xid`),
      key `idx_gmt_modified_status` (`gmt_modified`, `status`),
      key `idx_transaction_id` (`transaction_id`)
    );
    
    -- the table to store BranchSession data
    drop table if exists `branch_table`;
    create table `branch_table` (
      `branch_id` bigint not null,
      `xid` varchar(128) not null,
      `transaction_id` bigint ,
      `resource_group_id` varchar(32),
      `resource_id` varchar(256) ,
      `lock_key` varchar(128) ,
      `branch_type` varchar(8) ,
      `status` tinyint,
      `client_id` varchar(64),
      `application_data` varchar(2000),
      `gmt_create` datetime,
      `gmt_modified` datetime,
      primary key (`branch_id`),
      key `idx_xid` (`xid`)
    );
    
    -- the table to store lock data
    drop table if exists `lock_table`;
    create table `lock_table` (
      `row_key` varchar(128) not null,
      `xid` varchar(96),
      `transaction_id` long ,
      `branch_id` long,
      `resource_id` varchar(256) ,
      `table_name` varchar(32) ,
      `pk` varchar(36) ,
      `gmt_create` datetime ,
      `gmt_modified` datetime,
      primary key(`row_key`)
    );
    
  • 在其它使用seata的数据库中建undo_log

    drop table `undo_log`;
    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;
    

修改file.conf

  • 将mode改为db
  • 修改数据库为自己的地址和用户名密码
## transaction log store, only used in seata-server
store {
  ## store mode: file、db
  mode = "db"

  ## file store property
  file {
    ## store location dir
    dir = "sessionStore"
    # branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions
    maxBranchSessionSize = 16384
    # globe session size , if exceeded throws exceptions
    maxGlobalSessionSize = 512
    # file buffer size , if exceeded allocate new buffer
    fileWriteBufferCacheSize = 16384
    # when recover batch read size
    sessionReloadReadSize = 100
    # async, sync
    flushDiskMode = async
  }

  ## database store property
  db {
    ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) 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 = "root"
    minConn = 5
    maxConn = 30
    globalTable = "global_table"
    branchTable = "branch_table"
    lockTable = "lock_table"
    queryLimit = 100
    maxWait = 5000
  }
}

修改file.conf.example

  • 更改的内容与file.conf一致
transport {
  # tcp udt unix-domain-socket
  type = "TCP"
  #NIO NATIVE
  server = "NIO"
  #enable heartbeat
  heartbeat = true
  # the client batch send request enable
  enableClientBatchSendRequest = false
  #thread factory for netty
  threadFactory {
    bossThreadPrefix = "NettyBoss"
    workerThreadPrefix = "NettyServerNIOWorker"
    serverExecutorThreadPrefix = "NettyServerBizHandler"
    shareBossWorker = false
    clientSelectorThreadPrefix = "NettyClientSelector"
    clientSelectorThreadSize = 1
    clientWorkerThreadPrefix = "NettyClientWorkerThread"
    # netty boss thread size,will not be used for UDT
    bossThreadSize = 1
    #auto default pin or 8
    workerThreadSize = "default"
  }
  shutdown {
    # when destroy server, wait seconds
    wait = 3
  }
  serialization = "seata"
  compressor = "none"
}

## transaction log store, only used in server side
store {
  ## store mode: file、db
  mode = "db"
  ## file store property
  file {
    ## store location dir
    dir = "sessionStore"
    # branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions
    maxBranchSessionSize = 16384
    # globe session size , if exceeded throws exceptions
    maxGlobalSessionSize = 512
    # file buffer size , if exceeded allocate new buffer
    fileWriteBufferCacheSize = 16384
    # when recover batch read size
    sessionReloadReadSize = 100
    # async, sync
    flushDiskMode = async
  }

  ## database store property
  db {
    ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) 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 = "root"
    minConn = 5
    maxConn = 30
    globalTable = "global_table"
    branchTable = "branch_table"
    lockTable = "lock_table"
    queryLimit = 100
  }
}
## server configuration, only used in server side
server {
  recovery {
    #schedule committing retry period in milliseconds
    committingRetryPeriod = 1000
    #schedule asyn committing retry period in milliseconds
    asynCommittingRetryPeriod = 1000
    #schedule rollbacking retry period in milliseconds
    rollbackingRetryPeriod = 1000
    #schedule timeout retry period in milliseconds
    timeoutRetryPeriod = 1000
  }
  undo {
    logSaveDays = 7
    #schedule delete expired undo_log in milliseconds
    logDeletePeriod = 86400000
  }
  #unit ms,s,m,h,d represents milliseconds, seconds, minutes, hours, days, default permanent
  maxCommitRetryTimeout = "-1"
  maxRollbackRetryTimeout = "-1"
  rollbackRetryTimeoutUnlockEnable = false
}

## metrics configuration, only used in server side
metrics {
  enabled = false
  registryType = "compact"
  # multi exporters use comma divided
  exporterList = "prometheus"
  exporterPrometheusPort = 9898
}

修改registry.conf

  • 将type修改为nacos
  • 修改serverAddr为localhost:8848;默认为localhsot
registry {
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  type = "nacos"

  nacos {
    application = "seata-server"
    serverAddr = "localhost:8848"
    namespace = ""
    cluster = "default"
    username = ""
    password = ""
  }
  eureka {
    serviceUrl = "http://localhost:8761/eureka"
    application = "default"
    weight = "1"
  }
  redis {
    serverAddr = "localhost:6379"
    db = 0
    password = ""
    cluster = "default"
    timeout = 0
  }
  zk {
    cluster = "default"
    serverAddr = "127.0.0.1:2181"
    sessionTimeout = 6000
    connectTimeout = 2000
    username = ""
    password = ""
  }
  consul {
    cluster = "default"
    serverAddr = "127.0.0.1:8500"
  }
  etcd3 {
    cluster = "default"
    serverAddr = "http://localhost:2379"
  }
  sofa {
    serverAddr = "127.0.0.1:9603"
    application = "default"
    region = "DEFAULT_ZONE"
    datacenter = "DefaultDataCenter"
    cluster = "default"
    group = "SEATA_GROUP"
    addressWaitTime = "3000"
  }
  file {
    name = "file.conf"
  }
}

config {
  # file、nacos 、apollo、zk、consul、etcd3
  type = "file"

  nacos {
    serverAddr = "localhost"
    namespace = ""
    group = "SEATA_GROUP"
    username = ""
    password = ""
  }
  consul {
    serverAddr = "127.0.0.1:8500"
  }
  apollo {
    appId = "seata-server"
    apolloMeta = "http://192.168.1.204:8801"
    namespace = "application"
  }
  zk {
    serverAddr = "127.0.0.1:2181"
    sessionTimeout = 6000
    connectTimeout = 2000
    username = ""
    password = ""
  }
  etcd3 {
    serverAddr = "http://localhost:2379"
  }
  file {
    name = "file.conf"
  }
}

启动Seata(之前得先启动Nacos)

  • 直接闪退

    原因:找不到logback.xml配置log文件或目录

    解决: 修改logback.xml文件

    将${user.home}写为固定地址

    修改前:

    <property name="LOG_HOME" value="${user.home}/logs/seata"/>
    

    修改后:

    <property name="LOG_HOME" value="E:\SpringCloud\soft\seata-server-1.2.0\seata\logs\seata"/>
    
  • 报错:java.sql.SQLException: Could not retrieve transation read-only status server

    解决

    一、查看mysql的事务隔离级别

    SHOW VARIABLES LIKE '%iso%';
    

    Seata 1.2.0的配置以及踩坑记录_第1张图片

    二、将隔离级别改为READ-COMMITTED

    SET GLOBAL transaction_isolation='READ-COMMITTED'; 
    
  • 再次启动Seata 报错:

  • ERROR[main]com.alibaba.druid.pool.DruidDataSource.init:878 -init datasource error, url: jdbc:mysql://127.0.0.1:3306/seata java.sql.SQLException: The server time zone value '?й???????' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the 'serverTimezone' configuration property) to use a more specifc time zone value if you want to utilize time zone support.

    解决:修改file.conf 和 file.conf.example 在url后要加上serverTimezone

    • 修改前:

      url = "jdbc:mysql://127.0.0.1:3306/seata"
      
    • 修改后:

      url = "jdbc:mysql://127.0.0.1:3306/seata?serverTimezone=GMT%2B8"
      

    注意:如果使用的是mysql8版本以上,还需将修改driverClassName

    • 修改前:

      driverClassName = "com.mysql.jdbc.Driver"
      
    • 修改后:

      driverClassName = "com.mysql.cj.jdbc.Driver"
      

环境准备完成,开撸

POM(版本信息在父POM已经定义好,都是目前位置最新版本)

<dependencies>
    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-starter-alibaba-seataartifactId>
        <exclusions>
            <exclusion>
                <groupId>io.seatagroupId>
                <artifactId>seata-allartifactId>
            exclusion>
            <exclusion>
                <groupId>io.seatagroupId>
                <artifactId>seata-spring-boot-starterartifactId>
            exclusion>
        exclusions>
    dependency>
    <dependency>
        <groupId>io.seatagroupId>
        <artifactId>seata-spring-boot-starterartifactId>
        <version>1.2.0version>
    dependency>
    <dependency>
        <groupId>com.alibabagroupId>
        <artifactId>druidartifactId>
        <version>1.1.22version>
    dependency>
    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-alibaba-nacos-discoveryartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-openfeignartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-actuatorartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-devtoolsartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-data-jdbcartifactId>
    dependency>
    <dependency>
        <groupId>org.mybatis.spring.bootgroupId>
        <artifactId>mybatis-spring-boot-starterartifactId>
    dependency>
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
    dependency>
    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
    dependency>
dependencies>

YAML

server:
  port: 9001
spring:
  application:
    name: cloud-seata-order
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    username: root
    password: root
    url: jdbc:mysql://127.0.0.1:3306/order?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8
    driver-class-name: com.mysql.cj.jdbc.Driver
management:
  endpoints:
    web:
      exposure:
        include: '*'
mybatis:
  mapper-locations: classpath:mapper/*.xml
seata:
  application-id: ${spring.application.name}
  tx-service-group: default
  service:
    vgroupMapping:
      default: default
    grouplist:
      default: 127.0.0.1:8091
ribbon:
  ReadTimeout: 6000
  ConnectTimout: 6000

主启动

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
public class OrderSeataMain9001 {

    public static void main(String[] args) {
        SpringApplication.run(OrderSeataMain9001.class,args);
    }

}

目录结构

Seata 1.2.0的配置以及踩坑记录_第2张图片

其它的微服务模块和代码就不再赘述,order --> storage --> account {订单 库存 账户(余额)}

启动Order应用:

报错:no available service ‘null’ found, please make sure registry config correct

将依赖的seata-spring-boot-starter排除(前面的POM已经是修改过后的)

再导入seata-spring-boot-starter

<dependency>
    <groupId>com.alibaba.cloudgroupId>
    <artifactId>spring-cloud-starter-alibaba-seataartifactId>
    <exclusions>
        <exclusion>
            <groupId>io.seatagroupId>
            <artifactId>seata-allartifactId>
        exclusion>
        <exclusion>
            <groupId>io.seatagroupId>
            <artifactId>seata-spring-boot-starterartifactId>
        exclusion>
    exclusions>
dependency>
<dependency>
    <groupId>io.seatagroupId>
    <artifactId>seata-spring-boot-starterartifactId>
    <version>1.2.0version>
dependency>

YAML为(前面的YAML已经是修改后的,这里只是阐述问题)

在新版中vgroup-mappging改为了vgroupMapping驼峰命名

且此处Key对应 tx-service-group 的 Value, 此处 value 默认 default

如果不指定grouplist

报如下错java.lang.IllegalArgumentException: defalut.grouplist is required

seata:
  application-id: ${spring.application.name}
  tx-service-group: default
  service:
    vgroupMapping:
      default: default
    grouplist:
      default: 127.0.0.1:8091

第二个问题:

Cause: java.sql.SQLException: com.alibaba.fescar.core.exception.TransactionException: RPC Timeout

问题描述:之前我是连的远程阿里云服务器的mysql,在调用的出现RPC Timeout异常

@Service
public class OrderServiceImpl implements OrderService {

    @Resource
    private OrderDao orderDao;
    @Resource
    private AccountService accountService;
    @Resource
    private StorageService storageService;

    @Override
    @GlobalTransactional(name = "default",rollbackFor = Exception.class)
    public void create(@RequestParam Order order) {
        orderDao.create(order);
        accountService.accountDecease(order.getUserId(),order.getMoney()*order.getCount());
        int i = 10/0;
        storageService.storageDecease(order.getCommodityCode(),order.getCount());
    }

}

这里写了int i = 10 / 0;的一个异常调用时出现RPC Timeout异常,而去掉int i = 10/0后 调用正常;

这里的解决方法就是YAML为ribbon设置超时时间后访问成功by /zero,且事务回滚正常:

ribbon:
  ReadTimeout: 6000
  ConnectTimout: 6000

而这个问题比较奇怪的是,我把mysql切换到本地的mysql后,就没有RPC Timeout异常;

且我的阿里云服务器访问正常,不存在网络差的情况

最后附上使用AT模式的注意事项(来源:官网)

使用 AT 模式需要的注意事项有哪些 ?

1.必须使用代理数据源,有 3 种形式可以代理数据源:

  • 依赖 seata-spring-boot-starter 时,自动代理数据源,无需额外处理。

  • 依赖 seata-all 时,使用 @EnableAutoDataSourceProxy (since 1.1.0) 注解,注解参数可选择 jdk 代理或者 cglib 代理。

  • 依赖 seata-all 时,也可以手动使用 DatasourceProxy 来包装 DataSource。

2.配置 GlobalTransactionScanner,使用 seata-all 时需要手动配置,使用 seata-spring-boot-starter 时无需额外处理。

3.业务表中必须包含单列主键,若存在复合主键,请参考问题 13 。

4.每个业务库中必须包含 undo_log 表,若与分库分表组件联用,分库不分表。

5.跨微服务链路的事务需要对相应 RPC 框架支持,目前 seata-all 中已经支持:Apache Dubbo、Alibaba Dubbo、sofa-RPC、Motan、gRpc、httpClient,对于 Spring Cloud 的支持,请大家引用 spring-cloud-alibaba-seata。其他自研框架、异步模型、消息消费事务模型请结合 API 自行支持。

6.目前AT模式支持的数据库有:MySQL、Oracle、PostgreSQL和 TiDB。

7.使用注解开启分布式事务时,若默认服务 provider 端加入 consumer 端的事务,provider 可不标注注解。但是,provider 同样需要相应的依赖和配置,仅可省略注解。

8.使用注解开启分布式事务时,若要求事务回滚,必须将异常抛出到事务的发起方,被事务发起方的 @GlobalTransactional 注解感知到。provide 直接抛出异常 或 定义错误码由 consumer 判断再抛出异常。

你可能感兴趣的:(SpringCloud)