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来做分布式事务。但是却出现了如下错误

我截取了部分日志出来,可见seata 内置netty来实现网络通信,8091也正是seata-server的端口,根据如下日志可知我们客户端程序连接不上172.18.0.1:802022-02-18 17:03:07.724 ERROR 26860 --- [eoutChecker_2_1]

i.s.c.r.netty.NettyClientChannelManager  : 0101 can not connect to 172.18.0.1:8091 cause:can not register RM,err:can not connect to services-serverio.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.18.0.1:8091正是seata-server的地址,如下所示,但是我们访问不到,这是为什么

nacos 的注册中心信息图

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

容器网络信息

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

nacos-server

seata-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模式如下图所示:

所以我们跟本访问不到这个地址,一般我们访问容器服务,都是采用的端口转发功能。容器端口和宿主机的端口做了映射。我们通过访问宿主机的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重新启动了seata-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

(写博客主要是对自己学习的归纳整理,资料大部分来源于书籍、网络资料、官方文档和自己的实践,整理的不足和错误之处,请大家评论区批评指正。同时感谢广大博主和广大作者辛苦整理出来的资源和分享的知识。)

【BUG记录】spring cloud 集成seata的时候:can not register RM,err:can not connect to services-serverhttps://blog.51cto.com/u_14020077/5836706