七叶笔记 » golang编程 » Go语言实现RPC

Go语言实现RPC

rpc 定义,来源于百度百科

  • RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如 TCP 或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络 分布式 多程序在内的应用程序更加容易。
  • RPC采用 客户机 /服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。
  • 有多种 RPC模式和执行。最初由 Sun 公司提出。IETF ONC 宪章重新修订了 Sun 版本,使得 ONC RPC 协议成为 IETF 标准协议。现在使用最普遍的模式和执行是开放式软件基础的分布式计算环境(DCE)。
  • 个人的理解:不用管什么底层网络技术的协议,是一种通过网络从计算机程序上请求服务,通俗一点,我们写代码,要在一个地方,比如安卓,就需要在一个工程里面,才可以调用到其他的程序代码执行的过程。Go语言提供RPC支持使得开发网络分布式多程序在内的应用程序更加的easy

RPC工作流程图

图片来源于gitHub

  • 1.调用客户端句柄;执行传送参数
  • 2.调用本地系统内核发送网络消息
  • 3.消息传送到远程主机
  • 4.服务器句柄得到消息并取得参数
  • 5.执行远程过程
  • 6.执行的过程将结果返回服务器句柄
  • 7.服务器句柄返回结果,调用远程系统内核
  • 8.消息传回本地主机
  • 9.客户句柄由内核接收消息
  • 10.客户接收句柄返回的数据

Go语言提供对RPC的支持:HTTP、TCP、JSPNRPC,但是在Go中RPC是独一无二的,它采用了GoLang Gob 编码 ,只能支持Go语言!

  • GoLang Gob:是Golang包自带的一个数据结构序列化的编码/解码工具。编码使用Encoder,解码使用Decoder。一种典型的应用场景就是RPC(remote procedure calls)。

HTTP RPC Demo

  • 服务端的代码

  • Go RPC 的函数只有符合四个条件才能够被远程访问,不然会被忽略
  • 函数必须是首字母大写(可以导出的)
  • 必须有两个导出类型的参数
  • 第一个参数是接受的参数,第二个参数是返回给客户端的参数,而且第二个参数是指针的类型
  • 函数还要有一个返回值error

  • T、T1和T2类型必须能被encoding/gob包编解码。
  • 客户端的代码

运行的结果图

  • go run GoRPCWeb8.go 127.0.0.1:1234 20 3
  • go run 运行的命令
  • GoRPCWeb8.go :这是文件的名称,需要到指定的目录下启动cmd
  • 127.0.0.1:1234 : ip地址和端口号
  • 20 3 这是客服端传入的值:一个除数,一个被除数,传入到服务器做乘法运算 乘法: 20*3=60和除法取整数: 20/3=6 余数 2,怎么做的,客户端不关心,给到服务端去完成
  • os.Args[0]=[C:\Users\win7\AppData\Local\Temp\go-build011170718\command- line-arguments\_obj\exe\GoRPCWeb8.exe 127.0.0.1:1234 20 3]

TCP RPC Demo

  • 基于TCP协议实现的RPC,服务端的代码

  • 运行结果图

  • 结果图
E:\new_code\GoDemo\web_server>go run GoTCPRPCWeb10.go 127.0.0.1:1234 20 1
客户端 其他端 去调用的地方 对应的例子是 GoTCPRPC9.go
长度必须等于4,因为呢,你输入的肯定是一个ip的地址ip= 127.0.0.1:1234 嘿嘿,加上后面
的被除数os.Args[2]= 20 和除数os.Args[3]= 1
我进行正常结果如下
Num : 20*1=20
Num: 20/1=0 余数 0
E:\new_code\GoDemo\web_server>go run GoTCPRPCWeb10.go 127.0.0.1:1234 20 2
客户端 其他端 去调用的地方 对应的例子是 GoTCPRPC9.go
长度必须等于4,因为呢,你输入的肯定是一个ip的地址ip= 127.0.0.1:1234 嘿嘿,加上后面
的被除数os.Args[2]= 20 和除数os.Args[3]= 2
我进行正常结果如下
Num : 20*2=40
Num: 20/2=0 余数 0
E:\new_code\GoDemo\web_server>go run GoTCPRPCWeb10.go 127.0.0.1:1234 20 3
客户端 其他端 去调用的地方 对应的例子是 GoTCPRPC9.go
长度必须等于4,因为呢,你输入的肯定是一个ip的地址ip= 127.0.0.1:1234 嘿嘿,加上后面
的被除数os.Args[2]= 20 和除数os.Args[3]= 3
我进行正常结果如下
Num : 20*3=60
Num: 20/3=0 余数 2
 
  • 在定义BDemo 的时候, 如果定义的DD, CC int和服务端不一样,就会报错 reading body gob: type mismatch: no fields matched compiling decoder for ,其实发现好多种情况,也会出现这种错误,但是目前不知道为啥会这样,后续,等源码深入一点,回来看这个问题 todo2018/07/19
  • 这种TCP方式和上面的HTTP不同的是
  • HTTP:指定的网络地址连接到HTTP RPC服务器
 //DelayHTTP在指定的网络地址连接到HTTP RPC服务器
 ///在默认HTTP RPC路径上监听。
 client, err := rpc.DialHTTP("tcp", serverAddress)
 
  • TCP:指定的网络地址连接到HTTP RPC服务器
 client,err:=rpc.Dial("tcp",service)
 

JSON RPC

  • JSON RPC是数据编码采用了JSON,而不是gob编码,其他和上面介绍的RPC概念一模一样的。
  • 服务端的代码如下
package main
import (
 "fmt"
 "net/rpc"
 "net"
 "net/rpc/jsonrpc"
)
//使用Go提供的json-rpc 标准包
func init() {
 fmt.Println("JSON RPC 采用了JSON,而不是 gob编码,和RPC概念一模一样,")
}
type Work struct {
 Who,DoWhat string
}
type DemoM string
func (m *DemoM) DoWork(w *Work,whoT *string) error {
 *whoT="是谁:"+w.Who+",在做什么---"+w.DoWhat
 return nil
}
func main() {
 str:=new(DemoM)
 rpc.Register(str)
 tcpAddr,err:=net.ResolveTCPAddr("tcp",":8080")
 if err!=nil{
 fmt.Println("大哥发生错误了啊,请看错误 ResolveTCPAddr err=",err)
 }
 listener,err:=net.ListenTCP("tcp",tcpAddr)
 if err!=nil {
 fmt.Println("发生错误了--》err=",err)
 }
 for {
 conn,err:= listener.Accept()
 if err!=nil {
 continue
 }
 jsonrpc.ServeConn(conn)
 }
}
 
  • 客户端的代码

  • 运行的结果如下

  • 运行结果
E:\new_code\GoDemo\web_server>go run GoJSONRPCWeb11.go 127.0.0.1:8080 shiming g
ongzuo
这是客户端,用来启动,通过命令行来启动
客户端 其他端 去调用的地方 对应的例子是 GoTCPRPC9.go
长度必须等于4,因为呢,你输入的肯定是一个ip的地址ip= 127.0.0.1:8080 嘿嘿,加上后面
的被除数os.Args[2]= shiming 和除数os.Args[3]= gongzuo
收到信息了 是谁:shiming,在做什么---gongzuo
E:\new_code\GoDemo\web_server>go run GoJSONRPCWeb11.go 127.0.0.1:8080 shiming q
iaodaima
这是客户端,用来启动,通过命令行来启动
客户端 其他端 去调用的地方 对应的例子是 GoTCPRPC9.go
长度必须等于4,因为呢,你输入的肯定是一个ip的地址ip= 127.0.0.1:8080 嘿嘿,加上后面
的被除数os.Args[2]= shiming 和除数os.Args[3]= qiaodaima
收到信息了 是谁:shiming,在做什么---qiaodaima
 
  • os.Args是一个数组 var Args []string,通过输入获取到,然后把这个客户端输入的内容传送到服务端,服务端做些操作,然后在返回给客户端
  • Go已经提供了RPC良好的支持,通过HTTP TCP JSONRPC的实现,可以很方便开发分布式的Web应用,但是我目前还不会,在学习中。遗憾的是Go没有提供SOAP RPC的支持~~~

相关文章