Docker 中的基本 Go RPC 因 SIGSEGV 而失败
Posted
技术标签:
【中文标题】Docker 中的基本 Go RPC 因 SIGSEGV 而失败【英文标题】:Basic Go RPC in Docker fails with SIGSEGV 【发布时间】:2020-05-30 16:08:24 【问题描述】:我正在尝试使用 Golang 在两个 docker 容器之间运行一个简单的客户端/服务器 RPC 示例。
当我在本地机器上运行它们时,构建和运行都完美无缺。我知道将它们构建到 docker 容器中可能会出现一些我需要解决的通信错误,但我什至无法到达那个阶段,因为我在尝试运行我的客户端时遇到了分段错误。
当我运行主(服务器)容器时,它可以工作,没有问题。但是当我运行工人(客户端)时,我得到了这个:
panic: runtime error: invalid memory address or nil pointer ` `dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x10
pc=0x72425d]
goroutine 1 [running]:
net/rpc.(*Client).send(0x0, 0xc0000d61e0)
/usr/local/go/src/net/rpc/client.go:72 +0x3d
net/rpc.(*Client).Go(0x0, 0x7e062d, 0xa, 0x7887e0,
0xc0000b04a8, 0x788860, 0xb0c440, 0xc0000aa300,
0xc0000d6190)
/usr/local/go/src/net/rpc/client.go:316 +0xcc
net/rpc.(*Client).Call(...)
/usr/local/go/src/net/rpc/client.go:322
main.main()
/app/worker.go:20 +0x11c
exit status 2
我的master.go:
package main
import (
"fmt"
"net"
"net/http"
"net/rpc"
)
type Args struct
Addthis int
type Reply struct
Ret int
type Api int
func (master *Api) Add(args Args, reply *Reply) error
out := args.Addthis + 10
reply.Ret = out
return nil
func main()
var master = new(Api)
rpc.Register(master)
rpc.HandleHTTP()
listener, _ := net.Listen("tcp", ":4040")
fmt.Printf("\nServing on %d\n", 4040)
http.Serve(listener, nil)
我的主 Dockerfile:
FROM golang:latest
WORKDIR /app
COPY ./ /app
EXPOSE 4040
ENTRYPOINT go run master.go
我使用以下方式构建和运行 master:
docker build -t master
docker run --net=testnet --name=master master
这很好用。
我的工人.go
package main
import (
"fmt"
"net/rpc"
)
type Args struct
Addthis int
type Reply struct
Ret int
func main()
var reply Reply
client, _ := rpc.DialHTTP("tcp", ":4040")
num := Args215
client.Call("master.Add", num, &reply)
fmt.Println("Here")
fmt.Printf("\nGot back: %d\n", reply.Ret)
我的工人 Dockerfile:
FROM golang:latest
WORKDIR /app
COPY ./ /app
EXPOSE 4040
ENTRYPOINT go run worker.go
我构建并运行worker:
docker build -t worker .
docker run --net=testnet --name=worker worker
那是我收到上述错误的时候。
谷歌搜索了三个小时,似乎没有任何帮助。我想我不知道要使用什么搜索。
我知道这可能实际上不会按原样进行通信,但我想调试通信问题,而不是处理分段错误。代码是我的教授提供的,不是作为作业的一部分,而是因为我要求它。他声称这对他来说没有问题,并且对我的故障排除没有帮助(我认为他实际上没有尝试将它部署在容器中,但我不会打电话给他。他很“敏感”)。 “尝试堆栈交换!”真的。
【问题讨论】:
不要忽略rpc.DialHTTP
返回的错误(或其他错误)。
有证据表明客户为空。 HTTP 拨号可能存在非空错误。
完全正确!我发现了错误,现在我得到“拨号 tcp:4040:连接:连接被拒绝”然后我得到了 seg 错误。我认为这与我实际上没有输入 ip 的事实有关?
这意味着在 localhost 端口:4040 上没有任何监听。如果您正在运行两个单独的容器,则需要设置适当的网络,它不会在 localhost 上。您还应该正确处理错误,而不仅仅是继续尝试使用客户端。
【参考方案1】:
client, _ := rpc.DialHTTP("tcp", ":4040")
这基本上意味着您正在尝试连接到同一容器上的端口 4040,但是,您的主服务器在不同的容器中运行。要连接到您的主容器,您需要连接到 ip that docker has assigned automatically:4040(用于测试)或 setup your docker network 以正确使用容器。
【讨论】:
以上是关于Docker 中的基本 Go RPC 因 SIGSEGV 而失败的主要内容,如果未能解决你的问题,请参考以下文章