初识RPC

介绍

RPC 是远程过程调用的简称,是分布式系统中不同节点间流行的通信方式。在互联网时代,RPC 已经和 IPC 一样成为一个不可或缺的基础构件。因此 Go 语言的标准库也提供了一个简单的 RPC 实现,我们将以此为入口学习 RPC 的各种用法。

hello RPC

server端代码

package main

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

type HelloService struct{}

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

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)
}

client代码

package main

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

func main() {
client, err := rpc.Dial("tcp", "localhost:1234")
if err != nil {
panic(err)
}
var reply string
err = client.Call("HelloService.Hello", "hello", &reply)
if err != nil {
log.Fatal(err)
}

fmt.Println(reply)
}

跨语言的RPC

go的RPC默认采用go独有的gob编码,其他语言无法直接调用

基于JSON的RPC

server端

package main

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

type HelloService struct{}

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

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

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)
}

go rpc.ServeCodec(jsonrpc.NewServerCodec(conn))
}
}

client

package main

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

func main() {
client, err := rpc.Dial("tcp", "localhost:1234")
if err != nil {
panic(err)
}
var reply string
err = client.Call("HelloService.Hello", "hello", &reply)
if err != nil {
log.Fatal(err)
}

fmt.Println(reply)
}