smallnest / rpcx

Best microservices framework in Go, like alibaba Dubbo, but with more features, Scale easily. Try it. Test it. If you feel it's better, use it! 𝐉𝐚𝐯𝐚有𝐝𝐮𝐛𝐛𝐨, 𝐆𝐨𝐥𝐚𝐧𝐠有𝐫𝐩𝐜𝐱! build for cloud!
https://rpcx.io
Other
8.08k stars 1.16k forks source link

runtime: call返回的err,类型为net.(*OpError)调用时panic #776

Closed arch3754 closed 1 year ago

arch3754 commented 1 year ago

如图:

image

部署环境是在公网,请求的目标地址也是公网 以下是对应代码块,在fmt.Sprintf("%v", err)时panic

func call(i interface{}) {
    f := i.(*ProbePlanning)
    arg := &model.ProbeArg{
        Stra:     f.stra,
        Endpoint: f.endpoint,
        Agent:    f.agent,
    }
    var err error
    defer func() {
        if e := recover(); e != nil {
            if ee, ok := e.(error); ok {
                err = ee
                return
            }

            err = fmt.Errorf("failed to get xclient: %v", e)
        }
    }()

    ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
    defer cancel()
    var reply model.ProbeReply
    err = f.xc.Get().Call(ctx, "Probe", arg, &reply)
    if err != nil {
        f.ch <- &model.ProbeReply{
            Stra:      arg.Stra,
            Endpoint:  arg.Endpoint,
            Agent:     arg.Agent,
            Code:      0,
            RpcError:  fmt.Sprintf("%v", err),
            Timestamp: time.Now().Unix(),
        }
        return
    }
    f.ch <- &reply
}
smallnest commented 1 year ago

@arch3754 你的go 版本是多少?

smallnest commented 1 year ago

当err是(*net.OpError)时,把这个err的各字段信息打印出来,看看哪里有问题,或许踩到了一个go的bug.

type OpError struct {
    Op string
    Net string
    Source Addr
    Addr Addr
    Err error
}
smallnest commented 1 year ago

尤其是Err字段,可以同时%T打印出这个字段的实际类型

smallnest commented 1 year ago

如果你不能复现,我建议你加一层保护,如果是(net.OpError), 直接返回`net.OpError, 而不是fmt.Sprintf("%v", err)`。

当然,如果你能复现是最好了。 复现的时候先把这个net.OpError各字段信息打印出来,看看有没有啥异常。

arch3754 commented 1 year ago

go 版本1.18.5和1.19.2都有问题,我先打出来试试,不太容易复现,好多天才能复现一次