Seata使用

本文以seata-server-1.5.2,以配置中心、注册中心使用Nacos,store.mode=db(mysql)为例进行操作。

一、Seata Server端

1、下载seata server

链接: http://seata.io/zh-cn/blog/download.html下载压缩包,解压至非中文目录。

下载版本参考之前我们提到的:SpringBoot、SpringCloud、Spring Cloud Alibaba版本对照表选择适合自己环境的版本。

本文版本环境:

复制代码
Spring Cloud Alibaba 2021.0.4.0
Spring Boot 2.6.11
Nacos 2.2.1
Seata1.5.2

解压后可以发现原来的conf/registry.conf配置文件没有了,可直接修改application.yml进行配置。

2、客户端配置-application.yml

配置application.yml(低版本的是file.conf+registry.conf文件),主要配置config:配置中心部分及registry:注册中心部分。

复制代码
server:
  port: 7091

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控制台,
# 可通过访问http://localhost:7091进行登录,账号如下seata/seata
console:
  user:
    username: seata
    password: seata

seata:
  # Seata接入Nacos配置中心
  config:
    # support: file, nacos, consul, apollo, zk, etcd3
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      namespace: 891d7906-dd03-4b8c-9fe9-a1f0609b3189
      group: SEATA_GROUP
      username: nacos
      password: nacos
      ##if use MSE Nacos with auth, mutex with username/password attribute
      #access-key: ""
      #secret-key: ""
  # Seata接入Nacos服务注册中心
  registry:
    # support: file, nacos, eureka, redis, zk, consul, etcd3, sofa
    type: nacos
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      namespace: 891d7906-dd03-4b8c-9fe9-a1f0609b3189
      cluster: default
      username: nacos
      password: nacos
      ##if use MSE Nacos with auth, mutex with username/password attribute
      #access-key: ""
      #secret-key: ""
  # 此处可不必配置,由于接入了nacos配置,以下store相关配置可直接通过seataServer.properties进行配置
  # store:
    # support: file 、 db 、 redis
    # mode: db
#  server:
#    service-port: 8091 #If not configured, the default is '${server.port} + 1000'
  security:
    secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
    tokenValidityInMilliseconds: 1800000
    ignore:
      urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login

Tip:seata 版本客户端和服务端最好还保持一样

3、初始Mysql数据库

新建seata库->执行mysql.sql初始化脚本->【Seata 1.5版本mysql脚本】压缩包目录seata/script/db/mysql.sql

4、导入初始配置到nacos

1)先任意模式启动nacos,本文使用单机模式运行nacos。

win系统双击启动文件即可

Mac系统执行如下命令

复制代码
moon@moondeiMac  ~  %  cd /Users/moon/Downloads/nacos-2.2.1/distribution/target/nacos-server-2.2.1/nacos/bin
moon@moondeiMac bin % sh startup.sh -m standalone

2)新建一个namespace用于本地开发使用eg:dev

3)修改压缩包目录seata/script/config-center/config.txt文件中几处内容:

复制代码
# 存储模式
store.mode=db
 
store.db.datasource=druid
store.db.dbType=mysql
# 需要根据mysql的版本调整driverClassName
# mysql8及以上版本对应的driver:com.mysql.cj.jdbc.Driver
# mysql8以下版本的driver:com.mysql.jdbc.Driver
store.db.driverClassName=com.mysql.jdbc.Driver
# 注意根据生产实际情况调整参数host和port
store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&rewriteBatchedStatements=true
# 数据库用户名密码
store.db.user=root
store.db.password=12345678
# 微服务里配置与这里一致
service.vgroupMapping.dev_tx_group=default

特别说明下:

配置事务分组service.vgroupMapping.dev_tx_group=default

dev_tx_group:需要与客户端保持一致 ,可以自定义

default:需要跟客户端和application.yml中的cluster保持一致

default 必须要等于 registry.conf cluster = "default"

4)官方推荐通过压缩包目录seatascript/config-center/nacos/nacos-config.sh将修改后的config.txt发布到nacos上

复制代码
# 运行指令 ,通过 Git Bash Here
sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 891d7906-dd03-4b8c-9fe9-a1f0609b3189

# 具体说明参见:http://seata.io/zh-cn/docs/user/configurations.html
# -h: nacos host,默认localhost
# -p: nacos端口,默认8848
# -g: nacos分组,默认'SEATA_GROUP'.
# -t: 租户信息Tenant information,对应nacos namespace ID,默认''
# -u: nacos用户名,默认''
# -w: nacos用户密码,默认''

5)导入结果:

复制代码
namespace: dev
group: SEATA_GROUP
配置项变成了N个,每项都可单独修改。

5、启动测试

进入seata/bin 目录下,执行命令:

复制代码
sh seata-server.sh 

可以看到seata-server成功注入nacos,至此Seata Server端处理完毕。

二、Seata Client端搭建

1、为示例业务创建表

以用户购买商品的业务逻辑为例搭建微服务系统:

仓储服务(Stock):对给定的商品扣除仓储数量。

订单服务(Order):根据采购需求创建订单。

账户服务(Account):从用户账户中扣除余额。

三个独立的应用,分别使用三个独立的数据源。

为示例业务创建库、表,及每个库增加undo_log表,执行脚本

注意:每个业务数据库都要有UNDO_LOG

2、业务代码集成 Seata

源码:项目源码

1)父pom引入依赖:

复制代码
 <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-dependencies</artifactId>
          <version>2021.0.4</version>
          <type>pom</type>
          <scope>import</scope>
        </dependency>
        <dependency>
          <groupId>com.alibaba.cloud</groupId>
          <artifactId>spring-cloud-alibaba-dependencies</artifactId>
          <version>2021.0.4.0</version>
          <type>pom</type>
          <scope>import</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-dependencies</artifactId>
          <version>2.6.11</version>
          <type>pom</type>
          <scope>import</scope>
        </dependency>

2)子pom引入依赖:

复制代码
 <!-- seata -->
<dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
  <!--seata starter -->
<dependency>
			<groupId>io.seata</groupId>
			<artifactId>seata-spring-boot-starter</artifactId>
</dependency>

 <!--nacos discovery -->
 <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  </dependency>
   <!--nacos config -->
<dependency>
       <groupId>com.alibaba.cloud</groupId>
       <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
 </dependency>
     <!--openfeign -->
<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>3.1.3</version>
 </dependency>

3)yml文件,其他两个类似:

复制代码
server:
  port: 2001

spring:
  application:
    name: seata-order-service
  cloud:
    nacos:
      discovery:
        # 服务分组
        group: SEATA_GROUP
        server-addr: http://localhost:8848
        # 必须填命名空间的ID
        namespace: 891d7906-dd03-4b8c-9fe9-a1f0609b3189
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource  #当前数据源操作类型
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/seata_order?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false #useSSL安全加固
    username: root
    password: 12345678


# MyBatis Plus配置
mybatis-plus:
  # 配置mapper的扫描,找到所有的mapper.xml映射文件
  mapper-locations: classpath*:mapper/**/*.xml
  #实体扫描,多个package用逗号或者分号分隔
  typeAliasesPackage: com.qytest.springcloud.entitites
  global-config:
    db-config:
      id-type: auto
  configuration:
    # 开启驼峰,开启后,只要数据库字段和对象属性名字母相同,无论中间加多少下划线都可以识别
    map-underscore-to-camel-case: true

# Seata 配置
seata:
  application-id: seata-server
  # 是否启用数据源bean的自动代理
  enable-auto-data-source-proxy: false
  tx-service-group: dev_tx_group  # 必须和服务器配置一样
  registry:
    type: nacos
    nacos:
      # Nacos 服务地址
      server-addr: http://localhost:8848
      group: SEATA_GROUP
      namespace: 891d7906-dd03-4b8c-9fe9-a1f0609b3189
      application: seata-server # 必须和服务器配置一样
      username: nacos
      password: nacos
      cluster: default
  config:
    type: nacos
    nacos:
      server-addr: ${spring.cloud.nacos.discovery.server-addr}
      group: SEATA_GROUP
      namespace: 891d7906-dd03-4b8c-9fe9-a1f0609b3189
  service:
    vgroup-mapping:
      tx-service-group: dev_tx_group # 必须和服务器配置一样
    disable-global-transaction: false
  client:
    rm:
      # 是否上报成功状态
      report-success-enable: true
      # 重试次数
      report-retry-count: 5

4)编写业务测试类

order通过feign接口调用库存及账户系统接口

复制代码
@RestController
@RequestMapping("")
@Slf4j
public class OrderController {
    @Resource
    private OrderService orderService;
    @GetMapping("/order/create")
    public CommonResult<Order> create(Order order) {
        orderService.create(order);
        return new CommonResult<Order>(200, "订单创建成功", order);
    }

}

public interface OrderService extends IService<Order> {
    void create(Order order);
}

@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

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

        /**
         * 创建订单->调用库存服务扣减库存->调用账户服务扣减账户余额->修改订单状态
         * 简单说:下订单->扣库存->减余额->改状态
         */
        @Override
        public void create(Order order) {
            //1 新建订单
            log.info("----->开始新建订单");
            baseMapper.create(order);
            log.info("----->新建订单完成");

            //2 扣减库存
            log.info("----->订单微服务开始调用库存,做扣减Count");
            storageService.decrease(order.getProductId(), order.getCount());
            log.info("----->库存扣减Count完成");

            //3 扣减账户
            log.info("----->订单微服务开始调用账户,做扣减Money");
            accountService.decrease(order.getUserId(), order.getMoney());
            log.info("----->账户扣减Money完成");

            //4 修改订单状态,从0到1,1代表已经完成
            log.info("----->修改订单状态开始");
            baseMapper.update(order.getUserId(),0);
            log.info("----->修改订单状态结束");

            log.info("----->下订单结束了,O(∩_∩)O哈哈~");

        }
}

5)启动测试

复制代码
# 先单机模式启动nacos
moon@moondeiMac  ~  %  cd /Users/moon/Downloads/nacos-2.2.1/distribution/target/nacos-server-2.2.1/nacos/bin
moon@moondeiMac bin % sh startup.sh -m standalone

# 再启动seata
moon@moondeiMac  ~  %  cd /Users/moon/Downloads/seata/bin
moon@moondeiMac bin % sh seata-server.sh 

分别访问:http://localhost:8848/nacos、http://localhost:7091/确认下nacos和seata启动无误。

然后依次启动seata-account-service、seata-storage-service、seata-order-service

请求接口,模拟正常下单:

http://localhost:2001/order/create?userId=1\&productId=1\&count=10\&money=100

运行结果:

3、常见问题

1)can not get cluster name in registry config 'service.vgroupMapping.xx', please make sure registry问题解决;

核对项目中和配置文件是否一致:

2)ERROR --- [cos.client.naming.updater] c.a.nacos.client.security.SecurityProxy : [SecurityProxy] login http request failed url: http://127.0.0.1:8848/nacos/v1/auth/users/login, params: {username=nacos}, bodyMap: {password=nacos}, errorMsg: Server returned HTTP response code: 500 for URL: http://127.0.0.1:8848/nacos/v1/auth/users/login?username=nacos

大体上是版本问题,参考文章开头,更换组件版本。

注意以下几点:

Seata相关配置是否正确

Seata Server是否正常启动,并可以被访问

Seata Client是否正确配置,并与Seata Server保持连接

相关推荐
咖啡不甜不好喝6 小时前
SpringCloud之OpenFeign
spring cloud·openfeign
黄俊懿10 小时前
【深入理解SpringCloud微服务】Spring-Security作用与原理解析
java·后端·安全·spring·spring cloud·微服务·架构师
叫致寒吧14 小时前
Dockerfile
java·spring cloud·eureka
悟空码字17 小时前
从零到一搭建SpringCloud微服务,一场代码世界的“分家”大戏
java·后端·spring cloud
黄俊懿18 小时前
【深入理解SpringCloud微服务】Gateway源码解析
java·后端·spring·spring cloud·微服务·gateway·架构师
刘个Java19 小时前
手搓遥控器通过上云api执行航线
java·redis·spring cloud·docker
没有bug.的程序员19 小时前
Ribbon vs LoadBalancer 深度解析
jvm·后端·spring cloud·微服务·ribbon·架构·gc调优
黄俊懿1 天前
【深入理解SpringCloud微服务】Seata(AT模式)源码解析——全局事务的回滚
java·后端·spring·spring cloud·微服务·架构·架构师
码农小卡拉2 天前
Java多线程:CompletableFuture使用详解(超详细)
java·开发语言·spring boot·python·spring·spring cloud
秋邱2 天前
Java面向对象进阶:封装、继承、多态的实现逻辑与实战案例
java·开发语言·后端·spring cloud·ar·restful