Configuración Detallada de Seata AT con Nacos en Proyectos Spring Boot

La integración de Seata en su modo AT para gestionar transacciones distribuidas, utilizando Nacos como centro de registro y configuración, es una estrategia robusta para aplicaciones Spring Boot. Esta guía proporciona una configuración completa y práctica, optimizada para entornos modernos (Spring Boot 3.x, Spring Cloud Alibaba 2023.x, Seata 2.0.0+, Nacos 2.x).

Arquitectura General

  • TC (Transaction Coordinator): El servidor de Seata, encargado de orquestar las transacciones globales.
  • TM (Transaction Manager): El servicio que inicia la transacción global (e.g., servicio de pedidos), marcado con la anotación @GlobalTransactional.
  • RM (Resource Manager): Los servicios que participan en las ramas de la transacción (e.g., serviicos de inventario, pagos), los cuales se registran automáticamente en el TC.
  • Nacos: Actúa simultáneamente como servicio de registro y centro de configuración.
  • Modo AT: Emplea un proxy de base de datos (DataSourceProxy) para generar automáticamente registros de reversión (undo_log) y facilitar la anulación de transacciones.

Requisitos Previos y Versiones Recomendadas

Componente Versión Sugerida
JDK 17
Maven 3.8+
MySQL 8.0
Nacos 2.2.x ~ 2.3.x
Seata Server 2.0.0
Spring Boot 3.2.x
Spring Cloud Alibaba 2023.0.1.0

Nota importante: A partir de Seata 2.0.0, se recomienda configurar Seata mediante application.yml, eliminando la dependencia de archivos como registry.conf y file.conf.

Despliegue del Servidor Seata (TC)

1. Descarga y Extracción del Servidor Seata


wget https://github.com/seata/seata/releases/download/v2.0.0/seata-server-2.0.0.tar.gz
tar -zxvf seata-server-2.0.0.tar.gz

2. Inicialización de la Base de Datos de Seata

Cree la base de datos seata en su servidor MySQL y ejecute los scripts SQL proporcionados:


-- Ubicación del script: seata/script/server/db/mysql.sql
CREATE DATABASE seata;
USE seata;
-- Ejecute el contenido de mysql.sql para crear las tablas: global_table, branch_table, lock_table

3. Configuración de seata/conf/application.yml


seata:
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848 # Dirección de Nacos
      group: SEATA_GROUP
      namespace: ""  # O especifique su ID de Namespace
      username: nacos
      password: nacos
      data-id: seataServer.properties  # Nombre del archivo de configuración en Nacos
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      namespace: ""
      cluster: default
      username: nacos
      password: nacos
  store:
    mode: db
    db:
      datasource: druid
      db-type: mysql
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
      user: root
      password: your_mysql_password

4. Creación del Archivo seataServer.properties en Nacos

En el panel de Nacos, cree un nuevo archivo de configuración:

  • Data ID: seataServer.properties
  • Group: SEATA_GROUP

Contenido de ejemplo:


store.mode=db
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
store.db.user=root
store.db.password=your_mysql_password

5. Inicio del Servidor Seata


cd seata/bin
./seata-server.sh -h 127.0.0.1 -p 8091 -m db

Tras el inicio, verifique en la consola de Nacos que el servicio seata-server se haya registrado correctamente.

Configuración de Microservicios Spring Boot (TM / RM)

A continuación, se muestra la configuración para el servicio de pedidos (order-service). Los servicios de inventario (stock-service) y pago (payment-service) se configuran de manera similar.

1. Dependencias Maven (pom.xml)


<dependencies>
    <!-- Web Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Nacos Discovery -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        <version>2023.0.1.0</version>
    </dependency>

    <!-- Seata Starter -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
        <version>2023.0.1.0</version>
    </dependency>

    <!-- MySQL Connector & MyBatis -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
    </dependency>
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>3.0.3</version>
    </dependency>
</dependencies>

2. Configuración de application.yml


spring:
  application:
    name: order-service
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        username: nacos
        password: nacos

seata:
  enabled: true
  application-id: ${spring.application.name}
  tx-service-group: my_tx_group  # IMPORTANTE: Debe coincidir con vgroup-mapping
  data-source-proxy-mode: AT
  enable-auto-data-source-proxy: false  # Recomendado para un control manual más preciso
  registry:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      namespace: ""
      username: nacos
      password: nacos
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      namespace: ""
      username: nacos
      password: nacos
      data-id: seataServer.properties # Debe coincidir con el archivo de configuración del TC
  service:
    vgroup-mapping:
      my_tx_group: default  # Debe coincidir con tx-service-group
    # grouplist: # A partir de Seata 2.0+, la resolución se hace vía Nacos, esta sección puede omitirse
    #   default: 127.0.0.1:8091

Establecer enable-auto-data-source-proxy: false permite la configuración manual del DataSourceProxy, crucial para evitar conflictos, especialmente con múltiples fuentes de datos.

3. Creación Manual del Proxy de DataSource (Paso Clave)

Es fundamental envolver su fuente de datos original con DataSourceProxy para que Seata pueda interceptar las operaciones SQL y generar los registros de reversión:


@Configuration
public class SeataDataSourceConfig {

    @Bean
    @ConfigurationProperties("spring.datasource") // Asegúrese de que coincida con su configuración de datasource
    public DruidDataSource druidDataSource() {
        return new DruidDataSource();
    }

    @Primary // Si tiene múltiples DataSources, marque el principal
    @Bean("dataSource") // Nombre del bean
    public DataSource dataSource(DruidDataSource druidDataSource) {
        return new DataSourceProxy(druidDataSource);
    }
}

4. Creación de la Tabla undo_log en Cada Base de Datos de Microservicio

Cada base de datos utilizada por los microservicios que participan en transacciones distribuidas debe contener la tabla undo_log:


-- Ejecutar en cada base de datos de negocio (e.g., order_db, stock_db, payment_db)
CREATE TABLE `undo_log` (
  `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
  `branch_id` BIGINT(20) NOT NULL,
  `xid` VARCHAR(100) NOT NULL,
  `context` VARCHAR(128) NOT NULL,
  `rollback_info` LONGBLOB NOT NULL,
  `log_status` INT(11) NOT NULL,
  `log_created` DATETIME NOT NULL,
  `log_modified` DATETIME NOT NULL,
  `ext` VARCHAR(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;

Implementación del Código de Transacción Distribuida

TM (Lado del Iniciador - Servicio de Pedidos)

Utilice la anotación @GlobalTransactional para marcar los métodos que inician una transacción distribuida:


@RestController
public class OrderController {

    @Autowired
    private OrderService orderService;

    @PostMapping("/createOrder")
    @GlobalTransactional(name = "create-order-tx", rollbackFor = Exception.class)
    public String createOrder(@RequestBody OrderDTO dto) {
        // Llama a los servicios de stock y pago internamente
        orderService.createOrder(dto);
        return "success";
    }
}

RM (Lado del Participante - Servicios de Stock/Pago)

Los servicios participantes solo necesitan usar la anotación estándar @Transactional de Spring. Seata interceptará estas transacciones automáticamente:


@Service
public class StockService {

    @Transactional // Seata interceptará esta transacción
    public void deductStock(Long productId, Integer count) {
        // Lógica para deducir el inventario
        stockMapper.updateStock(productId, count);
        // Simulación de fallo: throw new RuntimeException("Stock insuficiente");
    }
}

Verificación y Depuración

  1. Orden de Inicio:
    • Inicie Nacos.
    • Inicie el servidor Seata (TC).
    • Inicie todos sus microservicios.
  2. Puntos de Verificación:
    • Nacos Console: Verifique que seata-server y todos los microservicios estén registrados.
    • Bases de Datos: Confirme la existencia de la tabla undo_log en las bases de datos de negocio.
    • Logs: Revise los logs del cliente Seata para asegurar la conexión con el TC.
  3. Escenarios de Prueba:
    • Flujo Normal: Ejecute una transacción completa y observe que todas las operaciones se confirmen.
    • Flujo con Fallo: Simule un error en uno de los servicios (e.g., falta de stock) y observe que la transacción completa se revierta. Verifique que undo_log se limpie correctamente.

Solución de Problemas Comunes

Problema Solución
No available service 'default' Asegúrese de que tx-service-group en el cliente coincida exactamente con la clave en vgroup-mapping de la configuración de Seata.
Conexión fallida al Servidor Seata Verifique que seata-server esté activo en Nacos y que el puerto 8091 (o el configurado) sea accesible.
undo_log no se genera Confirme que está utilizando DataSourceProxy y que los métodos participantes tienen la anotación @Transactional.
Configuración de Seata 2.0.0 no se aplica Asegúrese de haber eliminado las configuraciones de registry.conf y file.conf, y de que toda la configuración se realice a través de application.yml y Nacos.

Al seguir estos pasos, habrá integrado exitosamente Seata AT con Nacos en sus proyectos Spring Boot, logrando consistencia transaccional distribuida. Los puntos clave a recordar son:

  • Configurar el registro y la configuración del Servidor Seata a través de Nacos.
  • Proxy manual de DataSource en los clientes.
  • Crear la tabla undo_log en cada base de datos de negocio.
  • Usar @GlobalTransactional en el TM y @Transactional estándar en los RM.

Para arquitecturas más complejas, considere la configuración de alta disponibilidad para el TC y el uso de múltiples namespaces en Nacos.

Etiquetas: seata at-mode spring-boot nacos distributed-transactions

Publicado el 6-29 08:11