天天看點

【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​​