go 原生rpc使用详解

实现RPC调用几大要素

  • 概念: 像调用本地方法一样调用远程方法, 要实现类似的效果就必须满足一些规则,即以下几大要素
  • CALLID映射(服务端和客户端都需要有一个映射表, 服务端通过表知道客户端调用的是那个方法),
  • 序列化和反序列化(数据协议, 参数无法直接传输, 需要序列化成双方都知道的协议进行传输, 数据协议压缩的越小传递的字节就越小, 传递速度也就越快, 常用的json就是一种数据协议,但是压缩比率并不高,故性能也不高)
  • 网络传输协议(HTTP, TCP 等)

HTTP实现一个简单的RPC

  • CALLID映射通过URL, 数据协议使用URL参数, 网络传输协议使用HTTP

服务端代码

func main() {
	http.HandleFunc("/add", func(w http.ResponseWriter, r *http.Request) {
		_ = r.ParseForm()
		fmt.Println(fmt.Sprintf("路径:%v",r.URL.Path))
		a, _ := strconv.Atoi(r.Form.Get("a"))
		b, _ := strconv.Atoi(r.Form.Get("b"))
		jData,_ := json.Marshal(map[string]int{
			"data":a+b,
		})
		_, _ = w.Write(jData)
	})
	_ = http.ListenAndServe(":8000", nil)
}

客户端代码

type ResponseData struct {
	Data int `json:"data"`
}
func add(a, b int) int {
	req := HttpRequest.NewRequest()
	resp, _ := req.Get(fmt.Sprintf("http://127.0.0.1:8000/%v?a=%v&b=%v","add",a,b))
	resBody, _ := resp.Body()
	respData := &ResponseData{}
	_ = json.Unmarshal(resBody, respData)
	return respData.Data
	
}
func main() {
	total := add(1,2)
	fmt.Println(total)
}

go 原生RPC调用

  • go的默认的rpc使用gob数据协议, 是go自己定义的一种数据传输协议,效率比json高,但是通用性较差, 无法跨语言调用

服务端代码

type HelloService struct {
}

func (receiver *HelloService) Hello(arg string, reply *string) error {
	*reply = "hello " + arg
	return nil
}
func main() {
	// 创建一个server实例
	listen, _ := net.Listen("tcp", ":1234")
	// 注册rpc函数
	_ = rpc.RegisterName("HelloService", &HelloService{})
	// 启动server
	for {
		accept, _ := listen.Accept()
		go rpc.ServeConn(accept) // 进入的链接让rpc来执行
	}
}

客户端代码

func main() {
	// rpc 拨号
	dial, err := rpc.Dial("tcp", "127.0.0.1:1234")
	if err != nil {
		panic(err)
	}
	// 调用
	var reply string
	_ = dial.Call("HelloService.Hello", "rpc2", &reply)
	fmt.Println(reply)
}

go原生rpc使用json数据协议进行调用示例

  • 使用json数据协议是当前的一个示例, 也可以自定义其他数据协议

服务端代码

type HelloService struct {
}

func (receiver *HelloService) Hello(arg string, reply *string) error {
	*reply = "hello " + arg
	return nil
}
func main() {
	// 创建一个server实例
	listen, _ := net.Listen("tcp", ":1234")
	// 注册rpc函数
	_ = rpc.RegisterName("HelloService", &HelloService{})
	// 启动server
	for {
		accept, _ := listen.Accept()
		// 进入的链接让rpc来执行,并设置rpc的编解码使用json数据协议
		go rpc.ServeCodec(jsonrpc.NewServerCodec(accept))
	}
}

客户端代码

func main() {
	// rpc 拨号
	conn, err := net.Dial("tcp", "127.0.0.1:1234")
	if err != nil {
		panic(err)
	}
	// 调用
	var reply string
	// 设置发送rpc,使用json 编码解码
	client := rpc.NewClientWithCodec(jsonrpc.NewClientCodec(conn))
	_ = client.Call("HelloService.Hello", "rpc2", &reply)
	fmt.Println(reply)
}

你可能感兴趣的:(golang,golang,rpc,开发语言)