Golang GRPC 返回 EOF 错误

Posted

技术标签:

【中文标题】Golang GRPC 返回 EOF 错误【英文标题】:Go lang RPC return EOF error 【发布时间】:2017-12-25 16:45:17 【问题描述】:

我正在使用http调用RPC,代码如下

func (c *CallClient) Wallet(method string, req, rep interface) error 
    client := &http.Client
    data, _ :=  EncodeClientRequest(method, req)
    reqest, _ := http.NewRequest("POST", c.endpoint, bytes.NewBuffer(data))
    resp, err := client.Do(reqest)
    if err != nil 
        return err
    
    defer resp.Body.Close()
    io.Copy(ioutil.Discard, resp.Body)
    return DecodeClientResponse(resp.Body, rep)

使用 EncodeClientRquest && DecodeClientResponse

// EncodeClientRequest 对 JSON-RPC 客户端请求的参数进行编码。

func EncodeClientRequest(method string, args interface) ([]byte, error) 
    c := &clientRequest
        Version: "2.0",
        Method: method,
        Params: [1]interfaceargs,
        Id:     uint64(rand.Int63()),
    

    return json.Marshal(c)

// DecodeClientResponse 将客户端请求的响应体解码为 // 接口回复。

func DecodeClientResponse(r io.Reader, reply interface) error 
    var c clientResponse
    if err := json.NewDecoder(r).Decode(&c); err != nil 
        return err
    
    if c.Error != nil 
        return fmt.Errorf("%v", c.Error)
    
    if c.Result == nil 
        return errors.New("result is null")
    
    return json.Unmarshal(*c.Result, reply)

我收到错误 EOF。

【问题讨论】:

两个开始建议:1) 不要忽略错误 2) 记录原始请求和响应。 【参考方案1】:

这一行:

io.Copy(ioutil.Discard, resp.Body)

读取整个 resp.Body,让阅读器没有更多字节可读取。因此,任何对resp.Body.Read 的连续调用都将返回EOF,并且json.Decoder.Decode 方法在解码给定阅读器的内容时​​确实使用io.Reader.Read 方法,所以...

而且由于resp.Body 是一个io.ReadCloser,这是一个不支持“倒带”的接口,并且您想多次读取正文内容(ioutil.Discard 和 json.Decode),您将必须将正文读入一个变量,然后您可以重新读取。这取决于你如何做到这一点,一个字节,或bytes.Reader,或其他东西。

使用bytes.Reader的示例:

func (c *CallClient) Wallet(method string, req, rep interface) error 
    client := &http.Client
    data, err := EncodeClientRequest(method, req)
    if err != nil 
        return err
    
    reqest, err := http.NewRequest("POST", c.endpoint, bytes.NewBuffer(data))
    if err != nil 
        return err
    
    resp, err := client.Do(reqest)
    if err != nil 
        return err
    
    defer resp.Body.Close()

    // get a reader that can be "rewound"
    buf := bytes.NewBuffer(nil)
    if _, err := io.Copy(buf, resp.Body); err != nil 
        return err
    
    br := bytes.NewReader(buf.Bytes())

    if _, err := io.Copy(ioutil.Discard, br); err != nil 
        return err
    

    // rewind
    if _, err := br.Seek(0, 0); err != nil 
        return err
    
    return DecodeClientResponse(br, rep)

【讨论】:

以上是关于Golang GRPC 返回 EOF 错误的主要内容,如果未能解决你的问题,请参考以下文章

GRPC状态码

golang (*bufio.Reader)的读取方法

Golang gRPC 实践

手撸golang GO与微服务 grpc

golang随手记-grpc

GoLang -- gRPC框架四大服务