Go - RPC
参考
https://geektutu.com/post/quick-go-rpc.html
RPC简介
RPC(Remote Procedure Call)远程过程调用,计算机通信协议的一种
RPC下 调用程序 会放置client节点的机器,被调方法子程序 会放置Server节点的机器, client通过向Server发送请求、Server回调响应来获取 调用程序 的 结果
调用方和执行方分别在不同的机器上
本地调用的例子
$ mkdir ./goRpc && cd goRpc && go mod init goRpc
$ vi main.go
package main
import(
"fmt"
)
type Result struct {
Num int
Ret int
}
type Cal int
func (cal *Cal) Square(num int) *Result{
return &Result{
Num: num,
Ret: num*num,
}
}
func main(){
c := new(Cal)
ret := c.Square(8)
fmt.Println(ret)
fmt.Println(ret.Num)
fmt.Println(ret.Ret)
}
$ go run main.go
&{8 64}
8
64$
RPC被调用子方法需要满足的条件
func (t *T) MethodName(argType T1, replyType *T2) error
方法类型(T)是导出的(首字母大写)
方法名(MethodName)是导出的
方法有2个参数(argType T1, replyType *T2),均为导出/内置类型
方法的第2个参数一个指针(replyType *T2)
方法的返回值类型是 error
// 改造Square函数
...
func (cal *Cal) Square(num int, ret *Result) error{
ret.Num = num
ret.Ret = num * num
return nil
}
...
RPC 服务与调用
创建服务端
$ mkdir goRPC_server && cd goRPC_server && go mod init goRPC_server
$ vi server.go
package main
import(
"fmt"
"net/rpc"
"net/http"
)
type Result struct {
Num int
Ret int
}
type Cal int
func (cal *Cal) Square(num int, ret *Result) error{
ret.Num = num
ret.Ret = num * num
return nil
}
func main(){
rpc.Register(new(Cal))
rpc.HandleHTTP()
fmt.Println("server running on port 8080...")
if err := http.ListenAndServe(":8080", nil);err != err{
fmt.Println("error: ", err)
}
}
$ go run server.go
server running on port 8080...
创建客户端(同步调用)
$ mkdir goRPC_client && cd goRPC_client && go mod init goRPC_client
$ vi client.go
package main
import(
"fmt"
"net/rpc"
)
type Result struct {
Num int
Ret int
}
func main(){
var ret Result
client, err := rpc.DialHTTP("tcp", ":8080")
if err != nil{
fmt.Println("create rpc client error: ", err)
return
}
if err := client.Call("Cal.Square", 8, &ret);err != nil{
fmt.Println("failed to call Cal.Square: ", err)
return
}
fmt.Printf("success to call Cal.Square of 8: %d\n", ret.Ret)
}
$ go run client.go
success to call Cal.Square of 8: 64
创建客户端(异步调用)
package main
import(
"fmt"
"net/rpc"
)
type Result struct {
Num int
Ret int
}
func main(){
var ret Result
client, err := rpc.DialHTTP("tcp", ":8080")
if err != nil{
fmt.Println("create rpc client error: ", err)
return
}
asyCall := client.Go("Cal.Square", 8, &ret, nil)
<-asyCall.Done // 阻塞当前程序直到 RPC 调用结束
fmt.Printf("success to call Cal.Square of 8: %d\n", ret.Ret)
}