服务注册(service register)

  • 通过反射实现服务注册功能
  • 在服务端实现服务调用

结构体映射为服务

RPC 框架的一个基础能力是:像调用本地程序一样调用远程服务。那如何将程序映射为服务呢?那么对 Go 来说,这个问题就变成了如何将结构体的方法映射为服务。

net/rpc
  • the method’s type is exported. – 方法所属类型是导出的。
  • the method is exported. – 方式是导出的。
  • the method has two arguments, both exported (or builtin) types. – 两个入参,均为导出或内置类型。
  • the method’s second argument is a pointer. – 第二个入参必须是一个指针。
  • the method has return type error. – 返回值为 error 类型。

通过反射实现 service

service.go

service.go

集成到服务端

service.call
server.goreadRequesthandleRequestRegister


超时处理(timeout)

  • 增加连接超时的处理机制
  • 增加服务端处理超时的处理机制

超时处理是 RPC 框架一个比较基本的能力,如果缺少超时处理机制,无论是服务端还是客户端都容易因为网络或其他错误导致挂死,资源耗尽,这些问题的出现大大地降低了服务的可用性。因此,我们需要在 RPC 框架中加入超时处理的能力。

纵观整个远程调用的过程,需要客户端处理超时的地方有:

  • 与服务端建立连接,导致的超时
  • 发送请求到服务端,写报文导致的超时
  • 等待服务端处理时,等待处理导致的超时(比如服务端已挂死,迟迟不响应)
  • 从服务端接收响应时,读报文导致的超时

需要服务端处理超时的地方有:

  • 读取客户端请求报文时,读报文导致的超时
  • 发送响应报文时,写报文导致的超时
  • 调用映射服务的方法时,处理报文导致的超时

GinRPC 在 3 个地方添加了超时处理机制。分别是:

Client.Call()Server.handleRequest

创建连接超时

为了实现上的简单,将超时设定放在了 Option 中。ConnectTimeout 默认值为 10s,HandleTimeout 默认值为 0,即不设限。

客户端连接超时,只需要为 Dial 添加一层超时处理的外壳即可。

client.go

dialTimeout
net.Dialnet.DialTimeouttime.After()

Client.Call 超时

Client.Call

服务端处理超时

time.After()select+chan

server.go

sendResponsecalledsent
time.After()case <-time.After(timeout)sendResponse