关于上一篇文章中,遇到了一个操蛋的问题,将我的RPC服务端运行在docker容器中时。在其他docker容器中访问RPC服务时,总是Connection refused
问题排查
1.测试网络连通性(ping)
我在另外一个容器中访问RPC服务时,是以 容器名称:端口号
的形式访问RPC服务的,本来我以为是两个容器之间网络不通导致服务无法连接。
但是进入容器中使用ping测试,是可以互相连通的。所以排除网络不通的原因
2.测试接口响应(curl)
当我进入RPC服务器容器时,用curl命令测试。
curl http://127.0.0.1:8000
虽然返回的是501,但证明服务时可访问的,只是访问的姿势不对。
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error response</title>
</head>
<body>
<h1>Error response</h1>
<p>Error code: 501</p>
<p>Message: Unsupported method ('GET').</p>
<p>Error code explanation: 501 - Server does not support this operation.</p>
</body>
</html>
在容器外宿主机测试(注:我做了端口映射,将宿主机的8000端口映射到容器内部的8000端口)
curl http://127.0.0.1:8000
Connection reset by peer
,连接被重置 ----> 连接不通
curl: (56) Recv failure: Connection reset by peer
请求无法到达我RPC服务。但是端口都对的上的呀,为什么访问不到,在内网访问时,也涉及不到防火墙策略啥的。到底是为什么呢????
错误解决
就不搞那么多弯弯绕绕了,直接说错误是什么,该怎么解决,上面主要是展示我排错的过程,或许可以值得借鉴一下。
直接上代码
如下,我的RPC服务监听的是本机的8000端口,所以在上面进入docker容器中可以访问到服务。
# Create server
with SimpleXMLRPCServer(('localhost', 8000),requestHandler=RequestHandler) as server:
server.register_introspection_functions()
server.register_instance(RpcMethodsHanlers())
server.serve_forever()
那为什么,我在容器外部就访问不到了呢,我也做了端口映射的呀。
问题就出现在localhost
!!!!
进入docker容器,使用ifconfig
查看接口配置,可以看到有两个接口,eth0
和lo,而我的RPC服务监听的就是lo这个接口,127.0.0.1(等同于localhost)
/app # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:C0:A8:2F:04
inet addr:192.168.47.4 Bcast:192.168.47.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1203 errors:0 dropped:0 overruns:0 frame:0
TX packets:1185 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:3185826 (3.0 MiB) TX bytes:65576 (64.0 KiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:12 errors:0 dropped:0 overruns:0 frame:0
TX packets:12 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:1264 (1.2 KiB) TX bytes:1264 (1.2 KiB)
eth0是负责与docker网络通信的接口,其ip地址也是docker网络分配的,当我们在docker外部访问该docker容器时,最终是与这个接口通信。
如下图,我的RPC服务监听的是lo接口,而请求最终转发到了eth0,导致了Connection refused
解决办法
监听0.0.0.0
注:
通配符地址:在某些情况下,0.0.0.0
可以用作通配符地址,表示所有可能的 IP 地址。例如,在服务器中,当一个服务绑定到 0.0.0.0
时,它将监听来自本地网络接口和所有网络接口的连接。
# Create server
with SimpleXMLRPCServer(('0.0.0.0', 8000),requestHandler=RequestHandler) as server:
server.register_introspection_functions()
server.register_instance(RpcMethodsHanlers())
server.serve_forever()
此时的效果。问题得到解决。
总结
当我们在docker容器内部可以正常访问服务,而在外部无法访问服务时,
最可能就是请求没有转发到服务监听的接口。