golang RPC通信读写超时设置

golang RPC通信中,有时候就怕读写hang住。

那是否可以设置读写超时呢?

1.方案一: 设置连接的读写超时

1.1 client

直接通过设置connSetDeadline()
可参考
golang网络通信超时设置--读写超时部分

1.2 server

通常情况下,RPC server端的代码如下:

    server := rpc.NewServer()
    ... ....
    for {
        conn, err := l.Accept()
        if err != nil {
            log.Println("listener accept fail:", err)
            time.Sleep(time.Duration(100) * time.Millisecond)
            continue
        }
        
        // timeout
        timeout := 10*time.Second
        conn.SetDeadline(time.Now().Add(timeout))
        
        go server.ServeCodec(jsonrpc.NewServerCodec(conn))
    }

这样,如果设置超时,只有效的影响一次。

对于server来说,都是多次读写。所以,暂时没有方法设置。

2.方案二:定时器

通过定时器的方式,如果RPC调用在指定时间内没有完成,触发定时器,返回超时错误,关闭连接。

2.1 client端

func  RpcCall(method string, args interface{}, reply interface{}) error {
    ... ...

    timeout := time.Duration(10 * time.Second)
    done := make(chan error, 1)

    go func() {
        err := rpcClient.Call(method, args, reply)
        done <- err
    }()

    select {
    case <-time.After(timeout):
        log.Printf("[WARN] rpc call timeout %v => %v", rpcClient, RpcServer)
        rpcClient.Close()
        return fmt.Errorf("timeout")
    case err := <-done:
        if err != nil {
            rpcClient.Close()
            return err
        }
    }

    return nil
}

2.2 server端

无论是gobServerCodec 或者 jsonrpc ,都是实现了ServerCodec接口。

gobServerCodec文件路径:/usr/local/go/src/net/rpc/server.go

jsonrpc文件路径:/usr/local/go/src/net/rpc/server.go

要给server端RPC读写加上超时机制,需要重新定义ServerCodec接口,加上超时的控制。

扫描二维码关注公众号,回复: 6214380 查看本文章
// A ServerCodec implements reading of RPC requests and writing of
// RPC responses for the server side of an RPC session.
// The server calls ReadRequestHeader and ReadRequestBody in pairs
// to read requests from the connection, and it calls WriteResponse to
// write a response back. The server calls Close when finished with the
// connection. ReadRequestBody may be called with a nil
// argument to force the body of the request to be read and discarded.
type ServerCodec interface {
    ReadRequestHeader(*Request) error
    ReadRequestBody(interface{}) error
    // WriteResponse must be safe for concurrent use by multiple goroutines.
    WriteResponse(*Response, interface{}) error

    Close() error
}

目前,已经有现成的实现方式,可参考Golang标准库RPC实践及改进

3.参考

Does RPC have a timeout mechanism?

net/rpc: expected Timeout based alternatives to functions for rpc.Dial, rpc.DialHTTP, rpc.DialHTTPPath [proposal]. #15236

猜你喜欢

转载自www.cnblogs.com/lanyangsh/p/10853903.html
今日推荐