前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go 使用标准库 net/rpc 包

Go 使用标准库 net/rpc 包

作者头像
frank.
发布2020-10-27 10:37:54
7460
发布2020-10-27 10:37:54
举报
文章被收录于专栏:Golang语言开发栈

01

RPC 是什么?

RPC 是远程过程调用(Remote Procedure Call),用于调用方和被调用方两个进程间的交互,并且提供类似本地方法调用的形式。RPC 广泛用于在分布式系统中不同节点间的通信。

02

Go 语言 RPC 标准库

在 Go 语言的标准库中,也提供了一个简单的 RPC 实现(net/rpc)。rpc 包提供对对象在网络或其他 I/O 连接中导出方法的访问。服务器端注册对象,使其作为可见服务,服务的名称是对象类型名称。注册后,对象的导出方法将可远程访问。服务器可以注册不同类型的多个对象(服务),但注册同一类型的多个对象是错误的。

对象的导出方法有以下几点要求:

  • 方法的类型是可导出的。
  • 方法是可导出的。
  • 方法有两个参数,都是可导出类型或内置类型。
  • 方法的第二个参数是指针。
  • 方法返回一个错误类型。

实际上,方法看起来像这样:

代码语言:javascript
复制
func (t *T) MethodName(argType T1, replyType *T2) error

其中 T1 和 T2 可以通过 encoding/gob 编码进行序列化。即使使用不同的编码解码器,这些限制也适用。将来,对自定义的编码解码器的限制可能会宽松一些。

该方法的第一个参数表示调用方提供的参数;第二个参数表示要返回给调用方的结果参数。方法的返回值(如果不是 nil)作为字符串传递回来,客户端认为该字符串就像由 errors.New 创建的错误一样。如果返回错误,则不会将回复参数发送回客户端。

服务器端可以调用 ServeConn 处理单个连接上的请求。更典型的是,它将创建一个网络监听器并调用 Accept,或者,对于 HTTP 监听器,调用 HandleHTTP 和 http.Serve。

想要使用该服务的客户端会建立连接,然后在连接上调用 NewClient。

更方便的函数是 Dial (DialHTTP) ,会在原始网络连接(HTTP 连接)依次执行这两个步骤。生成的 Client 对象有两个方法,即 Call 和 Go,它们的参数是要调用的服务和方法,一个包含参数的指针,一个用于接收结果的指针。

Call 方法等待远程调用完成。Go 方法异步发送调用请求,并使用返回的 Call结构体类型的 "Done 通道" 传递完成的信号。

除非显式设置了编码解码器,否则 net/rpc 包默认采用 encoding/gob 包编码解码数据。

03

RPC 怎么使用?

通过一个简单的示例,我们演示 Go 语言标准库 net/rpc 的使用方法。

RPC 方法:

服务器端定义一个可导出的 User 类型和一个符合 RPC 方法定义要求的 GetUser 方法:

代码语言:javascript
复制
type User struct {
  ID   int
  Name string
}
// rpc 方法
func (u *User) GetUser(id int, user *User) error {
  userMap := map[int]User{
    1: {ID: 1, Name: "frank"},
    2: {ID: 2, Name: "lucy"},
  }
  if userInfo, ok := userMap[id]; ok {
    *user = userInfo
  }
  return nil
}

服务器端:

服务器端被调用(用于 HTTP 服务):

代码语言:javascript
复制
func main() {
  _ = rpc.Register(new(message.User))
  rpc.HandleHTTP()
  listener, _ := net.Listen("tcp", ":8081")
  _ = http.Serve(listener, nil)
}

客户端:

此时,客户端可以看到具有 "User.GetUser" 方法的服务 "User"。要调用方法,客户端首先呼叫服务器端:

代码语言:javascript
复制
client, _ := rpc.DialHTTP("tcp", ":8081")

然后客户端可以进行远程调用:

Call 方法,同步调用:

代码语言:javascript
复制
id := 1
var user message.User
_ = client.Call("User.GetUser", id, &user)
fmt.Println(user)

Go 方法,异步调用:

代码语言:javascript
复制
userCall := client.Go("User.GetUser", id, &user, nil)
if replyCall := <-userCall.Done; replyCall != nil {
  fmt.Println(user)
}

服务器端的实现通常为客户端提供简单、类型安全的包装。

net/rpc 包已冻结,不接受新功能。

04

总结

本文简要描述 Go 语言标准库 net/rpc 包的使用方法,通过阅读本文,读者应该已经对Go 语言标准库 net/rpc 有了初步的认识。


本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-10-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Go语言开发栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档