以Nacos作为seata配置中心快速集成

1 以Nacos作为seata配置中心快速集成

首先需要搭建好Nacos服务,本实例使用AT模式,相关核心依赖版本号如下:

  • seata 1.7.0
  • seata-spring-boot-starter 1.7.0
  • spring-cloud-starter-alibaba-nacos-discovery 2022.0.0.0
  • springboot 3.0.2
  • spring-cloud-starter 2022.0.0

1.1 创建Seata Server Database (TC)

创建seata数据库,并执行以下配置脚本:

-- -------------------------------- The script used when storeMode is 'db' --------------------------------
-- the table to store GlobalSession data
CREATE TABLE IF NOT EXISTS `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_status_gmt_modified` (`status` , `gmt_modified`),
    KEY `idx_transaction_id` (`transaction_id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4;

-- the table to store BranchSession data
CREATE TABLE IF NOT EXISTS `branch_table`
(
    `branch_id`         BIGINT       NOT NULL,
    `xid`               VARCHAR(128) NOT NULL,
    `transaction_id`    BIGINT,
    `resource_group_id` VARCHAR(32),
    `resource_id`       VARCHAR(256),
    `branch_type`       VARCHAR(8),
    `status`            TINYINT,
    `client_id`         VARCHAR(64),
    `application_data`  VARCHAR(2000),
    `gmt_create`        DATETIME(6),
    `gmt_modified`      DATETIME(6),
    PRIMARY KEY (`branch_id`),
    KEY `idx_xid` (`xid`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4;

-- the table to store lock data
CREATE TABLE IF NOT EXISTS `lock_table`
(
    `row_key`        VARCHAR(128) NOT NULL,
    `xid`            VARCHAR(128),
    `transaction_id` BIGINT,
    `branch_id`      BIGINT       NOT NULL,
    `resource_id`    VARCHAR(256),
    `table_name`     VARCHAR(32),
    `pk`             VARCHAR(36),
    `status`         TINYINT      NOT NULL DEFAULT '0' COMMENT '0:locked ,1:rollbacking',
    `gmt_create`     DATETIME,
    `gmt_modified`   DATETIME,
    PRIMARY KEY (`row_key`),
    KEY `idx_status` (`status`),
    KEY `idx_branch_id` (`branch_id`),
    KEY `idx_xid_and_branch_id` (`xid` , `branch_id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4;

CREATE TABLE IF NOT EXISTS `distributed_lock`
(
    `lock_key`       CHAR(20) NOT NULL,
    `lock_value`     VARCHAR(20) NOT NULL,
    `expire`         BIGINT,
    primary key (`lock_key`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4;

INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('AsyncCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryRollbacking', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('TxTimeoutCheck', ' ', 0);

1.2 下载 Seata

点击下载 Seata 1.7.0 版本

1.3 同步配置到Nacos

新建 seata-config 命名空间,然后把参数同步到配置中心,具体操作如下:

  • 解压下载的 seata-server-1.7.0.zip,然后进入config-center目录,把config.text文件往前面移动一个目录到script目录里面,并修改config.text,数据库连接别忘记修改,大体内容如下:

    #For details about configuration items, see https://seata.io/zh-cn/docs/user/configurations.html
    #Transport configuration, for client and server
    transport.type=TCP
    transport.server=NIO
    transport.heartbeat=true
    transport.enableTmClientBatchSendRequest=false
    transport.enableRmClientBatchSendRequest=true
    transport.enableTcServerBatchSendResponse=false
    transport.rpcRmRequestTimeout=30000
    transport.rpcTmRequestTimeout=30000
    transport.rpcTcRequestTimeout=30000
    transport.threadFactory.bossThreadPrefix=NettyBoss
    transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker
    transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler
    transport.threadFactory.shareBossWorker=false
    transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector
    transport.threadFactory.clientSelectorThreadSize=1
    transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread
    transport.threadFactory.bossThreadSize=1
    transport.threadFactory.workerThreadSize=default
    transport.shutdown.wait=3
    transport.serialization=seata
    transport.compressor=none
    
    #Transaction routing rules configuration, only for the client
    service.vgroupMapping.default_tx_group=default
    #If you use a registry, you can ignore it
    service.default.grouplist=127.0.0.1:8091
    service.enableDegrade=false
    service.disableGlobalTransaction=false
    
    #Transaction rule configuration, only for the client
    client.rm.asyncCommitBufferLimit=10000
    client.rm.lock.retryInterval=10
    client.rm.lock.retryTimes=30
    client.rm.lock.retryPolicyBranchRollbackOnConflict=true
    client.rm.reportRetryCount=5
    client.rm.tableMetaCheckEnable=true
    client.rm.tableMetaCheckerInterval=60000
    client.rm.sqlParserType=druid
    client.rm.reportSuccessEnable=false
    client.rm.sagaBranchRegisterEnable=false
    client.rm.sagaJsonParser=fastjson
    client.rm.tccActionInterceptorOrder=-2147482648
    client.tm.commitRetryCount=5
    client.tm.rollbackRetryCount=5
    client.tm.defaultGlobalTransactionTimeout=60000
    client.tm.degradeCheck=false
    client.tm.degradeCheckAllowTimes=10
    client.tm.degradeCheckPeriod=2000
    client.tm.interceptorOrder=-2147482648
    client.undo.dataValidation=true
    client.undo.logSerialization=jackson
    client.undo.onlyCareUpdateColumns=true
    server.undo.logSaveDays=7
    server.undo.logDeletePeriod=86400000
    client.undo.logTable=undo_log
    client.undo.compress.enable=true
    client.undo.compress.type=zip
    client.undo.compress.threshold=64k
    #For TCC transaction mode
    tcc.fence.logTableName=tcc_fence_log
    tcc.fence.cleanPeriod=1h
    
    #Log rule configuration, for client and server
    log.exceptionRate=100
    
    #Transaction storage configuration, only for the server. The file, db, and redis configuration values are optional.
    store.mode=db
    store.lock.mode=db
    store.session.mode=db
    #Used for password encryption
    store.publicKey=
    
    
    #These configurations are required if the `store mode` is `db`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `db`, you can remove the configuration block.
    store.db.datasource=druid
    store.db.dbType=mysql
    store.db.driverClassName=com.mysql.jdbc.Driver
    store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&rewriteBatchedStatements=true
    store.db.user=username
    store.db.password=password
    store.db.minConn=5
    store.db.maxConn=30
    store.db.globalTable=global_table
    store.db.branchTable=branch_table
    store.db.distributedLockTable=distributed_lock
    store.db.queryLimit=100
    store.db.lockTable=lock_table
    store.db.maxWait=5000
    
    
    #Transaction rule configuration, only for the server
    server.recovery.committingRetryPeriod=1000
    server.recovery.asynCommittingRetryPeriod=1000
    server.recovery.rollbackingRetryPeriod=1000
    server.recovery.timeoutRetryPeriod=1000
    server.maxCommitRetryTimeout=-1
    server.maxRollbackRetryTimeout=-1
    server.rollbackRetryTimeoutUnlockEnable=false
    server.distributedLockExpireTime=10000
    server.xaerNotaRetryTimeout=60000
    server.session.branchAsyncQueueSize=5000
    server.session.enableBranchAsyncRemove=false
    server.enableParallelRequestHandle=false
    
    #Metrics configuration, only for the server
    metrics.enabled=false
    metrics.registryType=compact
    metrics.exporterList=prometheus
    metrics.exporterPrometheusPort=9898
    
    
  • 然后执行以下命令命令:
    sh yourSeataPath/script/config-center/nacos/nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 5a3c7d6c-f497-4d68-a71a-2e5e3340b3ca -u username -w password

  • 脚本示例:
    sh /Users/xxx/Downloads/seata/script/config-center/nacos/nacos-config.sh -h local-nacos.xxx.com -p 8848 -g SEATA_GROUP -t seata-config -u admin -w xxx

参数说明:

  • -h: host,默认值 localhost

  • -p: port,默认值 8848

  • -g: 配置分组,默认值为 ‘SEATA_GROUP’

  • -t: 租户信息,对应 Nacos 的命名空间 ID 字段, 默认值为空 ‘’

注:该步骤,一个nacos地址,仅需要配置一次即可

1.4 配置 Seata-server

修改 seata-server-1.7.0\conf\application.yml 配置文件中的配置项如下:

server:
  port: 6688

spring:
  application:
    name: seata-server

logging:
  config: classpath:logback-spring.xml
  file:
    path: ${user.home}/logs/seata
#  extend:
#    logstash-appender:
#      destination: 127.0.0.1:4560
#    kafka-appender:
#      bootstrap-servers: 127.0.0.1:9092
#      topic: logback_to_logstash

console:
  user:
    username: seata
    password: seata@666888.


seata:
  # nacos配置
  config:
    type: nacos
    nacos:
      server-addr: xxx
      namespace: seata-config
      group: SEATA_GROUP
      username: xxx
      password: xxx
      context-path:
      data-id: seataServer.properties
  registry:
    # nacos配置
    type: nacos
    nacos:
      application: seata-server
      server-addr: xxx
      namespace: seata-config
      group: SEATA_GROUP
      # tc集群名称
      cluster: default
      username: xxx
      password: xxx
      server:
        #If not configured, the default is '${server.port} + 1000'
        service-port: 7688
  security:
    secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017666888
    tokenValidityInMilliseconds: 1800000
    ignore:
      urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login

1.5 启动 Seata-server

Enter the start directory: cd /smilehappiness-framework-base/smilehappiness-seata/src/main/java/start

Execution: ./seata-server.sh

Note: If you do not have permission, you can add executable permission (chmod+x./seata server. sh)

1.6 Seata 控制台访问

Seata 1.5.1 开始支持控制台 本地访问控制台地址:http://127.0.0.1:6688,通过 Seata
内置的控制台可以观察正在执行的事务信息和全局锁信息,事务执行结束即删除相关信息。

2 使用Seata 示例

2.1 添加依赖

 <!--seata client config-->
  <dependency>
      <groupId>io.seata</groupId>
      <artifactId>seata-spring-boot-starter</artifactId>
      <exclusions>
          <exclusion>
              <groupId>com.alibaba</groupId>
              <artifactId>druid</artifactId>
          </exclusion>
      </exclusions>
  </dependency>
  <!--SpringCloud users can introduce spring cloud starter libaba seata, which XID has already implemented cross service delivery internally-->
  <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
      <exclusions>
          <exclusion>
              <groupId>io.seata</groupId>
              <artifactId>seata-spring-boot-starter</artifactId>
          </exclusion>
      </exclusions>
  </dependency>
  <dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>dynamic-datasource-spring-boot3-starter</artifactId>
  </dependency>

2.2 配置nacos,在seata-config命名空间里面,新增分组为 SEATA_GROUP, dataId 如下:

service.vgroupMapping.seata-example-tx-group=default

2.3 创建seata client database

Seata AT模式需要使用到undo_log表,所以在需要使用seata的相关的服务里面,都需要添加以下表:

CREATE TABLE `undo_log`
(
    `branch_id`     bigint(20) NOT NULL COMMENT 'branch transaction id',
    `xid`           varchar(128) NOT NULL COMMENT 'global transaction id',
    `context`       varchar(128) NOT NULL COMMENT 'undo_log context,such as serialization',
    `rollback_info` longblob     NOT NULL COMMENT 'rollback info',
    `log_status`    int(11) NOT NULL COMMENT '0:normal status,1:defense status',
    `log_created`   datetime(6) NOT NULL COMMENT 'create datetime',
    `log_modified`  datetime(6) NOT NULL COMMENT 'modify datetime',
    UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COMMENT ='AT transaction mode undo table';

2.4 创建测试用例中业务所需要的数据库表

CREATE DATABASE IF NOT EXISTS seata_order;
CREATE DATABASE IF NOT EXISTS seata_account;
CREATE DATABASE IF NOT EXISTS seata_product;
       

DROP TABLE IF EXISTS seata_account.account;
CREATE TABLE seata_account.account
(
  id               INT(11) NOT NULL AUTO_INCREMENT,
  balance          DOUBLE   DEFAULT NULL,
  last_update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (id)
) AUTO_INCREMENT = 1
  DEFAULT CHARSET = utf8;


insert into seata_account.account (id, balance)
VALUES (1, 50);


DROP TABLE IF EXISTS seata_order.p_order;
CREATE TABLE seata_order.p_order
(
  id               INT(11) NOT NULL AUTO_INCREMENT,
  user_id          INT(11) DEFAULT NULL,
  product_id       INT(11) DEFAULT NULL,
  amount           INT(11) DEFAULT NULL,
  total_price      DOUBLE       DEFAULT NULL,
  status           VARCHAR(100) DEFAULT NULL,
  add_time         DATETIME     DEFAULT CURRENT_TIMESTAMP,
  last_update_time DATETIME     DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (id)
) AUTO_INCREMENT = 1
  DEFAULT CHARSET = utf8;


DROP TABLE IF EXISTS seata_product.product;
CREATE TABLE seata_product.product
(
  id               INT(11) NOT NULL AUTO_INCREMENT,
  price            DOUBLE   DEFAULT NULL,
  stock            INT(11) DEFAULT NULL,
  last_update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (id)
) AUTO_INCREMENT = 1
  DEFAULT CHARSET = utf8;

insert into seata_product.product (id, price, stock)
VALUES (1, 10, 20);

2.5 配置seata client nacos配置

在需要集成seata的项目中,需要在application.yml中配置seata相关配置:


seata:
  enabled: true
  application-id: ${spring.application.name}
  tx-service-group: seata-example-tx-group
  #it must be false, otherwise the component will automatically use a DataSourceProxy to wrap the DataSource when seata is enabled internally
  enable-auto-data-source-proxy: false
  service:
    # https://seata.apache.org/zh-cn/docs/user/configurations/
    # 更多 Seata-server以Nacos作为配置中心的配置请参考:https://seata.io/zh-cn/docs/ops/deploy-by-docker-compose/#nacos-db
    vgroupMapping:
      # Transaction routing rules configuration, only for the client,The key corresponds to the value of tx service group above
      # Specify the transaction grouping to cluster mapping relationship (the cluster name on the right side of the equal sign needs to be consistent with the cluster registered by Seata Server)
      seata-example-tx-group: default
  config:
    type: nacos
    nacos:
      serverAddr: xxx
      namespace: seata-config
      group: SEATA_GROUP
      dataId: seataServer.properties
      username: admin
      password: xxx
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: xxx
      namespace: seata-config
      group: SEATA_GROUP
      username: admin
      password: xxx

2.6 添加事务注解

重点来了,第一个开启事务的需要添加seata全局事务注解 @GlobalTransactional,以及@Transactional,被调用方需要添加事务注解 @Transactional(propagation = Propagation.REQUIRES_NEW)
如smilehappiness-seata-example示例所示

启动客户端服务,项目中出现以下信息,说明client服务启动完成:

register TM success. client version:1.7.0, server version:1.7.0,channel:[id: 0x58c999ba, L:/192.168.80.32:64869 - R:/192.168.80.32:7688]
register RM success. client version:1.7.0, server version:1.7.0,channel:[id: 0xf4b71250, L:/192.168.80.32:65047 - R:/192.168.80.32:7688]

2.7 示例说明

模拟用户下单,扣商品库存,扣用户余额,初步可分为订单服务+商品服务+用户服务。项目中使用了多数据源模拟,实际业务中,多半是微服务实现的,这里测试效果是一样的。

  • 模拟正常下单

    http://localhost:6687/order/placeOrder
    
    {
        "userId": 1,
        "productId": 1,
        "num": 1
    }
    
  • 模拟库存不足事务回滚

    http://localhost:6687/order/placeOrderProductFail
    
    {
        "userId": 1,
        "productId": 1,
        "num": 22
    }
    
  • 模拟账户余额不足事务回滚

    http://localhost:6687/order/placeOrderAccountFail
    
    {
        "userId": 1,
        "productId": 1,
        "num": 6
    }
    

写博客是为了记住自己容易忘记的东西,另外也是对自己工作的总结,希望尽自己的努力,做到更好,大家一起努力进步!

如果有什么问题,欢迎大家一起探讨,代码如有问题,欢迎各位大神指正!

给自己的梦想添加一双翅膀,让它可以在天空中自由自在的飞翔!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值