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

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

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

1.1 client

RPC通信基于底层网络通信,可以通过设置connection的读写超时时间,达到RPC读写超时的目的。更多细节可参考golang网络通信超时设置.

下面以client端的读超时为例,介绍设置方法。

server端和client端代码如下。

server

一个简单的json RPC server。

package main

import (
"fmt"
"log"
"net"
"net/rpc"
"net/rpc/jsonrpc"
"time"
) type Counter struct {
Sum int
} func (this *Counter) Add(i int, r *int) error {
//sleep
time.Sleep(3*time.Second) if i < 0 {
return fmt.Errorf("data format incorrect")
} this.Sum += i
*r = this.Sum
log.Printf("i: %v\n", i)
return nil
} func NewJsonRpcSocketServer() { rpc.Register(new(Counter)) l, err := net.Listen("tcp", ":3333")
if err != nil {
log.Printf("Listener tcp err: %s", err)
return
} for {
log.Println("waiting...")
conn, err := l.Accept()
if err != nil {
log.Printf("accept connection err: %s\n", conn)
continue
} go jsonrpc.ServeConn(conn)
} } func main() {
NewJsonRpcSocketServer()
}

client

json RPC client。

连接建立后,会设置connection的读超时时间。

package main

import (
"log"
"net"
"net/rpc/jsonrpc"
"time"
) func main() { NewJsonRpcSocketClient()
} func NewJsonRpcSocketClient() {
timeout := time.Second*30
conn, err := net.DialTimeout("tcp", "127.0.0.1:3333", timeout)
if err != nil {
log.Printf("create client err:%s\n", err)
return
}
defer conn.Close() // timeout
readAndWriteTimeout := 2*time.Second
err = conn.SetDeadline(time.Now().Add(readAndWriteTimeout))
if err != nil {
log.Println("SetDeadline failed:", err)
} client := jsonrpc.NewClient(conn) var reply int err = client.Call("Counter.Add", 2, &reply)
if err != nil {
log.Println("error:", err, "reply:", reply)
return
} log.Printf("reply: %d, err: %v\n", reply, err) }

client输出:

2019/05/12 22:52:57 error: read tcp 127.0.0.1:55226->127.0.0.1:3333: i/o timeout reply: 0

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接口,加上超时的控制。

// 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

golang RPC通信读写超时设置的更多相关文章

  1. golang网络通信超时设置

    网络通信中,为了防止长时间无响应的情况,经常会用到网络连接超时.读写超时的设置. 本文结合例子简介golang的连接超时和读写超时设置. 1.超时设置 1.1 连接超时 func DialTimeou ...

  2. RPC通信功能实现

    Table of Contents RPC通信功能实现 配置參数 调用方法 RPC通信功能实现 HBase的RPC通信功能主要基于Protobuf和NIO这两个组件来实现.在通信管道上选择的是prot ...

  3. [转]JDBC如何进行超时设置

    文档来源:https://jingyan.baidu.com/article/fc07f98922615a12ffe519ce.html 恰当的JDBC超时设置能够有效地减少服务失效的时间.本文将对数 ...

  4. RPC通信原理(未完,先睡觉)

    一 背景 OpenStack 各组件之间是通过 REST 接口进行相互通信,比如Nova.Cinder.Neutron.Glance直间的通信都是通过keystone获取目标的endpoint,即ap ...

  5. 深入理解JDBC的超时设置

    恰当的JDBC超时设置能够有效地减少服务失效的时间.本文将对数据库的各种超时设置及其设置方法做介绍. 真实案例:应用服务器在遭到DDos攻击后无法响应 在遭到DDos攻击后,整个服务都垮掉了.由于第四 ...

  6. JDBC超时设置【转】

    恰当的JDBC超时设置能够有效地减少服务失效的时间.本文将对数据库的各种超时设置及其设置方法做介绍. 真实案例:应用服务器在遭到DDos攻击后无法响应 在遭到DDos攻击后,整个服务都垮掉了.由于第四 ...

  7. Spring Cloud 系列之 Dubbo RPC 通信

    Dubbo 介绍 官网:http://dubbo.apache.org/zh-cn/ Github:https://github.com/apache/dubbo 2018 年 2 月 15 日,阿里 ...

  8. Linux串口中的超时设置

    在Linux下使用串口通信时,默认的阻塞模式是不实用的.而采用select或epoll机制的非阻塞模式,写代码有比较麻烦.幸好Linux的串口自己就带有超时机制. Linux下使用termios.h中 ...

  9. PHP与Golang如何通信?

    PHP与Golang如何通信? 最近遇到的一个场景:php项目中需要使用一个第三方的功能(结巴分词),而github上面恰好有一个用Golang写好的类库.那么问题就来了,要如何实现不同语言之间的通信 ...

随机推荐

  1. 从Spring看Web项目开发

    之前简单介绍过Spring框架,本文换个角度重新诠释Spring.使用Java语言开发的项目,几乎都绕不过Spring,那么Spring到底是啥,为何被如此广泛的应用,下面从以下两个问题出发来剖析Sp ...

  2. Delphi 程序调试

  3. l洛谷P4779 【模板】单源最短路径(标准版)(dijkstra)

    题目描述 给定一个 NN 个点,MM 条有向边的带非负权图,请你计算从 SS 出发,到每个点的距离. 数据保证你能从 SS 出发到任意点. 输入格式 第一行为三个正整数 N, M, SN,M,S. 第 ...

  4. 搭建hadoop单机版

    一.准备工作 1.申请机器 1)修改配置: 申请虚拟机下来了,通过xshell连接进入, 主机名还是默认的,修改下,不然看着不习惯 >hostname 查看主机名 >vim /etc/sy ...

  5. 7.Go-用户信息和系统文件目录

    7.1.获取操作系统用户信息 (1)os包及子包功能 os/exec包,负责执行外部命令 os/singal对输入信息的访问 os/user通过名次或ID 查询用户账号 (2)在os/user中提供了 ...

  6. 〇三——css常规使用

    我们在前面已经学习了常用的html基础,就可以画出一个最直接的‘裸体’ ,那么这么画出来的比较简陋,那怎么能让他变得更漂亮呢?这里就引出今天要讲的——css 我们先看看怎么把页面加上修饰的效果 < ...

  7. 第五章Java

    2 [单选题] 已知MyInterface是一个接口,ClassA是实现该接口的一个类,ClassB是ClassA的子类,则下面说法哪个正确?   A. ClassB obj = new ClassA ...

  8. tomcat 搭建网站

    基本概念 JDK(Java Development Kit)是Sun Microsystems针对Java开发人员的产品.自从Java推出以来,JDK已经成为使用最广泛的Java SDK.JDK 是整 ...

  9. HDU - 6582 Path (最短路+最小割)

    题意:给定一个n个点m条边的有向图,每条边有个长度,可以花费等同于其长度的代价将其破坏掉,求最小的花费使得从1到n的最短路变长. 解法:先用dijkstra求出以1为源点的最短路,并建立最短路图(只保 ...

  10. hivesql之str_to_map函数

    str_to_map(字符串参数, 分隔符1, 分隔符2) 使用两个分隔符将文本拆分为键值对. 分隔符1将文本分成K-V对,分隔符2分割每个K-V对.对于分隔符1默认分隔符是 ',',对于分隔符2默认 ...