Skip to content

DDK Seata Starter ​

基于 Seata 的分布式事务。DDK 额外补上 Seata 缺的一半:出站 HTTP 调用携带全局事务 XID,下游服务才能加入同一个全局事务。

能做什么 ​

text
order-service                                        inventory-service
  @GlobalTransactional placeOrder
    RootContext.getXID() = 10.0.0.1:8091:42
    inventoryClient.post("/deduct")
      XidPropagationInterceptor            (DDK)
        TX_XID: 10.0.0.1:8091:42   ──── HTTP ────►  JakartaTransactionPropagationInterceptor  (Seata)
                                                      RootContext.bind(xid)
                                                      deduct() 登记在同一个全局事务下

Seata 只处理入站:从 TX_XID 请求头取出 XID 绑定到当前线程。出站调用不带这个头时,下游在全局事务之外各自提交,全局回滚撤不回来,而且没有任何报错。

能力提供方
数据源代理(AT 模式)、@GlobalTransactional 扫描seata-spring-boot-starter
入站请求绑定 XIDseata-spring-boot-starter
出站 RestClient / RestTemplate 携带 XID本 starter

引入方式 ​

xml
<dependency>
    <groupId>com.ddk</groupId>
    <artifactId>ddk-seata-starter</artifactId>
    <version>${ddk.version}</version>
</dependency>

传递引入 seata-spring-boot-starter(版本由根 pom 管理)与 spring-boot-starter-jdbc。Seata 自身用 seata.* 配置:

yaml
seata:
  application-id: order-service
  tx-service-group: default_tx_group
  service:
    vgroup-mapping:
      default_tx_group: default
    grouplist:
      default: 127.0.0.1:8091

从容器注入 builder 构建 HTTP 客户端,拦截器自动生效:

java
@Bean
RestClient inventoryClient(RestClient.Builder builder) {
    return builder.baseUrl("http://inventory-service").build();
}

配置项 ​

配置项类型默认值说明
ddk.seata.http-propagation.enabledbooleantrue出站 RestClient / RestTemplate 调用是否携带 TX_XID
seata.enabledbooleantrueSeata 自身的开关,关闭时 DDK 的补充一并关闭

装配条件与降级行为 ​

  • 自动配置类:com.ddk.seata.starter.config.DdkSeataAutoConfiguration。
  • 条件:classpath 有 Seata、seata.enabled 不为 false;HTTP 传播还要求 classpath 有 spring-web 且 ddk.seata.http-propagation.enabled 不为 false。
  • 注册 RestClientCustomizer 与 RestTemplateCustomizer,挂到容器提供的 RestClient.Builder / RestTemplateBuilder 上。
  • 只在全局事务内写头;调用方显式设置了 TX_XID 时不覆盖。请求头名取 RootContext.KEY_XID,与 Seata 入站拦截器是同一个常量。

不适用的场景 / 已知问题 ​

  1. 绕过 builder 创建的客户端不传播。new RestTemplate()、RestClient.create()、手写的 HttpClient 需要自己加 XidPropagationInterceptor。
  2. 只覆盖 RestClient / RestTemplate。WebClient、OpenFeign、消息队列的 XID 传播没有提供。
  3. Seata 核心 Bean 没有单元测试覆盖。GlobalTransactionScanner 依赖 spring.factories 里的 ApplicationContextInitializer,ApplicationContextRunner 不执行它;数据源代理与真实回滚需要 @SpringBootTest 加可达的 TC 做集成测试。
  4. 与 DDK DB Starter 的组合未验证。Seata 的数据源自动代理会作用于容器里所有 DataSource,多数据源场景下的行为没有测试覆盖。
  5. XA / TCC / SAGA 模式没有额外辅助,模式选择与补偿逻辑由业务自己实现。

文章以 CC BY-NC-SA 4.0 授权 · 代码片段以 MIT 授权