• 微服务整合Seata1.5.2+Nacos2.2.1+SpringBoot


    在这里插入图片描述

    本文以seata-server-1.5.2,以配置中心、注册中心使用Nacos,store.mode=db(mysql)为例进行操作。
    Seata简介及入门参看:SpringCloud入门实战(十五)分布式事务框架Seata简介

    一、Seata Server端

    1、下载seata server

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

    本文版本环境:
    Spring Cloud Alibaba 2021.0.4.0
    Spring Boot 2.6.11
    Nacos 2.2.1
    Seata1.5.2

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

    在这里插入图片描述
    解压后可以发现原来的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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

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

    3、初始Mysql数据库

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

    在这里插入图片描述

    4、导入初始配置到nacos

    1)先任意模式启动nacos,不清楚的参看:nacos安装运行,本文使用单机模式运行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
    
    • 1
    • 2

    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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    特别说明下📢:
    配置事务分组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用户密码,默认''
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    5)导入结果:

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

    在这里插入图片描述

    5、启动测试

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

    sh seata-server.sh 
    
    • 1

    可以看到seata-server成功注入nacos,至此Seata Server端处理完毕。
    在这里插入图片描述

    二、Seata Client端搭建

    1、为示例业务创建表

    以用户购买商品的业务逻辑为例搭建微服务系统:
    仓储服务(Stock):对给定的商品扣除仓储数量。
    订单服务(Order):根据采购需求创建订单。
    账户服务(Account):从用户账户中扣除余额。
    在这里插入图片描述
    三个独立的应用,分别使用三个独立的数据源。

    为示例业务创建库、表,及每个库增加undo_log表,执行脚本
    在这里插入图片描述

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

    在这里插入图片描述

    2、业务代码集成 Seata

    源码:项目源码

    在这里插入图片描述

    1)父pom引入依赖:

     <dependency>
              <groupId>org.springframework.cloudgroupId>
              <artifactId>spring-cloud-dependenciesartifactId>
              <version>2021.0.4version>
              <type>pomtype>
              <scope>importscope>
            dependency>
            <dependency>
              <groupId>com.alibaba.cloudgroupId>
              <artifactId>spring-cloud-alibaba-dependenciesartifactId>
              <version>2021.0.4.0version>
              <type>pomtype>
              <scope>importscope>
            dependency>
            <dependency>
              <groupId>org.springframework.bootgroupId>
              <artifactId>spring-boot-dependenciesartifactId>
              <version>2.6.11version>
              <type>pomtype>
              <scope>importscope>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    2)子pom引入依赖:

     
    <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-starter-alibaba-seataartifactId>
    dependency>
      
    <dependency>
    			<groupId>io.seatagroupId>
    			<artifactId>seata-spring-boot-starterartifactId>
    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>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-openfeignartifactId>
                <version>3.1.3version>
     dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    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
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    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哈哈~");
    
            }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    更多内容,可查看源码

    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 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    分别访问: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保持连接

  • 相关阅读:
    Leetcode 878. 第 N 个神奇数字
    CTFhub-RCE-过滤cat
    【JS】-内置对象API-Array(数组)-(一)改变原数组-的API-篇
    介绍一下rabbitMq应用场景
    递归算法实现二分查找c++
    算法题:平均数为k的最长连续子数组
    flink-sql写入hudi的行列转换lateral
    开源协议介绍
    基于springboot实现智慧外贸平台系统【项目源码+论文说明】计算机毕业设计
    性能优化之详解各种指标
  • 原文地址:https://blog.csdn.net/weixin_47061482/article/details/132625385