说明
本文的目的
- 理解一下rpc协议使用上的区别
- golang下jsonrpc框架的使用
示例
定义RPC协议
import "github.com/pkg/errors"
//定义一个叫做Demo的Rpc服务协议
//包含参数结构和2个不同的参数处理协议
// 返回值通过result指针获取,这点是由RPC服务来定义的
type DemoService struct {
}
//包含1: 参数的个数和类型
type Args struct {
A, B int
}
//包含2: 参数的处理协议 除法协议
func (DemoService) Div(args Args, result *float64) error {
if args.B == 0 {
return errors.New("divide by zero")
}
*result = float64(args.A) / float64(args.B)
return nil
}
//包含2: 参数的处理协议 乘法协议
func (DemoService) Muti(args Args, result *int) error {
*result = args.A * args.B
return nil
}
注册为服务端
package main
import (
"fmt"
"learning_go/rpc/demorpc"
"net"
"net/rpc"
"net/rpc/jsonrpc"
)
func main() {
//注册demoService到rpc框架中,成为当前server的rpc协议之一
rpc.Register(demorpc.DemoService{})
listen, err := net.Listen("tcp", ":9999")
if err!=nil{
panic(err)
}
for {
conn, err := listen.Accept()
if err!=nil{
fmt.Println("Server listens error")
continue
}
go jsonrpc.ServeConn(conn)
}
}
客户端测试
通过telnet测试
telent localhost 9999 链接上后如初参数
"method":"DemoService.Div","params":[{"A":3,"B":4}],"id":1}
=》{"id":1,"result":0.75,"error":null}
{"method":"DemoService.Muti","params":[{"A":3,"B":4}],"id":1}
=>{"id":1,"result":12,"error":null}
说明不同的参数可以调用不同的协议
注意:虽然服务器启动了端口,但是不能通过接口调用,因为接口使用的http协议,会包含http的头部和body,数据格式不符合我们定义的rpc协议
通过客户端测试
package main
import (
"fmt"
"learning_go/rpc/demorpc"
"net"
"net/rpc/jsonrpc"
)
func main() {
conn, err := net.Dial("tcp",":9999")
if err!=nil{
panic(err)
}
var result1 float64
var result2 int
client := jsonrpc.NewClient(conn)
//调用除法
err = client.Call("DemoService.Div",
demorpc.Args{
A: 3,
B: 4,
}, &result1)
fmt.Println(result1,err)
//调用乘法
err = client.Call("DemoService.Muti",
demorpc.Args{
A: 3,
B: 4,
}, &result2)
fmt.Println(result2,err)
}
结论
- 可以自定义server的协议参数和协议动作
- 注册到jsonrpc框架后,可以借助框架实现服务间的rpc调用
- rpc基于自定义协议,而http基于http协议,两者主要在于协议不同
- 协议的本质就是数据交换格式