资讯动态

Nacos+Seata Docker化部署实战:微服务注册中心与分布式事务两件套

发布时间:2026/10/18 4:30:19 来源:尧图企业网站定制
做微服务的这几年Nacos和Seata基本是绕不开的两件套。Nacos负责服务注册与配置管理Seata解决分布式事务两个组合起来就是一套挺完整的微服务基础设施。我这次在测试环境用Docker容器方式把它们都搭起来踩了不少坑包括端口不通、事务分组对不上、容器重启配置丢失之类的问题这里整理一份能直接照着干的完整记录。无论是刚接触微服务的新手还是准备在团队里快速搭一套联调环境的老手这篇文章都能帮你省下大半天的摸索时间。1. 选型思考与环境准备1.1 为什么是NacosSeata这套组合先说说选型。现在微服务注册中心可选的有Eureka、Consul、Zookeeper、Nacos配置中心又有Spring Cloud Config、Apollo、Nacos。Nacos一个组件把注册中心和配置中心都干了而且控制台用起来顺手配置热更新、命名空间隔离这些功能都是开箱即用国内团队用的也多遇到问题好查资料。Seata这边目前主流是AT模式业务代码里只需要加个GlobalTransactional注解不需要侵入式地写一堆分布式事务协调逻辑对于大部分业务系统来说是最省事的方案。Seata Server端通过Nacos做注册和配置管理客户端从Nacos拉取配置服务端也把自己注册到Nacos整个链路的数据流是通的。这套组合解决的问题很典型订单服务调用库存服务扣库存库存服务调用积分服务加积分任何一个环节失败前面的操作都要回滚。没有分布式事务方案数据就花了。Nacos保证服务之间找得到彼此Seata保证跨服务调用的数据一致性两个搭配是很成熟的标准组合。1.2 版本规划与Docker环境检查版本选型这块我吃过亏。Nacos和Seata的版本兼容性要注意我自己用的是Nacos 2.3.2 Seata 1.8.0这两个版本组合测试下来比较稳。Nacos 2.x和1.x有个大的区别是新增了gRPC端口如果你的服务还是老版本客户端可能需要额外配置兼容参数。Docker环境检查也比较关键建议先确认一下docker --version docker compose version磁盘空间至少留出3到5G两个镜像加上日志、数据库初始化文件空间太小容易出问题。另外要注意Docker的存储驱动在Linux上默认的overlay2问题不大如果是在Docker Desktop或者某些虚拟化环境里注意给容器多分配一些内存Nacos默认启动就要2G左右的堆内存。1.3 网络规划与端口约定规划端口的时候多想想后面联调排查会省很多事。我建议固定一套自己的端口约定避免每次都要查组件端口说明Nacos8848HTTP主端口控制台、配置读写Nacos gRPC98482.x新增的gRPC通信端口Nacos gRPC984998481客户端gRPC请求端口MySQL3306业务库和Seata依赖的库都在这Seata7091Seata 1.5管理控制台端口Seata8091服务间事务协调端口有人会问为什么Nacos 2.x要额外注意9848端口这里说明一下Nacos 2.x的客户端和服务端通信已经从HTTP切换到了gRPC如果只映射8848老版本项目可能能连上但新版本客户端很可能出现连接失败、注册不上的情况。所以Docker映射时把8848、9848、9849都映射出来省得后面抓瞎。2. Nacos容器搭建与验证2.1 拉取镜像与启动单机模式Nacos有集群模式和单机模式测试环境用单机模式就够了。拉镜像、启动容器我的命令是这样docker pull nacos/nacos-server:v2.3.2 docker run -d \ --name nacos \ -p 8848:8848 \ -p 9848:9848 \ -p 9849:9849 \ -e MODEstandalone \ -e NACOS_AUTH_ENABLEtrue \ -e NACOS_AUTH_IDENTITY_KEYserverIdentity \ -e NACOS_AUTH_IDENTITY_VALUEsecurity \ -e NACOS_AUTH_TOKENVGhpc0lzTXlDdXN0b21TZWNyZXRLZXkwMDE \ nacos/nacos-server:v2.3.2注意几个环境变量的含义。MODEstandalone表示单机模式不是集群模式。NACOS_AUTH_ENABLEtrue开启鉴权这个在生产上是必须的。NACOS_AUTH_TOKEN是JWT令牌的Base64密钥要自己生成一个足够长的字符串不然Nacos会认为密钥强度不够拒绝启动。启动完检查一下日志docker logs -f nacos看到类似Nacos started successfully in xx ms的输出说明启动成功了。2.2 控制台初始化与配置准备容器起来后浏览器访问http://localhost:8848/nacos默认账号密码都是nacos/nacos。第一次登录后建议立刻改掉默认密码这台机器如果是团队公用默认密码就是一个大隐患。登录进去后先把命名空间建好。我习惯按照环境来分dev、test、prod三个命名空间ID不要用默认的自动生成ID而是自己定义一个容易记的比如dev、test、prod。这样在Seata配置里直接指定namespace ID就行不用去查那一长串随机字符串。同时把Seata要用到的配置项提前准备好。Seata的配置中心支持Nacos后我们把service.vgroupMapping、store.mode这些配置放在Nacos配置列表里统一管理后续调整事务分组不用再改配置文件重启服务。配置内容后面会详细讲这里先提一点Nacos作为配置中心dataId需要带分组Seata默认使用SEATA_GROUP这个分组如果你在Nacos里建配置时没注意分组Seata很可能读取不到配置。2.3 验证Nacos是否正常工作验证Nacos工作正常除了看控制台也可以用命令行简单测一下curl -X GET http://localhost:8848/nacos/v1/ns/service/list?pageNo1pageSize10返回JSON数据就说明接口是通的。注册中心这一侧还可以临时启动一个简单服务看看服务列表里能否正常出现不过测试环境的Nacos这时候多半是空的不用着急后面Seata和业务服务注册进来后就能看到了。我在实际部署中遇到过一个情况Docker容器启动成功但外部访问8848一直连接不上。查了半天发现是防火墙问题容器端口映射正常但防火墙没有放行8848、9848端口。这个问题后面汇总在常见问题里细说。3. Seata服务端容器化部署3.1 Seata的部署逻辑与配置中心关系Seata服务端在1.5版本以后重构了控制台端口和功能管理端口变成7091业务端口还是8091。部署Seata的时候核心不是容器怎么跑而是它怎么通过Nacos获取配置、怎么注册到Nacos。Seata的工作逻辑是这样的服务端启动时读取registry.conf决定注册中心和配置中心类型我们把注册中心、配置中心都指向Nacos服务端启动后向Nacos注册自己业务服务通过Nacos发现Seata服务端服务端的配置存储在Nacos配置中心比如事务分组、存储模式等理解了这个逻辑你就知道为什么Seata容器要依赖Nacos部署顺序上必须先有NacosSeata才能正常启动业务连接。3.2 初始化Seata服务端数据库Seata有几种存储模式file、db、redis。测试环境用db模式更接近生产而且事务信息落库方便排查问题。Seata服务端db模式需要三张表global_table、branch_table、lock_table。我用的是MySQL 8建表脚本在Seata源码的script/server/db/mysql.sql里能找到也可以直接从官方文档下载。建表之前创建一个独立的数据库我命名为seata_serverCREATE DATABASE seata_server DEFAULT CHARACTER SET utf8mb4; CREATE TABLE IF NOT EXISTS global_table ( xid varchar(128) NOT NULL, transaction_id bigint(20) DEFAULT NULL, status tinyint(4) NOT NULL, application_id varchar(32) DEFAULT NULL, transaction_service_group varchar(32) DEFAULT NULL, transaction_name varchar(128) DEFAULT NULL, timeout int(11) DEFAULT NULL, begin_time bigint(20) DEFAULT NULL, application_data varchar(2000) DEFAULT NULL, gmt_create datetime DEFAULT NULL, gmt_modified datetime DEFAULT NULL, PRIMARY KEY (xid), KEY idx_status_gmt_modified (status, gmt_modified), KEY idx_transaction_id (transaction_id) ) ENGINE InnoDB DEFAULT CHARSET utf8mb4;branch_table和lock_table也照同样的方式创建。这里有个容易被忽略的点不同的Seata版本表结构可能略有差异如果后面出现元数据错误要去核对建表脚本和版本是否匹配。我自己就遇到过1.6版本的脚本用在1.8版本上启动不报错但事务提交时报字段缺失。3.3 registry.conf配置详解Seata容器内部需要挂载registry.conf文件。先创建一个目录存放配置mkdir -p /opt/seata/config然后编写registry.confregistry { type nacos nacos { application seata-server serverAddr nacos:8848 group SEATA_GROUP namespace dev cluster default username nacos password nacos } } config { type nacos nacos { serverAddr nacos:8848 namespace dev group SEATA_GROUP username nacos password nacos } }这里已经用nacos:8848而不是localhost:8848了因为Seata容器和Nacos容器要在一个Docker网络中通过容器名互通。如果这个文件里写的是localhost容器启动后注册不上Nacos这个问题非常典型很多人第一次部署都会踩到。3.4 Docker网络与容器启动建议创建一个自定义网络让Nacos和Seata用容器名互相访问docker network create microservices-net启动Nacos的时候加上网络参数。如果已经启动了Nacos可以用docker network connect microservices-net nacos然后启动Seata容器docker pull seataio/seata-server:1.8.0 docker run -d \ --name seata-server \ --network microservices-net \ -p 8091:8091 \ -p 7091:7091 \ -e SEATA_IP127.0.0.1 \ -v /opt/seata/config/registry.conf:/seata-server/resources/registry.conf \ -v /opt/seata/logs:/root/logs \ seataio/seata-server:1.8.0注意SEATA_IP这个环境变量它决定了Seata服务端注册到Nacos的IP地址。测试环境填宿主机IP就行。如果在服务器部署就填服务器IP不要填容器内网IP否则别的机器上的业务服务拿到这个容器内网IP根本连不上。启动后观察日志docker logs -f seata-server正常会看到类似Server started successfully的日志同时可以回到Nacos控制台在服务列表里找到seata-server这个服务说明注册成功了。3.5 Seata控制台密码与权限Seata 1.8.0的管理控制台默认访问地址是http://localhost:7091首次登录需要设置一个自定义用户名和密码。控制台可以看到全局事务、分支事务的实时状态排查分布式事务问题非常方便。控制台的账号密码可以配置环境变量来预设-e CONSOLE_USER_NAMEseata \ -e CONSOLE_USER_PASSWORDseata123456 \如果不配置每次进入控制台都要手动设置。容器重建后这个设置会丢失所以最好在启动命令里固定下来。4. 客户端接入与配置中心完整配置4.1 业务数据库准备undo_log表Seata AT模式的核心机制是业务数据操作前后生成undo_log事务回滚时靠undo_log恢复数据。所以每个参与分布式事务的业务库都必须创建undo_log表。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), KEY ux_undo_log (xid, branch_id) ) ENGINE InnoDB AUTO_INCREMENT 1 DEFAULT CHARSET utf8mb4;如果业务服务连接了多个库每个库都要建这张表。常见的坑是只给主库建了undo_log表从库没建事务执行到从库操作时报错“Table undo_log doesnt exist”然后整体回滚。4.2 Nacos配置中心写入Seata配置Seata客户端启动时会根据registry.conf从Nacos配置中心拉取配置最核心的配置是下面这些配置key示例值说明service.vgroupMapping.my_test_tx_groupdefault事务分组映射key是事务分组名值是Seata集群名service.default.grouplist127.0.0.1:8091直连Seata服务端地址注册中心模式下可不配store.modedb事务存储模式store.db.datasourcedruid数据源类型store.db.dbTypemysql数据库类型store.db.urljdbc:mysql://127.0.0.1:3306/seata_server数据库连接store.db.userroot数据库账号store.db.password123456数据库密码在Nacos控制台里创建配置时注意两点dataId建议命名为seata.properties分组必须是SEATA_GROUP命名空间选择你之前建好的dev。创建好以后Seata客户端和服务端都能从Nacos拉取到这套配置。这里说下事务分组的重要性业务服务配置的tx-service-group要和service.vgroupMapping.{groupName}里的key对应上。比如你业务服务里配置的是my_test_tx_group但Nacos配置中心里写的是service.vgroupMapping.demo_tx_group那客户端根本找不到对应的Seata服务端地址事务全部失效。4.3 业务服务application.yml接入参数业务服务接入时引入依赖后主要配置这些内容spring: application: name: order-service cloud: nacos: discovery: server-addr: localhost:8848 namespace: dev config: server-addr: localhost:8848 namespace: dev group: SEATA_GROUP file-extension: yml seata: enabled: true application-id: order-service tx-service-group: my_test_tx_group registry: type: nacos nacos: server-addr: localhost:8848 namespace: dev group: SEATA_GROUP config: type: nacos nacos: server-addr: localhost:8848 namespace: dev group: SEATA_GROUP注意几个关键点tx-service-group这个名字是自定义的但必须和Nacos里的vgroupMapping配置对应。registry.nacos.namespace要和Nacos里建的命名空间ID一致。如果你用了dev这个命名空间ID那这里就写dev。4.4 注解使用与事务边界业务代码中使用方式很简单在分布式事务的入口方法上加注解GlobalTransactional(rollbackFor Exception.class) public void createOrder(OrderDTO order) { // 调用库存服务扣库存 stockService.deductStock(order.getSkuId(), order.getCount()); // 调用积分服务加积分 pointService.addPoint(order.getUserId(), order.getPoint()); // 本地业务逻辑 orderMapper.insert(order); }需要注意的是GlobalTransactional加在事务发起方也就是第一个调用链的入口方法上。被调用的下游服务方法上不需要再加但是下游方法如果想要本地事务控制可以保留Transactional注解。还有一点分布式事务的时间跨度比本地事务长数据库连接资源占用也更久高并发场景下连接池参数要适当调大不然容易出现连接池耗尽。5. 常见问题与排查实录5.1 Nacos容器启动失败或内存不足症状docker logs nacos显示内存不足或者容器反复重启。原因Nacos默认JVM参数较大普通开发机内存不够。解决方法是通过环境变量调整-e JVM_XMS256m -e JVM_XMX512m另外也可能和NACOS_AUTH_TOKEN有关系如果你自定义了这个值要确保Base64解码后长度满足要求。我遇到过一次启动停滞最后发现是自定义密钥太短Nacos直接拒绝认证模块初始化换成正常长度的密钥就解决了。5.2 Seata注册不到Nacos症状Nacos服务列表里找不到seata-server。排查顺序先看Seata日志看registry.conf是否被正确加载有没有报nacos registry init失败。确认Seata容器和Nacos容器网络互通在Seata容器里执行docker exec -it seata-server ping nacos如果ping不通多半是容器网络没配置检查启动时--network参数。确认registry.conf里的namespace存在。如果指定了不存在的命名空间注册不会报错但服务列表里看不到。换一个思路验证临时把namespace改成空字符串如果能注册成功说明问题出在命名空间不匹配上。5.3 事务不生效的定位方法事务不生效是分布式事务最让人头疼的问题因为业务代码不报错但实际没有全局事务效果。我分享几个定位方法。第一看Seata控制台的全局事务列表。如果控制台里根本没有任何事务记录说明客户端没连上服务端检查事务分组和registry配置。第二看业务服务日志有没有Begin new global transaction这类输出。如果连这行日志都没有说明GlobalTransactional注解可能没生效检查Seata依赖是否正确引入SpringBoot启动类上是否扫描了相关包。第三确认是不是有自调用绕过代理。Seata基于Spring AOP实现事务增强同一个类里的方法调用不会走代理比如订单服务里一个方法调用同一个类的另一个方法后者加了GlobalTransactional这时事务不会生效。解决方法把方法拆分到不同bean中或者通过代理对象调用。第四检查数据源代理。Seata AT模式要求使用它提供的DataSourceProxy代理数据源。引入Seata依赖后大部分情况会自动装配但是如果配置了多数据源要手动确保每个数据源都被代理了。5.4 端口与网络互通问题很多问题表面上是配置问题实际上都是网络问题。部署在宿主机上的业务服务要连接Docker里的Nacos注意几点# 查看容器占用的端口 docker port nacos docker port seata-server默认情况下业务服务所在机器要能访问到Nacos的8848、9848端口以及Seata的8091端口。如果这些端口没有在防火墙放行服务注册和事务协调都会失败。配置了代理或者多网卡的机器也要小心。Seata注册到Nacos的SEATA_IP要保证其他机器能访问到这个IP。如果服务器有两个网卡一个内网一个外网你填了错误的网卡IP其他机器通过Nacos拿到这个IP后连不上就会一直报connect timed out。5.5 容器重启后配置丢失Docker容器的文件系统是临时的容器删除重启后容器内修改的内容全部丢失。所以凡是自定义文件比如registry.conf都必须通过挂载卷映射到宿主机。另外Seata日志、Nacos数据目录这些也要挂出来否则容器重启后日志全没了排查问题很被动。我用到的挂载参数整理如下# Nacos -v /opt/nacos/logs:/home/nacos/logs # Seata -v /opt/seata/config/registry.conf:/seata-server/resources/registry.conf -v /opt/seata/logs:/root/logs这里特别提醒如果你要修改registry.conf改宿主机上的文件后需要重启Docker容器才能生效。改完文件忘记重启容器然后一直找不到问题原因这个坑我踩过不止一次。6. 容器化部署经验补充部署完Nacos和Seata业务跑通以后还有一些经验可以分享这些对于长期维护很重要。卷挂载和配置备份我建议做成标准操作。Nacos的配置数据默认存在容器内置的Derby数据库中单机模式下如果容器删除所有配置就丢了。虽然测试环境问题不大但养成把数据卷挂出来的习惯后面切生产少踩坑。另外我通常会在部署文档里固定一套检查清单每次环境出问题按清单过一遍比到处翻日志高效很多。这套检查清单包括Nacos健康检查地址是否200、Nacos服务列表是否包含seata-server、业务服务日志是否出现全局事务启动记录、数据库undo_log表是否存在且字段完整、Seata控制台能否看到事务记录。还有一点值得提升级Seata版本时要谨慎。小版本升级通常平滑但跨大版本可能会有兼容问题。我在测试环境升级过一次从1.6到1.8配置中心里的事务分组配置格式有变化导致老客户端报错最后只能把Nacos里的配置调整后才恢复。所以在生产环境升级之前一定要在测试环境完整跑一遍核心业务链路。我在实际使用中还有个体会Seata管理控制台7091端口在1.8版本已经比较完善事务列表刷新、全局锁查看都很好用。事务调试时优先用控制台观察而不是盲目查日志。控制台能看到全局事务的xid、状态、耗时对定位问题帮助很大。最后再分享一个使用技巧如果你只是验证Nacos和Seata连通性不需要急着把业务服务接进来。可以先用Seata自带的一些脚本模拟事务链路确认服务端、配置中心、数据库这层都通了再接入业务代码这样排查范围会小很多。按这个思路操作下来整套环境搭建基本能一次跑通。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑