RPC入门

449 阅读2分钟

文章同步发布到www.crownblog.icu/post/rpc_01…

什么是RPC

RPC 代指远程过程调用(Remote Procedure Call),==是分布式系统中不同节点间流行的通信方式==,它的调用包含了传输协议和编码(对象序列号)协议等等。允许运行于一台计算机的程序调用另一台计算机的子程序,而开发人员无需额外地为这个交互作用编程。

实际场景:

有两台服务器,分别是A、B。在 A 上的应用 C 想要调用 B 服务器上的应用 D,它们可以直接本地调用吗?

答案是不能的,但走 RPC 的话,十分方便。因此常有人称使用 RPC,就跟本地调用一个函数一样简单。

常见 RPC 框架

image.png

RPC版"Hello, World"

基本步骤:

  • 服务端
  1. 注册服务

rpc.RegisterName("服务名", 对象)

  1. 监听端口

listener, err := net.Listen("tcp", ":1234")

  1. 建立连接 conn, err := listener.Accept()

  2. 将连接绑定rpc服务

rpc.ServeConn(conn)

  • 客户端
  1. rpc连接服务

client, err := rpc.Dial("tcp", "localhost:1234")

  1. 远程调用函数

client.Call("服务名.方法名", 传入参数, 传出参数)

构造一个HelloService类型,其中的Hello方法用于实现打印功能:

type HelloService struct {}

func (p *HelloService) Hello(request string, reply *string) error {
    *reply = "hello:" + request
    return nil
}

其中Hello方法必须满足Go语言的RPC规则:

  • 方法是导出的(首字母大写)
  • 方法有两个参数,都是导出类型(如struct)或内建类型(如int)
  • 方法的第二个参数是指针
  • 方法只有一个error接口类型的返回值

将HelloService类型的对象注册为一个RPC服务:

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

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

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

    rpc.ServeConn(conn)
}

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

客户端请求HelloService服务:

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

    var reply string
    err = client.Call("HelloService.Hello", "hello", &reply)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(reply)
}

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

参考:

studygolang.com/pkgdoc

chai2010.gitbooks.io/advanced-go…