天天看点

【BUG记录】spring cloud 集成seata的时候:can not register RM,err:can not connect to services-server.

BUG背景

我在部署seata-server,也就是seata的服务端的时候,使用了nacos 做为注册中心和配置中心,并使用的是docker 来部署的seata-server。如下博客

​​Docker 部署 Seata Server(使用nacos 做为注册中心和配置中心)​​

然后我使用spring cloud 结合使用seata来做分布式事务。但是却出现了如下错误

【BUG记录】spring cloud 集成seata的时候:can not register RM,err:can not connect to services-server.

我截取了部分日志出来,可见seata 内置netty来实现网络通信,8091也正是seata-server的端口,根据如下日志可知我们客户端程序连接不上172.17.0.4:8091

2022-02-18 17:03:07.724 ERROR 26860 --- [eoutChecker_2_1] i.s.c.r.netty.NettyClientChannelManager  : 0101 can not connect to 172.17.0.4:8091 cause:can not register RM,err:can not connect to services-server.

io.seata.common.exception.FrameworkException: can not register RM,err:can not connect to services-server.
  at io.seata.core.rpc.netty.NettyClientChannelManager.doConnect(NettyClientChannelManager.java:210) ~[seata-all-1.3.0.jar:1.3.0]
  at io.seata.core.rpc.netty.NettyClientChannelManager.acquireChannel(NettyClientChannelManager.java:103) ~[seata-all-1.3.0.jar:1.3.0]
  at io.seata.core.rpc.netty.NettyClientChannelManager.reconnect(NettyClientChannelManager.java:175) ~[seata-all-1.3.0.jar:1.3.0]
  at io.seata.core.rpc.netty.AbstractNettyRemotingClient$1.run(AbstractNettyRemotingClient.java:106) [seata-all-1.3.0.jar:1.3.0]
  at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_301]
  at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) [na:1.8.0_301]
  at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_301]
  at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) [na:1.8.0_301]
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_301]
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_301]
  at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) [netty-all-4.1.51.Final.jar:4.1.51.Final]
  at java.lang.Thread.run(Thread.java:748) [na:1.8.0_301]      

而这个地址172.17.0.4:8091正是seata-server的地址,如下所示,但是我们访问不到,这是为什么

nacos 的注册中心信息图

【BUG记录】spring cloud 集成seata的时候:can not register RM,err:can not connect to services-server.

因为这个地址172.17.0.4:8091是容器seata-server的地址

容器网络信息

我部署的nacos-server和seata-server的网络信息如下

nacos-server

【BUG记录】spring cloud 集成seata的时候:can not register RM,err:can not connect to services-server.

seata-server的网络信息

【BUG记录】spring cloud 集成seata的时候:can not register RM,err:can not connect to services-server.

从上面两张图可以得知,这两个容器处于同一个网络当中。

关于docker网络的Bridge模式

当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。

从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。

bridge模式是docker的默认网络模式,不写–net参数,就是bridge模式。使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看。

bridge模式如下图所示:

【BUG记录】spring cloud 集成seata的时候:can not register RM,err:can not connect to services-server.

所以我们跟本访问不到这个地址,一般我们访问容器服务,都是采用的端口转发功能。容器端口和宿主机的端口做了映射。我们通过访问宿主机的IP:PORT来访问服务。

解决方案

那该怎么解决这个问题,只要nacos-server记录的是宿主机的IP和端口号就可以了。我们其他服务就能从nacos 的注册中心拿到能访问的seata-server服务地址。

docker部署seata-server可以参考 这篇博客

​Docker 部署 Seata Server(使用nacos 做为注册中心和配置中心)​​

docker run -itd --name seata-server \
        -p 8091:8091 \
        -e SEATA_CONFIG_NAME=file:/root/seata-config/registry \
        -e SEATA_IP=宿主机IP \
        -v /usr/local/seata/config:/root/seata-config  \
        seataio/seata-server:1.3.0      

重新启动了seata-server之后

【BUG记录】spring cloud 集成seata的时候:can not register RM,err:can not connect to services-server.

java 客户端的seata 客户端也成功连接上了seata-server,成功注册了TM和RMTM(Transaction Manager) - 事务管理器 :定义全局事务的范围:开始全局事务、提交或回滚全局事务。

RM (Resource Manager) - 资源管理器: 管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

References:

  • ​​https://yebd1h.smartapps.cn/pages/blog/index?blogId=84570488&_swebfr=1&_swebFromHost=baiduboxapp​​