Nacos+Seata+Feign分布式事务

本篇文章是从Seata官方样例改造而来的分布式事务,Nacos为服务的注册中心及配置中心,这里我采用的组件的版本为:Nacos 2.1.0、Seata 1.5.2

Seata的官方样例库为:https://github.com/seata/seata-samples

样例的结构如下:

启动seata服务让seata服务注册到Nacos上。
Nacos+Seata+Feign分布式事务_第1张图片

1.POM文件内容
<properties>
    <maven.compiler.source>11maven.compiler.source>
    <maven.compiler.target>11maven.compiler.target>
    <spring-cloud.version>2021.0.4spring-cloud.version>
    <cloud.alibaba.version>2021.0.4.0cloud.alibaba.version>
    <nacos.version>2.1.0nacos.version>
    <cloud.version>3.1.2cloud.version>
    <druid.version>1.2.11druid.version>
    <dynamic-datasource.version>3.5.1dynamic-datasource.version>
    <mybatis-plus.version>3.5.2mybatis-plus.version>
properties>
<dependencyManagement>
   <dependencies>
      <dependency>
          <groupId>org.springframework.cloudgroupId>
          <artifactId>spring-cloud-dependenciesartifactId>
          <version>${spring-cloud.version}version>
          <type>pomtype>
          <scope>importscope>
      dependency>
      <dependency>
          <groupId>com.alibaba.cloudgroupId>
          <artifactId>spring-cloud-alibaba-dependenciesartifactId>
          <version>${cloud.alibaba.version}version>
          <type>pomtype>
          <scope>importscope>
      dependency>
      <dependency>
          <groupId>com.alibaba.nacosgroupId>
          <artifactId>nacos-clientartifactId>
          <version>2.1.1version>
      dependency>
  dependencies>
dependencyManagement>

<dependencies>
  <dependency>
      <groupId>org.springframework.cloudgroupId>
      <artifactId>spring-cloud-starter-bootstrapartifactId>
      <version>3.1.4version>
  dependency>
  <dependency>
      <groupId>com.baomidougroupId>
      <artifactId>dynamic-datasource-spring-boot-starterartifactId>
      <version>${dynamic-datasource.version}version>
  dependency>
  <dependency>
      <groupId>com.baomidougroupId>
      <artifactId>mybatis-plus-boot-starterartifactId>
      <version>${mybatis-plus.version}version>
  dependency>
  <dependency>
      <groupId>com.alibabagroupId>
      <artifactId>druid-spring-boot-starterartifactId>
      <version>${druid.version}version>
  dependency>
  <dependency>
      <groupId>org.springframework.bootgroupId>
      <artifactId>spring-boot-starter-webartifactId>
  dependency>
  <dependency>
      <groupId>com.alibaba.cloudgroupId>
      <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
  dependency>
  <dependency>
      <groupId>com.alibaba.cloudgroupId>
      <artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
  dependency>
  <dependency>
      <groupId>com.alibaba.cloudgroupId>
      <artifactId>spring-cloud-starter-alibaba-seataartifactId>
      <exclusions>
          <exclusion>
              <groupId>io.seatagroupId>
              <artifactId>seata-spring-boot-starterartifactId>
          exclusion>
      exclusions>
  dependency>
  <dependency>
      <groupId>io.seatagroupId>
      <artifactId>seata-spring-boot-starterartifactId>
      <version>1.4.2version>
  dependency>
  <dependency>
      <groupId>mysqlgroupId>
      <artifactId>mysql-connector-javaartifactId>
      <scope>runtimescope>
      <version>8.0.16version>
  dependency>
  <dependency>
      <groupId>org.projectlombokgroupId>
      <artifactId>lombokartifactId>
      <optional>trueoptional>
      <version>1.18.24version>
  dependency>
  <dependency>
      <groupId>org.springframework.cloudgroupId>
      <artifactId>spring-cloud-starter-loadbalancerartifactId>
      <version>${cloud.version}version>
  dependency>
  <dependency>
      <groupId>org.springframework.cloudgroupId>
      <artifactId>spring-cloud-openfeign-coreartifactId>
      <version>${cloud.version}version>
  dependency>
  <dependency>
      <groupId>org.springframework.cloudgroupId>
      <artifactId>spring-cloud-starter-openfeignartifactId>
      <version>${cloud.version}version>
  dependency>
dependencies>
2.项目工程

模块的总体结构如下,这里只列出account-server的部分内容,具体内容可访问官方仓库。
Nacos+Seata+Feign分布式事务_第2张图片

account库的数据库表

CREATE TABLE `account`
(
    `id`      bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
    `user_id` bigint(11) DEFAULT NULL COMMENT '用户id',
    `total`   decimal(10, 0) DEFAULT NULL COMMENT '总额度',
    `used`    decimal(10, 0) DEFAULT NULL COMMENT '已用余额',
    `residue` decimal(10, 0) DEFAULT '0' COMMENT '剩余可用额度',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

INSERT INTO `account` (`id`, `user_id`, `total`, `used`, `residue`)
VALUES ('1', '1', '100', '0', '100');

每个库还得加上seata的undo_log数据表。undo-log 是 AT 模式中的核心部分 , 他是在 RM 部分完成的 , 在每一个数据库单元处理时均会生成一条 undoLog 数据。

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=17 DEFAULT CHARSET=utf8;

bootstrap.yml文件内容
具体的配置信息配置在Nacos上,所以要在bootstrap.yml上配置上Nacos的信息。

server:
  port: 8081
nacos:
  service:
    address: 127.0.0.1:8848

# spring配置
spring:
  application:
    name: feign-account-server
  profiles:
    active: dev
  cloud:
    nacos:
      discovery:
        server-addr: ${nacos.service.address}
        namespace: wey
      config:
        #配置中心地址
        server-addr: ${nacos.service.address}
        namespace: wey
        # 配置文件格式
        file-extension: yml
        # 共享配置
        shared-configs:
          - feigin-seata-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}

Nacos上的配置
Nacos+Seata+Feign分布式事务_第3张图片
Nacos上的feign-account-server-dev.yml 文件的配置内容,order模块跟storage模块的内容类似。

spring: 
  datasource:
    druid:
      stat-view-servlet:
        enabled: true
        loginUsername: admin
        loginPassword: 123456
    dynamic:
      druid:
        initial-size: 5
        min-idle: 5
        maxActive: 20
        maxWait: 60000
        timeBetweenEvictionRunsMillis: 60000
        minEvictableIdleTimeMillis: 300000
        validationQuery: SELECT 1
        testWhileIdle: true
        testOnBorrow: false
        testOnReturn: false
        poolPreparedStatements: true
        maxPoolPreparedStatementPerConnectionSize: 20
        filters: stat,slf4j
        connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
      primary: master
      #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候会抛出异常,不启动则使用默认数据源.
      strict: false 
      #seata1.0之后支持自动代理 这里直接配置true
      seata: true 
      #seata模式使用的at
      seata-mode: at 
      datasource:
        # 主库数据源
        master:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/feign-seata-account?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai
          username: root
          password: root
seata:
  # 默认关闭,如需启用spring.datasource.dynami.seata需要同时开启
  enabled: true
  # Seata 应用编号,默认为 ${spring.application.name}
  application-id: ${spring.application.name}
  # Seata 事务组编号,用于 TC 集群名,这个自定义命名很重要,server,client都要保持一致
  tx-service-group: my_test_tx_group
  # 关闭自动代理
  enable-auto-data-source-proxy: false
  # 服务配置项
  service:
    # 虚拟组和分组的映射
    vgroup-mapping:
      coolpad-apioutweb-application-group: default
  config:
    type: nacos
    nacos:
      serverAddr: 127.0.0.1:8848
      group: SEATA_GROUP
      namespace: seata
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      namespace: seata

feigin-seata-dev.yml 配置的是共享的配置信息,可以将公共的配置放在这个文件内。

# mybatis-plus配置
mybatis-plus:
  checkConfigLocation: false
  configuration:
    aggressiveLazyLoading: true
    autoMappingBehavior: PARTIAL
    autoMappingUnknownColumnBehavior: NONE
    defaultEnumTypeHandler: org.apache.ibatis.type.EnumTypeHandler
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    mapUnderscoreToCamelCase: true
  global-config:
    banner: true
    # 搜索指定包别名
  typeAliasesPackage: com.wey.**.entity
  # 配置mapper的扫描,找到所有的mapper.xml映射文件
  mapperLocations: classpath:mapper/**/*.xml

feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 10000


最后集成调用成环,通过@GlobalTransaction注解开户分布式事务。

   @Override
    @GlobalTransactional(name = "fsp-create-order",rollbackFor = Exception.class) //此注解开启全局事务
    public void create(Order order) {
        //本地方法 创建订单
        orderDao.create(order);
        //远程方法 扣减库存
        stockApi.decrease(order.getProductId(),order.getCount());
        //远程方法 扣减账户余额  可在accountServiceImpl中模拟异常
        accountApi.decrease(order.getUserId(),order.getMoney());
    }

在最初的order会创建一个订单,然后扣减库存,然后扣减账户,账户扣减完,会回头修改订单的金额和状态,这样调用就成环了。

调用成功后seata控制台会打印提交日志。
Nacos+Seata+Feign分布式事务_第4张图片

你可能感兴趣的:(Spring,Cloud,Spring,Cloud,Alibaba,分布式,spring,boot,java)