seata eureka 全局事务编号传递关键代码

本文深入解析Seata在Spring Cloud Alibaba环境下,基于Eureka的服务发现机制中,如何通过Feign进行全局事务ID(XID)的传递与获取。详细介绍了SeataRestTemplateInterceptor和SeataHandlerInterceptor的作用,以及它们如何协作确保XID在微服务间正确传播。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

seata eureka 全局事务编号传递关键代码

网文大部分是基于dobbo的分析,eureka传递xid(全局事务编号)的分析目前还没找到,断点跟踪了seata-sample的工程
seata-sample地址:https://github.com/seata/seata-samples
seata版本:0.6.1
关键依赖

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-alibaba-seata</artifactId>
                <version>0.9.1.BUILD-SNAPSHOT</version>
                <exclusions>
                    <exclusion>
                        <groupId>io.seata</groupId>
                        <artifactId>seata-spring</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>io.seata</groupId>
                <artifactId>seata-all</artifactId>
                <version>${seata.version}</version>
            </dependency>

构建feign请求头

package org.springframework.cloud.alibaba.seata.rest;

import io.seata.core.context.RootContext;
import java.io.IOException;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.support.HttpRequestWrapper;
import org.springframework.util.StringUtils;

public class SeataRestTemplateInterceptor implements ClientHttpRequestInterceptor {
    public SeataRestTemplateInterceptor() {
    }

    public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] bytes, ClientHttpRequestExecution clientHttpRequestExecution) throws IOException {
        HttpRequestWrapper requestWrapper = new HttpRequestWrapper(httpRequest);
        String xid = RootContext.getXID();
        if(!StringUtils.isEmpty(xid)) {
            //构建请求头
            requestWrapper.getHeaders().add("TX_XID", xid);
        }

        return clientHttpRequestExecution.execute(requestWrapper, bytes);
    }
}

获取xid放入seata上下文

package org.springframework.cloud.alibaba.seata.web;

import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

public class SeataHandlerInterceptorConfiguration implements WebMvcConfigurer {
    public SeataHandlerInterceptorConfiguration() {
    }

    public void addInterceptors(InterceptorRegistry registry) {
    	//注册HandlerInterceptor,拦截所有请求
        registry.addInterceptor(new SeataHandlerInterceptor()).addPathPatterns(new String[]{"/**"});
    }
}
package org.springframework.cloud.alibaba.seata.web;

import io.seata.core.context.RootContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

public class SeataHandlerInterceptor implements HandlerInterceptor {
    private static final Logger log = LoggerFactory.getLogger(SeataHandlerInterceptor.class);

    public SeataHandlerInterceptor() {
    }

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String xid = RootContext.getXID();
        String rpcXid = request.getHeader("TX_XID");
        //获取全局事务编号
        if(log.isDebugEnabled()) {
            log.debug("xid in RootContext {} xid in RpcContext {}", xid, rpcXid);
        }

        if(xid == null && rpcXid != null) {
            //设置全局事务编号
            RootContext.bind(rpcXid);
            if(log.isDebugEnabled()) {
                log.debug("bind {} to RootContext", rpcXid);
            }
        }

        return true;
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {
        String rpcXid = request.getHeader("TX_XID");
        if(!StringUtils.isEmpty(rpcXid)) {
            String unbindXid = RootContext.unbind();
            if(log.isDebugEnabled()) {
                log.debug("unbind {} from RootContext", unbindXid);
            }

            if(!rpcXid.equalsIgnoreCase(unbindXid)) {
                log.warn("xid in change during RPC from {} to {}", rpcXid, unbindXid);
                if(unbindXid != null) {
                    RootContext.bind(unbindXid);
                    log.warn("bind {} back to RootContext", unbindXid);
                }
            }

        }
    }
}

以上就是服务中心基于eureka的feign调用时传递及获取xid(全局事务编号)的核心代码

<think>我们正在讨论Seata基础类的类名命名建议。根据之前的对话,用户希望获取关于Seata基础类的类名建议。我们需要参考Seata的命名规范以及Java类命名的最佳实践。在Java中,类名通常采用大驼峰命名法(UpperCamelCase),即每个单词的首字母大写,且不使用下划线。类名应当简洁、有意义,能够清晰表达类的职责。考虑到Seata是一个分布式事务解决方案,其基础类可能涉及事务管理、资源协调、通信等模块。我们可以参考已有的Seata模块中的类名,例如:-`GlobalTransactionScanner`-`DefaultCoordinator`-`NettyRemotingServer`根据引用[3],我们注意到Seata的通信模块中有`NettyRemotingServer`这样的类名,它清晰地表达了该类的作用(使用Netty实现的远程通信服务端)。因此,在给出类名建议时,我们应该遵循以下原则:1.类名应使用大驼峰命名法。2.类名应明确表达类的职责。3.尽量保持类名简洁,避免过长。针对基础类,我们可以根据其功能模块给出建议:###事务管理相关-如果有一个类用于管理全局事务,可以命名为`GlobalTransactionManager`。-如果有一个类用于表示事务上下文,可以命名为`TransactionContext`。###资源协调相关-协调者(Coordinator)是Seata中的重要角色,因此可能有`TransactionCoordinator`接口,以及其默认实现`DefaultTransactionCoordinator`。###通信相关-如引用[3]中提到的,通信模块有`NettyRemotingServer`,同样可以有`NettyRemotingClient`。###配置相关-配置类通常以`Config`结尾,例如`TransactionConfig`。###工具类-工具类通常以`Utils`或`Helper`结尾,例如`TransactionUtils`。###异常类-自定义异常通常以`Exception`结尾,例如`TransactionException`。###示例类名根据以上分析,以下是一些建议的类名:1.**事务管理**:-`GlobalTransaction`:表示一个全局事务。-`BranchTransaction`:表示一个分支事务。-`TransactionManager`:事务管理器的接口。-`DefaultTransactionManager`:事务管理器的默认实现。2.**协调者**:-`Coordinator`:协调者接口。-`DefaultCoordinator`:协调者的默认实现(引用[3]中已存在,可作为参考)。3.**资源管理**:-`ResourceManager`:资源管理器接口,用于管理分支事务的资源。-`DefaultResourceManager`:资源管理器的默认实现。4.**通信**:-`RemotingServer`:远程服务端接口。-`RemotingClient`:远程客户端接口。-`NettyRemotingServer`:基于Netty的远程服务端实现(引用[3]中已存在)。-`NettyRemotingClient`:基于Netty的远程客户端实现。5.**配置**:-`SeataConfig`:Seata的全局配置类。-`TransactionConfig`:事务相关的配置。6.**上下文**:-`TransactionContext`:事务上下文,用于传递事务信息。7.**异常**:-`TransactionException`:事务相关异常。8.**工具类**:-`TransactionUtil`:事务相关的工具方法。这些类名符合Java的命名规范,并且能够清晰地表达类的职责。在Seata的实际代码中,我们也可以找到类似的命名,例如引用[3]中提到的`NettyRemotingServer`。此外,值得注意的是,Seata的模块化设计,不同的模块可能有不同的包名,例如:-`io.seata.core.rpc`:通信相关类-`io.seata.core.model`:模型类(如事务、资源等)-`io.seata.core.exception`:异常类因此,在给出类名时,我们也应该考虑包名的组织,但用户问题只要求类名建议,所以我们重点放在类名上。最后,我们还可以参考引用[1]和引用[2]中提到的关于类初始化和类型擦除的内容,确保我们的类设计符合Java语言规范,例如:-静态变量的初始化:在类中声明静态变量时,可以指定初始值或使用静态代码块。-泛型的使用:如果基础类需要使用泛型,应注意类型擦除的影响,例如设计一个泛型配置类:`Config<T>`,但类型擦除后原始类型为`Config`。综上所述,我们给出了针对不同功能模块的类名建议,这些建议符合Java命名规范和Seata的现有命名风格。§§相关问题§§1.Seata中如何设计一个全局事务管理器类?2.Seata通信模块的类设计有哪些要点?3.如何为Seata的配置类设计合理的属性和方法?</think>### Seata基础类类名命名建议 在设计Seata基础类时,类名应遵循 **语义清晰、功能明确、符合规范** 的原则,同时参考Java类命名惯例(大驼峰命名法)和Seata模块化设计思想。以下分类建议供参考: --- #### 1. **核心事务控制类** | 类名 | 功能说明 | |----------------------|--------------------------------------------------------------------------| | `GlobalTransaction` | 全局事务主控类,封装事务生命周期(begin/commit/rollback)[^3] | | `BranchTransaction` | 分支事务操作类,处理分支注册/状态上报 | | `TransactionManager` | 事务协调核心入口,调度全局与分支事务(参考引用[3]通信调度逻辑) | | `TransactionContext` | 事务运行时上下文载体,存储XID、分支ID等 | --- #### 2. **资源与配置管理类** | 类名 | 功能说明 | |--------------------------|--------------------------------------------------------------------------| | `ResourceManager` | 资源管理器基类,对接数据库/消息队列等资源 | | `ConfigurationFactory` | 统一配置加载器,支持文件/配置中心/Nacos等源(参考引用[1]初始化机制) | | `SeataConfig` | 配置项常量类,集中管理参数键名(如`seata.tx.timeout`) | | `RegistryService` | 服务注册发现抽象层,扩展支持Nacos/Eureka/Zookeeper | --- #### 3. **通信与协议类** | 类名 | 功能说明 | |--------------------------|--------------------------------------------------------------------------| | `RpcRemotingClient` | 通信客户端基类(参考引用[3]的`NettyRemotingClient`设计) | | `ProtocolCodec` | 协议编解码器,处理TC/TM/RM间消息序列化 | | `MessagePublisher` | 事务事件发布抽象,支持TCP/RocketMQ等通道 | --- #### 4. **异常与工具类** | 类名 | 功能说明 | |--------------------------|--------------------------------------------------------------------------| | `TransactionException` | 事务异常基类,定义错误码和层级关系 | | `SeataStringUtils` | 扩展工具类,提供事务ID生成等专用方法 | | `CompensableAction` | 补偿动作模板,封装TCC模式下的try/confirm/cancel逻辑 | --- ### 命名注意事项: 1. **避免泛型污染** 如引用[2]所述,泛型类擦除后类型信息丢失。优先使用具体类名(如`BranchTransaction`)而非泛型基类(如`BaseTransaction<T>`)。 2. **体现分层职责** 例如: - `RemoteService`(接口层) - `NettyRemoteServiceImpl`(实现层) - `RemoteServiceProxy`(代理层) 3. **遵循Java初始化规范** 静态配置类需通过静态块初始化(参考引用[1]),如: ```java public class SeataConfig { private static Properties config; static { // 初始化加载配置 } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值