Seata(分布式事务集成测试和总结)

文章目录

    • 1.集成测试
        • 1.集成测试正常下单
          • 1.步骤
          • 2.浏览器访问 http://localhost:10008/order/save?userId=666&productId=1&nums=1&money=100
          • 3.注意事项和细节
        • 2.集成测试模拟异常
          • 1.步骤
            • 1.com/sun/springcloud/controller/StorageController.java 休眠12s,模拟openfeign超时
            • 2.仍然按照正常步骤启动并测试
            • 3.预测结果
          • 2.执行前数据库状态
            • order表
            • account表
            • storage表
          • 3.浏览器输入 http://localhost:10008/order/save?userId=666&productId=1&nums=2&money=200,12s后查看数据库状态
            • order表
            • account表(这里在写sql时并没有计算数量,所以确实应该减去200)
            • storage表(库存减2)
        • 3.集成测试分布式事务控制
          • 1.在com/sun/springcloud/service/Impl/OrderServiceImpl.java 的save方法加上@GlobalTransactional进行分布式事务控制
          • 2.测试步骤
          • 3.全部启动后查看nacos注册情况
          • 4.测试前数据库状态
          • 5.浏览器请求 http://localhost:10008/order/save?userId=666&productId=1&nums=1&money=100
          • 5.注意事项
    • 2.seata分布式事务总结
        • 1.工作机制
        • 2.seata的使用流程
          • 1.安装
          • 2.修改 D:\seata\conf\file.conf文件
            • 1.修改事务组(需要进行分布式事务控制的微服务在同一组)
            • 2.修改日志存储模式为db
            • 3.修改数据库(MySQL5.7)连接信息
          • 3.修改registry.conf 配置注册中心nacos(seata需要注册到nacos)
          • 4.创建seata数据库和表
            • 1.创建seata数据库
            • 2.复制db_store.sql的内容,创建需要的表
          • 5.启动nacos和seata进行测试,seata会注册到nacos
          • 6.为每个需要分布式事务控制的数据库执行 db_undo_log.sql,创建undo_log表,用于事务回滚
          • 7.pom.xml引入依赖
          • 8.application.yml
          • 9.D:\seata\conf下的两个配置文件复制到src/main/resources下并修改
            • 1.将file.conf复制到src/main/resources下,然后修改这行,`seata的服务ip+端口`以及`db`根据实际情况修改(前面是修改过的)
            • 2.registry.conf复制到src/main/resources下,然后配置注册中心nacos(前面也配过,直接复制即可)
            • 3.最终的文件目录
          • 10.进行业务逻辑编写
            • 1.创建实体类
            • 2.dao层
            • 3.service层
            • 4.controller层
          • 11.两个常规配置类
            • 1.MyBatisConfig.java 配置类,依赖注入所有Mapper接口(不用加@Mapper注解了)
            • 2.DataSourceProxyConfig.java 配置数据源代理为 seata
          • 12.创建主启动类(示例)
          • 13.OpenFeign远程调用细节
            • 1.在前面的依赖中已经引入了OpenFeign,并且在主启动类中也开启了Feign客户端
            • 2.service接口声明需要远程调用的controller
            • 3.远程调用的方式
            • 4.谁可以远程调用

1.集成测试

1.集成测试正常下单
1.步骤

image-20240331195720151

2.浏览器访问 http://localhost:10008/order/save?userId=666&productId=1&nums=1&money=100

image-20240331200211635

image-20240331200315814

image-20240331200345159

image-20240331200405815

image-20240331200414455

3.注意事项和细节

image-20240331201240727

2.集成测试模拟异常
1.步骤
1.com/sun/springcloud/controller/StorageController.java 休眠12s,模拟openfeign超时

image-20240331204813269

2.仍然按照正常步骤启动并测试

image-20240331195720151

3.预测结果
  • 保存订单,扣减账户余额,扣减库存成功!但是修改订单状态失败,也就是status是0!

image-20240331202326884

image-20240331202503115

2.执行前数据库状态
order表

image-20240331204912334

account表

image-20240331204932277

storage表

image-20240331205004551

3.浏览器输入 http://localhost:10008/order/save?userId=666&productId=1&nums=2&money=200,12s后查看数据库状态
order表

image-20240331205124780

account表(这里在写sql时并没有计算数量,所以确实应该减去200)

image-20240331205149516

storage表(库存减2)

image-20240331210545726

3.集成测试分布式事务控制
1.在com/sun/springcloud/service/Impl/OrderServiceImpl.java 的save方法加上@GlobalTransactional进行分布式事务控制

image-20240401085848112

2.测试步骤

image-20240331195720151

3.全部启动后查看nacos注册情况

image-20240401090152198

4.测试前数据库状态

image-20240401090227123

image-20240401090238720

image-20240401090249370

5.浏览器请求 http://localhost:10008/order/save?userId=666&productId=1&nums=1&money=100

image-20240401090600011

image-20240401090536951

image-20240401090546928

image-20240401090555538

5.注意事项

image-20240401091116586

2.seata分布式事务总结

1.工作机制

image-20240401100528767

2.seata的使用流程
1.安装
2.修改 D:\seata\conf\file.conf文件
1.修改事务组(需要进行分布式事务控制的微服务在同一组)

image-20240331094307051

2.修改日志存储模式为db

image-20240331094402339

3.修改数据库(MySQL5.7)连接信息

在这里插入图片描述

3.修改registry.conf 配置注册中心nacos(seata需要注册到nacos)

image-20240331095851458

image-20240331095834040

4.创建seata数据库和表
1.创建seata数据库
# 创建数据库 seata
create database seata;
use seata;
2.复制db_store.sql的内容,创建需要的表

image-20240401101509841

image-20240331095307621

5.启动nacos和seata进行测试,seata会注册到nacos
6.为每个需要分布式事务控制的数据库执行 db_undo_log.sql,创建undo_log表,用于事务回滚

image-20240331103729957

7.pom.xml引入依赖
  • 注意这里引入的nacos是nacos-discovery starter,没有整合Seata之前引入的跟这个不一样!!!
    <dependencies>
        <!-- 提示 application.yml -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- 引入 openfeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <!-- 在微服务模块引入 nacos-discovery starter -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <!--seata-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
            <exclusions>
                <!-- 排除自带的 seata-all -->
                <exclusion>
                    <artifactId>seata-all</artifactId>
                    <groupId>io.seata</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- 引入指定版本的 io.seata -->
        <dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-all</artifactId>
            <version>0.9.0</version>
        </dependency>

        <!-- springboot web starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!-- 如果在子工程/模块指定了 version,则以指定为准 -->
        </dependency>

        <!--
        1. starter-actuator 是 springboot 程序的监控系统,可以实现健康检查,info 信息
        等
        2. 访问 http://localhost:10000/actuator 可以看到相关链接, 还可以做相关设置. -->
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web
        -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>

        <!-- druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <!-- 这里我们重新指定一下 version 因为父项目中没有对这个依赖进行版本仲裁-->
            <version>1.1.13</version>
        </dependency>

        <!-- mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!-- jdbc -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- 公共模块的jar包 -->
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>e_commerce_center-common-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
8.application.yml
server:
  port: 10010 # 配置服务端口
spring:
  application:
    name: seata-storage-micor-service # 配置服务的名称,名字任意这里与项目名保持一致
  cloud:
    alibaba:
      seata:  # 配置seata
        tx-service-group: sun_order_tx_group # 自定义事务组名称,与\conf\file.conf保持一致
    nacos: # 配置nacos
      discovery:
        server-addr: localhost:8848
  datasource: # 配置数据源
    driver-class-name: com.mysql.jdbc.Driver
    # 别忘记创建数据库之后修改数据库名称
    url: 
    username: 
    password: 
logging:  # 配置seata日志级别
  level:
    io:
      seata: info
mybatis:
  mapperLocations: classpath:mapper/*.xml # 扫描所有Mapper.xml
  configuration:
    map-underscore-to-camel-case: true # 开启驼峰命名
9.D:\seata\conf下的两个配置文件复制到src/main/resources下并修改
1.将file.conf复制到src/main/resources下,然后修改这行,seata的服务ip+端口以及db根据实际情况修改(前面是修改过的)

image-20240331112838536

2.registry.conf复制到src/main/resources下,然后配置注册中心nacos(前面也配过,直接复制即可)

image-20240331113355613

3.最终的文件目录

image-20240331113408627

10.进行业务逻辑编写
1.创建实体类
  • 如果数据库中的数据是sun_name则在实体类中可以编写为sunName,不过这样需要在application.yml中开启自动驼峰命名(上面配置了)
  • 这个就相当于在每个Mapper.xml中加了一个resultMap映射,如果实体类属性和表的字段可以被自动驼峰命名所映射那么就不需要再写resultMap
2.dao层
  • Mapper接口注入容器
  • Mapper接口的@Param注解一旦指定,就不需要在xml实现的时候指定参数类型了,直接使用#{}来取出数据即可
  • Mapper.xml在application.yml中已经配置了自动扫描
3.service层
  • service接口编写
  • service实现类注入容器
4.controller层
  • 注入容器
  • 在微服务中如果使用GetMapping则参数需要添加@RequestParam
  • 如果使用PostMapping则参数需要添加@RequestBody
11.两个常规配置类
1.MyBatisConfig.java 配置类,依赖注入所有Mapper接口(不用加@Mapper注解了)
package com.sun.springcloud.config;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;

/**
 * Description: MyBatis配置类,扫描所有Mapper接口,这样就不用在每个Mapper接口上添加@Mapper注解
 *
 * @Author sun
 * @Create 2024/3/31 13:16
 * @Version 1.0
 */
@MapperScan("com.sun.springcloud.dao")
@Configuration
public class MyBatisConfig {
}

2.DataSourceProxyConfig.java 配置数据源代理为 seata
  • 这里需要注意:配置文件中的mybatis.mapperLocations是以驼峰命名的
package com.sun.springcloud.config;

import com.alibaba.druid.pool.DruidDataSource;
import io.seata.rm.datasource.DataSourceProxy;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.transaction.SpringManagedTransactionFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;

/**
 * Description: 配置数据源的代理是 seata
 *
 * @Author sun
 * @Create 2024/3/31 13:28
 * @Version 1.0
 */
@Configuration
public class DataSourceProxyConfig {
    // 配置文件中的mybatis.mapperLocations
    @Value("${mybatis.mapperLocations}")
    private String mapperLocations; // 1.mybatis的mapper文件位置

    // 配置数据源
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource") // 2.读取配置文件中的数据源配置
    public DataSource druidDataSource() {
        return new DruidDataSource();
    }

    // 配置数据源代理为seata的DataSourceProxy
    @Bean // 配置数据源代理引入的包: io.seata.rm.datasource.DataSourceProxy
    public DataSourceProxy dataSourceProxy(DataSource dataSource) {
        return new DataSourceProxy(dataSource);
    }

    // 配置SqlSessionFactory为seata的SqlSessionFactoryBean
    @Bean // 配置SqlSessionFactory,常规配置
    public SqlSessionFactory sqlSessionFactoryBean(DataSourceProxy dataSourceProxy)
            throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean =
                new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSourceProxy);
        sqlSessionFactoryBean.setMapperLocations
                (new PathMatchingResourcePatternResolver().getResources(mapperLocations)); // 3.mybatis的mapper文件位置
        sqlSessionFactoryBean.setTransactionFactory
                (new SpringManagedTransactionFactory());
        return sqlSessionFactoryBean.getObject();
    }
}

12.创建主启动类(示例)
package com.sun.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * Description:
 *
 * @Author sun
 * @Create 2024/3/31 13:37
 * @Version 1.0
 */
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) // 取消数据源的自动创建,使用代理数据源
@EnableDiscoveryClient // 开启服务发现
@EnableFeignClients // 开启Feign客户端
public class SeataStorageMicroServiceApplication10010 {
    public static void main(String[] args) {
        SpringApplication.run(SeataStorageMicroServiceApplication10010.class, args);
    }
}

13.OpenFeign远程调用细节
1.在前面的依赖中已经引入了OpenFeign,并且在主启动类中也开启了Feign客户端
2.service接口声明需要远程调用的controller
  • 这里的FeignClient可以进行服务发现,得到要调用的服务的ip+端口+上下文路径
  • 这里的RequestMapping可以找到远程调用的服务的资源路径,与服务发现的路径进行拼接即可找到指定资源
  • 具体声明的方式就是
    1. 添加@FeignClient注解,指定要远程调用服务的application-name(注意不能带_)
    2. 将需要调用的controller直接复制过来,然后去掉方法体即可
package com.sun.springcloud.service;

import com.sun.springcloud.util.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * Description:
 *
 * @Author sun
 * @Create 2024/3/31 16:19
 * @Version 1.0
 */
@FeignClient(value = "seata-storage-micor-service")
public interface StorageService {
    @RequestMapping("/storage/reduce")
    public Result reduce(Long productId, Integer nums);
}

3.远程调用的方式
  • 通过依赖注入针对service接口的代理对象进行远程调用
4.谁可以远程调用
  • service接口实现类
  • controller

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/520769.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

虚拟机打不开

问题 另一个程序已锁定文件的一部分&#xff0c;进程无法访问 打不开磁盘“G:\centeros\hadoop104kl\hadoop100-cl2.vmdk”或它所依赖的某个快照磁盘。 模块“Disk”启动失败。 未能启动虚拟机。 原因 前一次非正常关闭虚拟机导致.lck 文件是VMWare软件的一种磁盘锁文件&…

线性数据结构

1.数组 数组使用一块连续的内存来存储元素&#xff0c;并且元素的类型都是相同的。可以通过索引来访问。 2.链表 链表由一系列节点组成&#xff0c;每个节点包含两部分&#xff1a;数据部分和指针部分。数据部分用于存储元素的值&#xff0c;指针部分则指向下一个节点。没有使…

机器学习 - multi-class 数据集训练 (含代码)

直接上代码 # Multi-class datasetimport numpy as np RANDOM_SEED 42 np.random.seed(RANDOM_SEED) N 100 # number of points per class D 2 # dimensionality K 3 # number of classes X np.zeros((N*K, D)) y np.zeros(N*K, dtypeuint8) for j in range(K):ix rang…

多线程的入门(二)线程实现与初步使用

1.实现Runable接口 实现Runable接口&#xff0c;实现run方法&#xff1b; 这种方式创建的线程实现类执行时需要创建Thread实例去运行该任务 示例如下&#xff1a; package com.example.springbootdamo.Thread;import org.apache.logging.log4j.LogManager; import org.apach…

三子棋游戏----C语言版【超级详细 + 视频演示 + 完整源码】

㊙️小明博客主页&#xff1a;➡️ 敲键盘的小明 ㊙️ ✅关注小明了解更多知识☝️ 文章目录 前言一、三子棋的实现思路二、三子棋的实现步骤2.1 先显示游戏的菜单2.2 游戏的具体实现2.2.1 棋盘的初始化2.2.2 展示棋盘2.2.3 下棋&#x1f534;玩家下棋&#x1f534;电脑下棋2.2…

二叉树进阶——手撕二叉搜索树

troop主页&#xff1a;troop 手撕二叉搜索树 1.二叉搜索树的定义2.实现&#xff08;非递归&#xff09;补充结构2.1查找2.2插入2.3删除&#xff08;重要&#xff09;情况1(无孩子&&一个孩子&#xff09; 3.二叉搜索树的应用3.1K模型3.2KV模型3.2.1KV模型的实现 总结二叉…

RUST语言值所有权之内存复制与移动

1.RUST中每个值都有一个所有者,每次只能有一个所有者 String::from函数会为字符串hello分配一块内存 内存示例如下: 在内存分配前调用s1正常输出 在分配s1给s2后调用报错 因为s1分配给s2后,s1的指向自动失效 s1被move到s2 s1自动释放 字符串克隆使用

I2C驱动实验:读取AP3216C设备中寄存器的数据

一. 简介 经过前面几篇文章的学习&#xff0c;已经完成了I2C驱动框架&#xff0c;字符设备驱动框架&#xff0c;编写了 读写 I2C设备中寄存器的数据的代码&#xff0c;文章如下&#xff1a; I2C驱动实验&#xff1a;实现读/写I2C设备寄存器的函数-CSDN博客 本文在此基础上&a…

C#开发中一些常用的工具类分享

一、配置文件读写类 用于在开发时候C#操作配置文件读写信息 1、工具类 ReadIni 代码 using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks;namesp…

不同设备使用同一个Git账号

想要在公司和家里的电脑上用同一个git账号来pull, push代码 1. 查看原设备的用户名和邮箱 第1种方法&#xff0c; 依次输入 git config user.name git config user.email第2种方法&#xff0c; 输入 cat ~/.gitconfig2. 配置新设备的用户名和邮箱 用户名和邮箱与原设备保持…

高效学习方法:冥想背诵,看一句念一句,再每个词分析位置及语法等合理性,忘记哪个词再看猜下为什么会忘,跟自己的表达哪里不一样。

原则&#xff1a;易学则易行&#xff0c;则效果最好。《易经》 你提到的这种学习方法结合了多种记忆和理解技巧&#xff0c;可以帮助提高学习效率。下面是对这种方法的一个详细解释和一些建议&#xff1a; 冥想背诵&#xff1a;通过冥想来集中注意力&#xff0c;可以帮助你在没…

数据如何才能供得出、流得动、用得好、还安全

众所周知&#xff0c;数据要素已经列入基本生产要素&#xff0c;同时成立国家数据局进行工作统筹。目前数据要素如何发挥其价值&#xff0c;全国掀起了一浪一浪的热潮。 随着国外大语言模型的袭来&#xff0c;国内在大语言模型领域的应用也大放异彩&#xff0c;与此同时&#x…

使用YOLOv8训练自己的【目标检测】数据集

文章目录 1.收集数据集1.1 使用开源已标记数据集1.2 爬取网络图像1.3 自己拍摄数据集1.4 使用数据增强生成数据集1.5 使用算法合成图像 2.标注数据集2.1确认标注格式2.2 开始标注 3.划分数据集4.配置训练环境4.1获取代码4.2安装环境 5.训练模型5.1新建一个数据集yaml文件5.2预测…

java中的正则表达式和异常

正则表达式&#xff1a; 作用一&#xff1a;用来校验数据格式是否合法 作用二&#xff1a;在文本中查找满足要求的内容 不用正则表达式&#xff1a;检验QQ号是否合法&#xff0c;要求全部是数字&#xff0c;长度在6-20&#xff0c;不能以0开头 public class test {public stat…

手机扫码查看视频如何实现?扫描二维码在线看视频的制作技巧

现在的学校或者幼儿园会需要拍摄学生的视频&#xff0c;然后展示给其他人查看&#xff0c;为了能够方便用户能够快速的获取文件内容&#xff0c;所以经常会通过生成视频二维码的方法&#xff0c;将二维码分享之后手机扫码来获取视频内容&#xff0c;有效提升用户获取内容的体验…

PTA C 1050 螺旋矩阵(思路与优化)

本题要求将给定的 N 个正整数按非递增的顺序&#xff0c;填入“螺旋矩阵”。所谓“螺旋矩阵”&#xff0c;是指从左上角第 1 个格子开始&#xff0c;按顺时针螺旋方向填充。要求矩阵的规模为 m 行 n 列&#xff0c;满足条件&#xff1a;mn 等于 N&#xff1b;m≥n&#xff1b;且…

160.相交链表

题目描述 解题思路 ————看评论区大神的思路———— 设「第一个公共节点」为 node &#xff0c;「链表 headA」的节点数量为 aaa &#xff0c;「链表 headB」的节点数量为 bbb &#xff0c;「两链表的公共尾部」的节点数量为 ccc &#xff0c;则有&#xff1a; 头节点 …

CSS设置字体样式

目录 前言&#xff1a; 1.font-family&#xff1a; 2.font-style&#xff1a; 3.font-weight&#xff1a; 4.font-size&#xff1a; 5.font-variant&#xff1a; 6.font&#xff1a; 前言&#xff1a; 在网页中字体是重要的组成部分&#xff0c;使用好字体可以让网页更…

第一次在msf控制台中运行search命令提示Module database cache not built yet问题解决

0x00 问题描述 在新装的kali虚拟机中使用msfconsole执行search命令时提示Module database cache not built yet问题&#xff0c;显然&#xff0c;是我们相关的数据库缓存存在问题。 故障现象&#xff1a; 0x01 启动数据库服务 msf中的search功能是基于postgresql来实现的&am…

python学习25:python中的元组(tuple)

python中的元组(tuple) 1.什么是元组&#xff1f; 元组也是容器数据类型的一种&#xff0c;同列表几乎是一样的&#xff0c;都是可以在里面封装多个&#xff0c;不同类型的元素在内&#xff1b;与列表最大的不同就是&#xff1a; 元组一旦被定义&#xff0c;就不能修改 2.元组…