猿创征文|手把手教你微服务分布式事务与Seata框架源码分析(二)

本文涉及的产品
注册配置 MSE Nacos/ZooKeeper,118元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
云原生网关 MSE Higress,422元/月
简介: 猿创征文|手把手教你微服务分布式事务与Seata框架源码分析

三,Seata 安装


1,下载seata


官网下载地址: https://seata.io/zh-cn/blog/download.html


2,安装seata


解压seata-server-1.5.2安装包。解压出来我们进入bin目录会看到相应的启动脚本(由于这里是在Windows演示)

1.png

在 Linux/Mac 下

sh ./bin/seata-server.sh

在 Windows 下

bin\seata-server.bat

高可用部署:

Seata 的高可用依赖于注册中心、配置中心和数据库来实现。使用nacos和redis为例

1.png

这里我们看到是基于文件的方式,后面我们会有详细的课程讲解基于nacos注册中心的安装配置等


3,运行seata


  • windows:bin目录下双击seata-server.bat启动
  • linux:命令行启动 seata-server.sh -h 127.0.0.1 -p 8091


启动参数:

  • -h: 注册到注册中心的ip
  • -p: Server rpc 监听端口
  • -m: 全局事务会话信息存储模式,nacos, consul, apollo, zk, etcd3,优先读取启动参数
  • -n: Server node,多个Server时,需区分各自节点,用于生成不同区间的transactionId,以免冲突
  • -e: 环境配置

1.png


四,项目环境搭建


1,增加 Maven 依赖


首先,您需要将 nacos-client 的 Maven 依赖添加到您的项目 pom.xml 文件中

<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-spring-boot-starter</artifactId>
    <version>最新版</version>
</dependency>
<dependency>
    <groupId>com.alibaba.nacos</groupId>
    <artifactId>nacos-client</artifactId>
    <version>1.2.0及以上版本</version>
</dependency>


2,Client端配置中心


在 application.yml 中加入对应的配置中心,其余配置参考

seata:
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      group : "SEATA_GROUP"
      namespace: ""
      username: "XXXXXX"


3,Server端配置中心


在 registry.conf 中加入对应配置中心,其余配置参考

config {
  type = "nacos"
  nacos {
    serverAddr = "127.0.0.1:8848"
    group = "SEATA_GROUP"
    namespace = ""
    username = "nacos"
  }
}


4,上传配置至Nacos配置中心

seata:
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      group : "SEATA_GROUP"
      namespace: ""
      dataId: "seataServer.properties"
      username: "nacos"


五,源码分析


今天咱们开始咱们的主题了,在了解以上问题之后我们是不是比较好奇他的运行流程。了解执行流程我们就要从官网,或者源码入手来了解


1,启动类


// 【排除SpringBoot启动时自动加载GlobalTransactionAutoConfiguration.class】
@SpringBootApplication(exclude = {GlobalTransactionAutoConfiguration.class})
@EnableFeignClients   // 远程调用
@EnableDiscoveryClient   // 开启nacos服务
public class GatewayApplication{
   public static void main(String[] args) {
     ErosApplication.run(ProjectNameConstatnt.GATEWAY_NAME,"consume",GatewayApplication.class,args);
  }
}


2,配置类

@GlobalTransactional(name="XXXXX",rollbackFor = RuntimeException.class)


3,@GlobalTransactional


方法上加了@GlobalTransactional,Seata通过aop检测到之后,就会使用TM和TC通信,注册全局事务。

在@GlobalTransactional涵括的代码中,不管是本服务中的sql操作,还是feign调用别的服务的sql操作,只要sql操作满足如下:insert操作,delete操作,update操作,select for update操作。 就会被seata增强,使用RM与TC通信,注册分支事务。

全局事务:包括开启事务、提交、回滚、获取当前状态等方法。

public interface GlobalTransaction {
    /**
     * 开启一个全局事务(使用默认的事务名和超时时间)
     */
    void begin() throws TransactionException;
    /**
     * 开启一个全局事务,并指定超时时间(使用默认的事务名)
     */
    void begin(int timeout) throws TransactionException;
    /**
     * 开启一个全局事务,并指定事务名和超时时间
     */
    void begin(int timeout, String name) throws TransactionException;
    /**
     * 全局提交
     */
    void commit() throws TransactionException;
    /**
     * 全局回滚
     */
    void rollback() throws TransactionException;
    /**
     * 获取事务的当前状态
     */
    GlobalStatus getStatus() throws TransactionException;
    /**
     * 获取事务的 XID
     */
    String getXid();
}

GlobalTransactionScanner继承自AbstractAutoProxyCreator,在这里拦截到加了@GlobalTransactional的方法。

GlobalTransactionScanner

1.png

  • AbstractAutoProxyCreator:wrapIfNecessary(aop的核心),getAdvicesAndAdvisorsForBean(拦截器)
  • InitializingBean:afterPropertiesSet(初始化TM,RM)


3.1 初始化TM,RM

@Override
    public void afterPropertiesSet() {
        //是否禁止了全局事务
        if (disableGlobalTransaction) {
            if (LOGGER.isInfoEnabled()) {
                LOGGER.info("Global transaction is disabled.");
            }
            return;
        }
        //初始化netty 客户端(TM  RM)
        initClient();
    }

初始化TM,RM

private void initClient() {  
        //init TM
        TMClient.init(applicationId, txServiceGroup);
        //init RM
        RMClient.init(applicationId, txServiceGroup);
    }

1.png


3.2 TransactionalTemplate


GlobalTransaction 和 GlobalTransactionContext API 把一个业务服务的调用包装成带有分布式事务支持的服务。

public class TransactionalTemplate {
    public Object execute(TransactionalExecutor business) throws TransactionalExecutor.ExecutionException {
        // 1. 获取当前全局事务实例或创建新的实例
        GlobalTransaction tx = GlobalTransactionContext.getCurrentOrCreate();
        // 2. 开启全局事务
        try {
            tx.begin(business.timeout(), business.name());
        } catch (TransactionException txe) {
            // 2.1 开启失败
            throw new TransactionalExecutor.ExecutionException(tx, txe,
                TransactionalExecutor.Code.BeginFailure);
        }
        Object rs = null;
        try {
            // 3. 调用业务服务
            rs = business.execute();
        } catch (Throwable ex) {
            // 业务调用本身的异常
            try {
                // 全局回滚
                tx.rollback();
                // 3.1 全局回滚成功:抛出原始业务异常
                throw new TransactionalExecutor.ExecutionException(tx, TransactionalExecutor.Code.RollbackDone, ex);
            } catch (TransactionException txe) {
                // 3.2 全局回滚失败:
                throw new TransactionalExecutor.ExecutionException(tx, txe,
                    TransactionalExecutor.Code.RollbackFailure, ex);
            }
        }
        // 4. 全局提交
        try {
            tx.commit();
        } catch (TransactionException txe) {
            // 4.1 全局提交失败:
            throw new TransactionalExecutor.ExecutionException(tx, txe,
                TransactionalExecutor.Code.CommitFailure);
        }
        return rs;
    }
}

DataSourceProxy#getConnection

@Override
    public ConnectionProxy getConnection() throws SQLException {
        Connection targetConnection = targetDataSource.getConnection();
        return new ConnectionProxy(this, targetConnection);
    }

ConnectionProxy#doCommit

private void doCommit() throws SQLException {
    //处理@GlobalTransaction的分支事务
        if (context.inGlobalTransaction()) {
            processGlobalTransactionCommit();
        } 
        //处理@GlobalLock,即检查一下是否可以获取全局锁
    else if (context.isGlobalLockRequire()) {
            processLocalCommitWithGlobalLocks();
        } else {
            targetConnection.commit();
        }
    }

ConnectionProxy#processGlobalTransactionCommit

1.png

模板的异常方法

class ExecutionException extends Exception {
        // 发生异常的事务实例
        private GlobalTransaction transaction;
        // 异常编码:
        // BeginFailure(开启事务失败)
        // CommitFailure(全局提交失败)
        // RollbackFailure(全局回滚失败)
        // RollbackDone(全局回滚成功)
        private Code code;
        // 触发回滚的业务原始异常
        private Throwable originalException;

 

  以上就是我们今天的教程,如果本文对你有所帮助,欢迎关注点赞,分享给您身边的朋友。您的鼓励就是对我的最大动力。

相关文章
|
10天前
|
安全 应用服务中间件 API
微服务分布式系统架构之zookeeper与dubbo-2
微服务分布式系统架构之zookeeper与dubbo-2
|
10天前
|
负载均衡 Java 应用服务中间件
微服务分布式系统架构之zookeeper与dubbor-1
微服务分布式系统架构之zookeeper与dubbor-1
|
1月前
|
Dubbo Java 应用服务中间件
微服务框架Dubbo环境部署实战
微服务框架Dubbo环境部署的实战指南,涵盖了Dubbo的概述、服务部署、以及Dubbo web管理页面的部署,旨在指导读者如何搭建和使用Dubbo框架。
85 17
微服务框架Dubbo环境部署实战
|
22天前
|
SQL NoSQL 数据库
SpringCloud基础6——分布式事务,Seata
分布式事务、ACID原则、CAP定理、Seata、Seata的四种分布式方案:XA、AT、TCC、SAGA模式
SpringCloud基础6——分布式事务,Seata
|
15天前
|
Kubernetes Java Android开发
用 Quarkus 框架优化 Java 微服务架构的设计与实现
Quarkus 是专为 GraalVM 和 OpenJDK HotSpot 设计的 Kubernetes Native Java 框架,提供快速启动、低内存占用及高效开发体验,显著优化了 Java 在微服务架构中的表现。它采用提前编译和懒加载技术实现毫秒级启动,通过优化类加载机制降低内存消耗,并支持多种技术和框架集成,如 Kubernetes、Docker 及 Eclipse MicroProfile,助力开发者轻松构建强大微服务应用。例如,在电商场景中,可利用 Quarkus 快速搭建商品管理和订单管理等微服务,提升系统响应速度与稳定性。
31 5
|
1月前
|
存储 Java Maven
从零到微服务专家:用Micronaut框架轻松构建未来架构
【9月更文挑战第5天】在现代软件开发中,微服务架构因提升应用的可伸缩性和灵活性而广受欢迎。Micronaut 是一个轻量级的 Java 框架,适合构建微服务。本文介绍如何从零开始使用 Micronaut 搭建微服务架构,包括设置开发环境、创建 Maven 项目并添加 Micronaut 依赖,编写主类启动应用,以及添加控制器处理 HTTP 请求。通过示例代码展示如何实现简单的 “Hello, World!” 功能,并介绍如何通过添加更多依赖来扩展应用功能,如数据访问、验证和安全性等。Micronaut 的强大和灵活性使你能够快速构建复杂的微服务系统。
61 5
|
29天前
|
缓存 Java 应用服务中间件
随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架
【9月更文挑战第6天】随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架。Nginx作为高性能的HTTP反向代理服务器,常用于前端负载均衡,提升应用的可用性和响应速度。本文详细介绍如何通过合理配置实现Spring Boot与Nginx的高效协同工作,包括负载均衡策略、静态资源缓存、数据压缩传输及Spring Boot内部优化(如线程池配置、缓存策略等)。通过这些方法,开发者可以显著提升系统的整体性能,打造高性能、高可用的Web应用。
58 2
|
1月前
|
Cloud Native 安全 Java
Micronaut对决Spring Boot:谁是微服务领域的王者?揭秘两者优劣,选对框架至关重要!
【9月更文挑战第5天】近年来,微服务架构备受关注,Micronaut和Spring Boot成为热门选择。Micronaut由OCI开发,基于注解的依赖注入,内置多种特性,轻量级且启动迅速;Spring Boot则简化了Spring应用开发,拥有丰富的生态支持。选择框架需考虑项目需求、团队经验、性能要求及社区支持等因素。希望本文能帮助您选择合适的微服务框架,助力您的软件开发项目取得成功!
99 2
|
2月前
|
监控 Go API
带你十天轻松搞定 Go 微服务之大结局(分布式事务)
带你十天轻松搞定 Go 微服务之大结局(分布式事务)
|
2月前
|
Cloud Native JavaScript API
一文读懂云原生 go-zero 微服务框架
一文读懂云原生 go-zero 微服务框架
下一篇
无影云桌面