springcloud+eureka+seata集成

主要示例为官网的例子,把官网关于springcloud集成eureka的模块独立出来了,排除一些其他示例项目的干扰,我们先看seata的概念:

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。 —— 引用自 SEATA 官方文档

接下来来看集成seata要做些什么工作:
1、引入seata相关包。

        <dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-all</artifactId>
            <version>1.1.0</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-seata</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>

2、配置yml,registry.conf 及 file.conf信息,其中registry.conf 及 file.conf对于后续要运行的seata server的配置也是一样的,也就是说seata server和被管理的事务项目工程都使用相同的配置,它们三个放在同一位置下:
在这里插入图片描述
具体配置信息如下所示:
yml:

logging.level.io.seata: debug
spring.cloud.alibaba.seata.tx-service-group: my_test_tx_group

registry.conf,特别注意registry.eureka.application的值要与file.conf的server.vgroupMapping.my_test_tx_group保持一致

registry {
  # 注册方式,如file 、nacos 、eureka、redis、zk、consul、etcd3、sofa,我们这里选择eureka
  type = "eureka"

  nacos {
    serverAddr = "localhost"
    namespace = ""
    cluster = "default"
  }
  eureka {
    # 要注册的eureka地址,这里为本地
    serviceUrl = "http://localhost:8761/eureka"
    # 要连接的seata server的服务名
    application = "default"
    weight = "1"
  }
  redis {
    serverAddr = "localhost:6379"
    db = "0"
    password = ""
    cluster = "default"
    timeout = "0"
  }
  zk {
    cluster = "default"
    serverAddr = "127.0.0.1:2181"
    session.timeout = 6000
    connect.timeout = 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、springCloudConfig,这里我们选择本地文件的方式file,就会读取file.conf文件。
  type = "file"

  nacos {
    serverAddr = "localhost"
    namespace = ""
    group = "SEATA_GROUP"
  }
  consul {
    serverAddr = "127.0.0.1:8500"
  }
  apollo {
    app.id = "seata-server"
    apollo.meta = "http://192.168.1.204:8801"
    namespace = "application"
  }
  zk {
    serverAddr = "127.0.0.1:2181"
    session.timeout = 6000
    connect.timeout = 2000
    username = ""
    password = ""
  }
  etcd3 {
    serverAddr = "http://localhost:2379"
  }
  file {
    name = "file.conf"
  }
}

file.conf,特别注意server下的vgroupMapping.xxx配置后面的xxx要与yml配置中的spring.cloud.alibaba.seata.tx-service-group一致,配置的值要与regiester.conf里的registry节点下的eureka下的application保持一致:

transport {
  # tcp udt unix-domain-socket
  type = "TCP"
  #NIO NATIVE
  server = "NIO"
  #enable heartbeat
  heartbeat = true
  # the client batch send request enable
  enableClientBatchSendRequest = true
  #thread factory for netty
  threadFactory {
    bossThreadPrefix = "NettyBoss"
    workerThreadPrefix = "NettyServerNIOWorker"
    serverExecutorThread-prefix = "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"
}
service {
  #此处的vgroupMapping.xxx配置后面的xxx要与yml配置中的spring.cloud.alibaba.seata.tx-service-group一致,配置的值要与regiester.conf里的registry节点下的eureka下的application保持一致。
  vgroupMapping.my_test_tx_group = "default"
  #当注册类型为file文件时配置,不要输入多个地址,此处的地址为seata server的监听地址(seata server也有相同配置)
  default.grouplist = "127.0.0.1:8091"
  #degrade, current not support
  enableDegrade = false
  #disable seata
  disableGlobalTransaction = false
}

client {
  rm {
    asyncCommitBufferLimit = 10000
    lock {
      retryInterval = 10
      retryTimes = 30
      retryPolicyBranchRollbackOnConflict = true
    }
    reportRetryCount = 5
    tableMetaCheckEnable = false
    reportSuccessEnable = false
  }
  tm {
    commitRetryCount = 5
    rollbackRetryCount = 5
  }
  undo {
    dataValidation = true
    logSerialization = "jackson"
    logTable = "undo_log"
  }
  log {
    exceptionRate = 100
  }
}

3、在各服务数据库中增加 undo_log 表
建表语句可从 SEATA 发布版中获得,如
https://github.com/seata/seata/blob/v1.0.0/script/client/at/db/mysql.sql
我这版用的是:


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,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

4、添加全局事务注解在 controller 或者 service 上,标记 @GlobalTransactional 注解。

接下来我们使用springcloud-eureka-seata例子来看一下实际效果,具体代码最后会贴出来:
1、首先先执行一下业务脚本sql:
在这里插入图片描述

CREATE TABLE `account_tbl` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(255) DEFAULT NULL,
  `money` int(11) DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

CREATE TABLE `storage_tbl` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `commodity_code` varchar(255) DEFAULT NULL,
  `count` int(11) DEFAULT '0',
  PRIMARY KEY (`id`),
  UNIQUE KEY `commodity_code` (`commodity_code`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

CREATE TABLE `order_tbl` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(255) DEFAULT NULL,
  `commodity_code` varchar(255) DEFAULT NULL,
  `count` int(11) DEFAULT '0',
  `money` int(11) DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

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,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

2、启动eureka
3、下载seata server,下载地址下载后修改seata\conf下的file.conf、registry.conf配置为上面讲到的配置,然后进入seata\bin,双击seata-server.bat启动server服务:在这里插入图片描述
看到这信息则表示启动无报错,再看eureka是否已注册成功:
在这里插入图片描述

注册成功!

4、再依次启动工程中的剩余四个模块,order、account、storage、business,启动后如下图所示:
在这里插入图片描述
准备工作已经就绪,接下来对例子说明一下,此例子主要模拟下单减库存的操作,拥有账户表,订单表,库存表三张表,并在business模块的controller里提供了两个接口,
一个为正常下单接口,每次扣取30库存:在这里插入图片描述
另一个为模拟全局事务回滚,一次性扣取9999库存:在这里插入图片描述
而purchase方法的下单逻辑为
1、先减库存
2、再创建订单信息(先下单,再扣用户账户钱)
3、校验用户账户是否没钱,库存是否不够,一旦两个条件任意一个满足,则抛出异常让@GlobalTransactional注解修饰的purchase方法感知,从而让全局事务进行回滚。相关代码如下所示:
在这里插入图片描述

在这里插入图片描述
下面测试一下:
先调用正常扣取接口:http://localhost:8084/purchase/commit
得到结果:

用户账户表
扣除前:在这里插入图片描述
扣扣除后在这里插入图片描述
订单表
扣除前:无
扣除后在这里插入图片描述
库存表
扣除前:在这里插入图片描述
扣除后在这里插入图片描述
再调用模拟全局事务回滚的接口:http://localhost:8084/purchase/rollback
,发现结果还是跟调用前一样,表示事务回滚成功!

具体代码例子:github地址

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值