标准库的RPC默认采用Go语言特有的gob编码,因此从其它语言调用Go语言实现的RPC服务将比较困难。
在互联网的微服务时代,每个RPC以及服务的使用者都可能采用不同的编程语言,因此跨语言是互联网时代RPC的一个首要条件。
得益于RPC的框架设计,Go语言的RPC其实也是很容易实现跨语言支持的。
Go语言的RPC框架有两个比较有特色的设计:一个是RPC数据打包时可以通过插件实现自定义的编码和解码;另一个是RPC建立在抽象的io.ReadWriteCloser接口之上的,我们可以将RPC架设在不同的通讯协议之上。这里我们将尝试通过官方自带的net/rpc/jsonrpc扩展实现一个跨语言的PPC。
1.服务端
package main
import (
"net"
"net/rpc"
"net/rpc/jsonrpc"
)
type HelloWordService struct{}
func (h *HelloWordService) SayHelloWord(request string, reply *string) error {
*reply = request + " 打印了'Hello Word!'"
return nil
}
func main() {
_ = rpc.RegisterName("HelloWordService",&HelloWordService{})
listener, err := net.Listen("tcp",":8090")
if err != nil {
panic(err)
}
conn,err := listener.Accept()
if err != nil {
panic("建立连接失败!")
}
rpc.ServeCodec(jsonrpc.NewServerCodec(conn))
}
代码中最大的变化是用rpc.ServeCodec函数替代了rpc.ServeConn函数,传入的参数是针对服务端的json编解码器。
2.客户端
package main
import (
"fmt"
"log"
"net"
"net/rpc"
"net/rpc/jsonrpc"
)
func main() {
conn,err := net.Dial("tcp","127.0.0.1:8090")
if err != nil {
log.Fatal("拨号失败!")
}
client := rpc.NewClientWithCodec(jsonrpc.NewClientCodec(conn))
var reply string
err = client.Call("HelloWordService.SayHelloWord","spl",&reply)
if err != nil {
log.Fatal(err)
}
fmt.Println(reply)
}