Loading

Seata 1.8.0 Docker 部署方案(MySQL 存储 + Nacos 鉴权)

Seata 1.8.0 Docker 部署方案(MySQL 存储 + Nacos 鉴权)

0. 版本与组件说明

  • 服务端镜像:seataio/seata-server:1.8.0(Seata 1.x 末版官方镜像,基于 openjdk8)
  • 端口:8091(TC 通信,Netty)、7091(管控台 HTTP,1.5+ 引入)
  • 存储:MySQL(store.mode=db
  • 注册中心:Nacos(type=nacos)
  • 配置中心:Nacos(type=nacos,data-id 推荐 seata.properties
  • 安全:1.8.0 控制台默认账号 seata/seata,本方案在 application.yml 中覆盖为自定义账号

部署架构

flowchart LR Client[业务微服务<br/>seata-client] subgraph Host[Linux 宿主机 SERVER_IP] Docker[seataio/seata-server:1.8.0<br/>8091 TC / 7091 Console] end Nacos[(Nacos<br/>注册 + 配置中心)] MySQL[(MySQL<br/>seata_server)] Docker -->|注册| Nacos Docker -->|读取配置| Nacos Docker -->|持久化全局/分支/锁| MySQL Client -->|获取地址| Nacos Client -->|TC RPC 8091| Docker

1. 环境准备

mkdir -p /data/seata/{conf,logs}
cd /data/seata

docker --version

ss -lnt | egrep '8091|7091' || echo "8091/7091 currently free"

如启用了 firewalld(云服务器还要同时在腾讯云控制台安全组放行):

firewall-cmd --permanent --add-port=8091/tcp
firewall-cmd --permanent --add-port=7091/tcp
firewall-cmd --reload

2. 初始化 MySQL(服务端存储)

在已有 MySQL 中创建数据库与 4 张服务端表(来自 Seata 官方 script/server/db/mysql.sql):

CREATE DATABASE IF NOT EXISTS seata_server
  DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

USE seata_server;

-- 全局事务表
CREATE TABLE IF NOT EXISTS `global_table` (
  `xid` VARCHAR(128) NOT NULL,
  `transaction_id` BIGINT,
  `status` TINYINT NOT NULL,
  `application_id` VARCHAR(32),
  `transaction_service_group` VARCHAR(32),
  `transaction_name` VARCHAR(128),
  `timeout` INT,
  `begin_time` BIGINT,
  `application_data` VARCHAR(2000),
  `gmt_create` DATETIME,
  `gmt_modified` DATETIME,
  PRIMARY KEY (`xid`),
  KEY `idx_status_gmt_modified` (`status`, `gmt_modified`),
  KEY `idx_transaction_id` (`transaction_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 分支事务表
CREATE TABLE IF NOT EXISTS `branch_table` (
  `branch_id` BIGINT NOT NULL,
  `xid` VARCHAR(128) NOT NULL,
  `transaction_id` BIGINT,
  `resource_group_id` VARCHAR(32),
  `resource_id` VARCHAR(256),
  `branch_type` VARCHAR(8),
  `status` TINYINT,
  `client_id` VARCHAR(64),
  `application_data` VARCHAR(2000),
  `gmt_create` DATETIME(6),
  `gmt_modified` DATETIME(6),
  PRIMARY KEY (`branch_id`),
  KEY `idx_xid` (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 全局锁表
CREATE TABLE IF NOT EXISTS `lock_table` (
  `row_key` VARCHAR(128) NOT NULL,
  `xid` VARCHAR(128),
  `transaction_id` BIGINT,
  `branch_id` BIGINT NOT NULL,
  `resource_id` VARCHAR(256),
  `table_name` VARCHAR(32),
  `pk` VARCHAR(36),
  `status` TINYINT NOT NULL DEFAULT 0 COMMENT '0:locked,1:rollbacking',
  `gmt_create` DATETIME,
  `gmt_modified` DATETIME,
  PRIMARY KEY (`row_key`),
  KEY `idx_status` (`status`),
  KEY `idx_branch_id` (`branch_id`),
  KEY `idx_xid` (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- HA 分布式锁
CREATE TABLE IF NOT EXISTS `distributed_lock` (
  `lock_key` CHAR(20) NOT NULL,
  `lock_value` VARCHAR(20) NOT NULL,
  `expire` BIGINT,
  PRIMARY KEY (`lock_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT IGNORE INTO `distributed_lock` (lock_key, lock_value, expire) VALUES
 ('AsyncCommitting','',0),('RetryCommitting','',0),
 ('RetryRollbacking','',0),('TxTimeoutCheck','',0);

业务侧(每个被 AT 模式管理的业务库)还需要 undo_log 表 —— 等接入客户端时再加,本次不在部署范围。

3. 准备 application.yml(注册中心 + 安全 + 指向配置中心)

文件路径:/data/seata/conf/application.yml

server:
  port: 7091

spring:
  application:
    name: seata-server

logging:
  config: classpath:logback-spring.xml
  file:
    path: ${user.home}/logs/seata
  extend:
    logstash-appender:
      destination: 127.0.0.1:4560
    kafka-appender:
      bootstrap-servers: 127.0.0.1:9092
      topic: logback_to_logstash

console:
  user:
    username: <SEATA_CONSOLE_USER>
    password: <SEATA_CONSOLE_PWD>

seata:
  config:
    type: nacos
    nacos:
      server-addr: <NACOS_IP>:8848
      namespace: <NACOS_NAMESPACE_ID>
      group: <NACOS_GROUP>
      username: <NACOS_USER>
      password: <NACOS_PWD>
      data-id: seataServer.properties
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: <NACOS_IP>:8848
      group: <NACOS_GROUP>
      namespace: <NACOS_NAMESPACE_ID>
      cluster: default
      username: <NACOS_USER>
      password: <NACOS_PWD>
  security:
    secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
    tokenValidityInMilliseconds: 1800000
    ignore:
      urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/**/*.woff,/**/*.woff2,/api/v1/auth/login

要点:

  • seata.config.type=nacos + data-id=seataServer.properties,所有存储/事务组等业务配置都从 Nacos 拉取
  • 控制台账号通过 console.user.username/password 覆盖默认 seata/seata(建议改成自定义强密码)
  • secretKey 仅作为本地控制台 JWT 签名,请在生产环境改成随机长串
  • **ignore.urls 末尾必须是 /api/v1/auth/login(Seata 1.8.0 控制台登录接口的真实路径)。

4. 推送 Seata 业务配置到 Nacos

在 Nacos 控制台(命名空间 <NACOS_NAMESPACE_ID>、分组 <NACOS_GROUP>)新建配置:

  • Data ID:seata.properties
  • 格式:Properties
  • 内容:
# ---- 存储模式 ----
store.mode=db
store.lock.mode=db
store.session.mode=db

# ---- 公共连接池 ----
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://<MYSQL_HOST>:3306/seata_server?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
store.db.user=<MYSQL_USER>
store.db.password=<MYSQL_PWD>
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.distributedLockTable=distributed_lock
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000

# ---- 服务端事务 ----
server.recovery.committingRetryPeriod=1000
server.recovery.asynCommittingRetryPeriod=1000
server.recovery.rollbackingRetryPeriod=1000
server.recovery.timeoutRetryPeriod=1000
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1
server.rollbackRetryTimeoutUnlockEnable=false
server.distributedLockExpireTime=10000
server.xaerNotaRetryTimeout=60000
server.session.branchAsyncQueueSize=5000
server.session.enableBranchAsyncRemove=false

# ---- 事务分组映射(业务侧使用) ----
# 业务方 spring.cloud.alibaba.seata.tx-service-group=mall_tx_group
# 这里需要把组名映射到上面 registry 注册的 cluster(默认 default)
service.vgroupMapping.fsymall_tx_group=default
service.default.grouplist=<SERVER_IP>:8091
service.enableDegrade=false
service.disableGlobalTransaction=false

# ---- 客户端默认参数 ----
client.rm.asyncCommitBufferLimit=10000
client.rm.lock.retryInterval=10
client.rm.lock.retryTimes=30
client.rm.lock.retryPolicyBranchRollbackOnConflict=true
client.rm.reportRetryCount=5
client.rm.tableMetaCheckEnable=true
client.rm.sqlParserType=druid
client.tm.commitRetryCount=5
client.tm.rollbackRetryCount=5
client.undo.dataValidation=true
client.undo.logSerialization=jackson
client.undo.onlyCareUpdateColumns=true
client.undo.logTable=undo_log
log.exceptionRate=100

业务侧的事务组名 mall_tx_group 之后接入时用,本次仅占位。

5. 启动 Seata Docker 容器

docker pull seataio/seata-server:1.8.0

docker run -d --name seata \
  --restart=always \
  -p 8091:8091 \
  -p 7091:7091 \
  -e SEATA_IP=42.194.214.28 \
  -e SEATA_PORT=8091 \
  -v /data/seata/conf/application.yml:/seata-server/resources/application.yml \
  -v /data/seata/logs:/root/logs/seata \
  seataio/seata-server:1.8.0

要点(这一步坑较多,请仔细看):

  • SEATA_IP 必须填能被业务微服务访问到的地址(同 VPC 内填内网 IP,跨 VPC 填公网/NAT 后地址)。否则注册到 Nacos 的是容器内 IP(如 172.x.x.x),客户端连不通。
  • 不要使用 -e SEATA_CONFIG_NAME=...。该环境变量是 1.x 早期为 registry.conf(HOCON 格式)设计的,内部会拼 .conf 后缀加载,对 1.5+ 的 application.yml 不生效,会静默回退到镜像内置默认配置。社区已知问题:apache/incubator-seata#7053
  • 覆盖 application.yml 的正确方式是 单文件挂载覆盖镜像内默认文件-v /data/seata/conf/application.yml:/seata-server/resources/application.yml
  • 不要-v /data/seata/conf:/seata-server/resources(目录对目录覆盖),因为镜像内 /seata-server/resources/ 下还有 logback-spring.xmlMETA-INF/services/ 等文件,目录挂载会把它们一起遮蔽掉,导致日志或 SPI 失效。
  • 不要把 STORE_MODE=db 用环境变量传 —— 我们走 Nacos 配置中心,统一在 seata.properties 中控制。

启动后立即验证生效的配置:

docker exec seata cat /seata-server/resources/application.yml | head -40

应当能看到你写的 console.user.username/passwordseata.config/registry 的 Nacos 配置,而不是镜像默认值。

6. 验证

docker logs -f --tail 200 seata

预期日志关键字:

  • Server started, service listen port: 8091
  • register TC successRegistryService is selected: NacosRegistryServiceImpl
  • 无 MySQL 连接异常、无 Nacos 401/403

其他验证:

  • 浏览器访问 http://<SERVER_IP>:7091,使用 <SEATA_CONSOLE_USER>/<SEATA_CONSOLE_PWD> 登录
  • Nacos 控制台 → 服务管理 → 服务列表(对应命名空间和分组)能看到 seata-server
  • MySQL seata_server 库表保持空状态即正常(有事务时才写入)

7. 常见问题排查清单

  • 客户端报 no available service 'default' found, please make sure registry config correct:检查 service.vgroupMapping.xxx 与客户端 tx-service-group 是否一致,以及 Nacos 命名空间/分组是否一致。
  • 容器启动后立刻退出:多半是 application.yml 解析失败或 Nacos 鉴权失败,看 docker logs
  • Nacos 列表里 IP 是 172.x 容器内网 IP:忘记设置 SEATA_IP
  • MySQL 报 Public Key Retrieval is not allowed:连接串加 allowPublicKeyRetrieval=true(方案中已带)。
  • 控制台 7091 打不开 / 401:1.8.0 默认账号是 seata/seata,本方案在 application.yml 中已覆盖,请使用 <SEATA_CONSOLE_USER>/<SEATA_CONSOLE_PWD> 登录。
  • 控制台仍然用默认 seata/seata 能登录、自己设的密码无效:典型表现是改了 application.yml 但未生效。原因是 SEATA_CONFIG_NAMEapplication.yml 不生效(见第 5 步要点)。修复:去掉 SEATA_CONFIG_NAME,改用 -v /data/seata/conf/application.yml:/seata-server/resources/application.yml 单文件挂载,重建容器。
  • 控制台输入正确账号密码点登录后返回 401:浏览器 POST /api/v1/auth/login 直接 401,服务端日志 JwtAuthenticationEntryPoint: Full authentication is required to access this resource。原因是 seata.security.ignore.urls 末尾写成了 /login,而 Seata 1.8.0 登录接口实际是 /api/v1/auth/login,登录请求自己被 JWT 过滤器拦了。修复:把 application.ymlignore.urls 末尾改为 /api/v1/auth/login,然后 docker restart seata
  • 客户端启动报 can not get cluster name in registry config 'service.vgroupMapping.xxx':在 Nacos 的 seataServer.properties 中没找到该事务组映射,注意客户端读取的 group 也得和服务端一致。
  • 浏览器换密码后还能用旧密码登录:浏览器仍持有旧 JWT,无痕窗口或清缓存再试。

8. 卸载/重置(如需)

docker rm -f seata
# 重建表
mysql -h <MYSQL_HOST> -u <MYSQL_USER> -p -e "DROP DATABASE seata_server;"
posted @ 2026-05-21 11:28  多久会在  阅读(46)  评论(0)    收藏  举报