Go语言RPC协议:远程过程调用
来源:云海天教程
时间:2023-01-07 12:12:17 374浏览 收藏
怎么入门Golang编程?需要学习哪些知识点?这是新手们刚接触编程时常见的问题;下面golang学习网就来给大家整理分享一些知识点,希望能够给初学者一些帮助。本篇文章就来介绍《Go语言RPC协议:远程过程调用》,涉及到网络编程,有需要的可以收藏一下
Go语言中 RPC(Remote Procedure Call,远程过程调用)是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络细节的应用程序通信协议。RPC 协议构建于 TCP 或 UDP,或者是 HTTP 之上,允许开发者直接调用另一台计算机上的程序,而开发者无需额外地为这个调用过程编写网络通信相关代码,使得开发包括网络分布式程序在内的应用程序更加容易。RPC 采用客户端—服务器(Client/Server)的工作模式。请求程序就是一个客户端(Client),而服务提供程序就是一个服务器(Server)。当执行一个远程过程调用时,客户端程序首先发送一个带有参数的调用信息到服务端,然后等待服务端响应。
在服务端,服务进程保持睡眠状态直到客户端的调用信息到达为止。当一个调用信息到达时,服务端获得进程参数,计算出结果,并向客户端发送应答信息,然后等待下一个调用。最后,客户端接收来自服务端的应答信息,获得进程结果,然后调用执行并继续进行。
在 Go 中,标准库提供的 net/rpc 包实现了 RPC 协议需要的相关细节,开发者可以很方便地使用该包编写 RPC 的服务端和客户端程序,这使得用 Go语言开发的多个进程之间的通信变得非常简单。
net/rpc 包允许 RPC 客户端程序通过网络或是其他 I/O 连接调用一个远端对象的公开方法(必须是大写字母开头、可外部调用的)。在 RPC 服务端,可将一个对象注册为可访问的服务,之后该对象的公开方法就能够以远程的方式提供访问。一个 RPC 服务端可以注册多个不同类型的对象,但不允许注册同一类型的多个对象。
一个对象中只有满足如下这些条件的方法,才能被 RPC 服务端设置为可供远程访问:
必须是在对象外部可公开调用的方法(首字母大写);必须有两个参数,且参数的类型都必须是包外部可以访问的类型或者是 Go 内建支持的类型;第二个参数必须是一个指针;方法必须返回一个error类型的值。
以上 4 个条件,可以简单地用如下一行代码表示:
func (t *T) MethodName(argType T1, replyType *T2) error
在上面这行代码中,类型 T、T1 和 T2 默认会使用 Go 内置的 encoding/gob 包进行编码解码。关于 encoding/gob 包的内容,稍后我们将会对其进行介绍。该方法(MethodName)的第一个参数表示由 RPC 客户端传入的参数,第二个参数表示要返回给 RPC 客户端的结果,该方法最后返回一个 error 类型的值。
RPC 服务端可以通过调用 rpc.ServeConn 处理单个连接请求。多数情况下,通过 TCP 或是 HTTP 在某个网络地址上进行监听来创建该服务是个不错的选择。
在 RPC 客户端,Go 的 net/rpc 包提供了便利的 rpc.Dial() 和 rpc.DialHTTP() 方法来与指定的 RPC 服务端建立连接。在建立连接之后,Go 的 net/rpc 包允许我们使用同步或者异步的方式接收 RPC 服务端的处理结果。
调用 RPC 客户端的 Call() 方法则进行同步处理,这时候客户端程序按顺序执行,只有接收完 RPC 服务端的处理结果之后才可以继续执行后面的程序。
当调用 RPC 客户端的 Go() 方法时,则可以进行异步处理,RPC 客户端程序无需等待服务端的结果即可执行后面的程序,而当接收到 RPC 服务端的处理结果时,再对其进行相应的处理。
无论是调用 RPC 客户端的 Call() 或者是 Go() 方法,都必须指定要调用的服务及其方法名称,以及一个客户端传入参数的引用,还有一个用于接收处理结果参数的指针。
如果没有明确指定 RPC 传输过程中使用何种编码解码器,默认将使用 Go 标准库提供的 encoding/gob 包进行数据传输。
接下来,我们来看一组 RPC 服务端和客户端交互的示例程序。下面的代码是 RPC 服务端程序。
package servertype Args struct { A, B int}type Quotient struct { Quo, Rem int}type Arith intfunc (t *Arith) Multiply(args *Args, reply *int) error { *reply = args.A * args.B return nil}func (t *Arith) Divide(args *Args, quo *Quotient) error { if args.B == 0 { return errors.New("divide by zero") } quo.Quo = args.A / args.B quo.Rem = args.A % args.B return nil}注册服务对象并开启该 RPC 服务的代码如下:
arith := new(Arith)rpc.Register(arith)rpc.HandleHTTP()l, e := net.Listen("tcp", ":1234")if e != nil { log.Fatal("listen error:", e)}go http.Serve(l, nil)此时,RPC 服务端注册了一个 Arith 类型的对象及其公开方法 Arith.Multiply() 和 Arith.Divide() 供 RPC 客户端调用。RPC 在调用服务端提供的方法之前,必须先与 RPC 服务端建立连接,如下列代码所示:
client, err := rpc.DialHTTP("tcp", serverAddress + ":1234")if err != nil { log.Fatal("dialing:", err)}在建立连接之后,RPC 客户端可以调用服务端提供的方法。首先,我们来看同步调用程序顺序执行的方式:
args := &server.Args{7,8}var reply interr = client.Call("Arith.Multiply", args, &reply)if err != nil { log.Fatal("arith error:", err)}fmt.Printf("Arith: %d*%d=%d", args.A, args.B, reply)此外,还可以以异步方式进行调用,具体代码如下:
quotient := new(Quotient)divCall := client.Go("Arith.Divide", args, "ient, nil)replyCall :=
今天关于《Go语言RPC协议:远程过程调用》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!
-
215 收藏
-
399 收藏
-
458 收藏
-
151 收藏
-
169 收藏
-
202 收藏
-
199 收藏
-
145 收藏
-
168 收藏
-
165 收藏
-
473 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 507次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习
-
- 称心的楼房
- 好细啊,已收藏,感谢作者的这篇文章,我会继续支持!
- 2023-04-01 07:53:47
-
- 甜美的高山
- 真优秀,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,帮助很大,总算是懂了,感谢老哥分享文章内容!
- 2023-03-28 03:47:53
-
- 冷傲的心情
- 这篇技术文章真是及时雨啊,大佬加油!
- 2023-02-26 10:05:37
-
- 直率的咖啡
- 这篇文章内容太及时了,很详细,写的不错,已收藏,关注师傅了!希望师傅能多写Golang相关的文章。
- 2023-02-26 06:41:25
-
- 俊逸的枕头
- 受益颇多,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,帮助很大,总算是懂了,感谢作者分享博文!
- 2023-02-21 17:22:26
-
- 高高的蜡烛
- 好细啊,已收藏,感谢楼主的这篇博文,我会继续支持!
- 2023-02-17 21:31:56
-
- 任性的芝麻
- 很好,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,看完之后很有帮助,总算是懂了,感谢作者分享技术文章!
- 2023-02-08 15:41:07
-
- 内向的铃铛
- 这篇博文出现的刚刚好,太全面了,很好,码起来,关注老哥了!希望老哥能多写Golang相关的文章。
- 2023-02-02 05:37:23
-
- 高挑的电灯胆
- 这篇技术贴太及时了,太详细了,赞 👍👍,已收藏,关注作者大大了!希望作者大大能多写Golang相关的文章。
- 2023-01-31 04:06:06
-
- 落寞的向日葵
- 这篇博文真及时,细节满满,感谢大佬分享,已加入收藏夹了,关注博主了!希望博主能多写Golang相关的文章。
- 2023-01-27 02:43:15
-
- 大意的烤鸡
- 太详细了,收藏了,感谢大佬的这篇文章内容,我会继续支持!
- 2023-01-21 17:48:59
-
- 酷炫的魔镜
- 这篇文章内容真是及时雨啊,太细致了,很好,mark,关注大佬了!希望大佬能多写Golang相关的文章。
- 2023-01-15 16:40:43
-
- 热心的玫瑰
- 很有用,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,帮助很大,总算是懂了,感谢作者分享博文!
- 2023-01-15 10:06:19
-
- 包容的鼠标
- 写的不错,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,看完之后很有帮助,总算是懂了,感谢up主分享博文!
- 2023-01-12 22:44:45
-
- 眯眯眼的小蘑菇
- 这篇博文出现的刚刚好,太全面了,很有用,已收藏,关注作者了!希望作者能多写Golang相关的文章。
- 2023-01-12 05:35:51
-
- 潇洒的酒窝
- 这篇博文真及时,楼主加油!
- 2023-01-09 23:57:23
-
- 专一的裙子
- 好细啊,码住,感谢大佬的这篇文章内容,我会继续支持!
- 2023-01-07 22:52:29