go使用rpc

RPC是远程过程调用的缩写(Remote Procedure Call),通俗地说就是调用远处的一个函数,是分布式系统中不同节点间流行的通信方式。Go语言的标准库提供了一个简单的RPC实现

server端

构造一个Cqh类型,其中的Test方法用于测试打印功能

注意:Test方法必须满足Go语言的RPC规则:

  • 方法只能有两个可序列化的参数
  • 其中第二个参数是指针类型,并且返回一个error类型,同时必须是公开的方法。
func (p *Cqh) Test(request string, reply *string) error {
	*reply = "test:" + request
	return nil
}

服务端程序如下:

func main() {
	rpc.RegisterName("Cqh", new(Cqh))

	listener, err := net.Listen("tcp", ":1234")
	if err != nil {
		log.Fatal("ListenTCP error", err)
	}

	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Fatal("Accept error:", err)
		}
		rpc.ServeConn(conn)
	}
}

其中rpc.Register函数调用会将对象类型中所有满足RPC规则的对象方法注册为RPC函数,所有注册的方法会放在“Cqh”服务空间之下。然后我们建立非阻塞的TCP链接,通过rpc.ServeConn函数在该TCP链接上为对方提供RPC服务。

 

client端

Go语言的RPC库最简单的使用方式是通过Client.Call方法进行同步阻塞调用,该方法的实现如下:

func (client *Client) Call(serviceMethod string, args interface{}, reply interface{}) error {
    call := <-client.Go(serviceMethod, args, reply, make(chan *Call, 1)).Done
    return call.Error
}

首先通过Client.Go方法进行一次异步调用,返回一个表示这次调用的Call结构体。然后等待Call结构体的Done管道返回调用结果。

客户端程序如下:

package main

import (
	"net/rpc"
	"log"
	"fmt"
)

func main() {
	client, err := rpc.Dial("tcp", ":1234")
	if err != nil {
		log.Fatal("dialing", err)
	}

	var reply string

	err = client.Call("Cqh.Test", "hello", &reply)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(reply)
}

rpc.Dial拨号RPC服务,然后通过client.Call调用具体的RPC方法。在调用client.Call时,第一个参数是用点号链接的RPC服务名字和方法名字,第二和第三个参数分别我们定义RPC方法的两个参数。

客户端运行后输出如下:

test:hello

 

由此以看出RPC的使用其实非常简单

posted @ 2018-09-29 16:33  雪山飞猪  阅读(2448)  评论(0编辑  收藏  举报