参考资料 GO高级编程
一 Rpc入门
RPC是远程过程调用的简称,是分布式系统中不同节点间流行的通信方式。在互联网时代,RPC已经和IPC一样成为一个不可或缺的基础构件。因此Go语言的标准库也提供了一个简单的RPC实现,我们将以此为入口学习RPC的各种用法。
Go语言的RPC包的路径为net/rpc,也就是放在了net包目录下面。因此我们可以猜测该RPC包是建立在net包基础之上的。在第一章“Hello, World”革命一节最后,我们基于http实现了一个打印例子。下面我们尝试基于rpc实现一个类似的例子。 (1)server端
package main
import (
"net"
"net/rpc"
)
type HelloService struct {}
func (h *HelloService) Hello(request string, reply *string) error{
*reply = "hello:" + request
return nil
}
func main() {
err := rpc.RegisterName("HelloService",new(HelloService))
if err != nil {
panic(err)
}
lis ,err := net.Listen("tcp",":1234")
if err != nil {
panic(err)
}
con,err := lis.Accept()
if err != nil {
panic(err)
}
rpc.ServeConn(con)
}
(1)client端
package main
import (
"fmt"
"net/rpc"
)
func main() {
cli,err := rpc.Dial("tcp",":1234")
if err != nil {
panic(err)
}
var reply string
err = cli.Call("HelloService.Hello","你好",&reply)
if err != nil {
panic(err)
}
fmt.Println(reply)
}
二 Http Rpc
Go语言内在的RPC框架已经支持在Http协议上提供RPC服务。但是框架的http服务同样采用了内置的gob协议,并且没有提供采用其它协议的接口,因此从其它语言依然无法访问的。在前面的例子中,我们已经实现了在TCP协议之上运行jsonrpc服务,并且通过nc命令行工具成功实现了RPC方法调用。现在我们尝试在http协议上提供jsonrpc服务。
新的RPC服务其实是一个类似REST规范的接口,接收请求并采用相应处理流程:
package main
import (
"io"
"net/http"
"net/rpc"
"net/rpc/jsonrpc"
)
type HelloService struct{}
func (s *HelloService) Hello(request string, reply *string) error {
*reply = "hello, " + request
return nil
}
func main() {
_ = rpc.RegisterName("HelloService", &HelloService{})
http.HandleFunc("/jsonrpc", func(w http.ResponseWriter, r *http.Request) {
var conn io.ReadWriteCloser = struct {
io.Writer
io.ReadCloser
}{
ReadCloser: r.Body,
Writer: w,
}
rpc.ServeRequest(jsonrpc.NewServerCodec(conn))
})
http.ListenAndServe(":1234", nil)
}
RPC的服务架设在“/jsonrpc”路径,在处理函数中基于http.ResponseWriter和http.Request类型的参数构造一个io.ReadWriteCloser类型的conn通道。然后基于conn构建针对服务端的json编码解码器。最后通过rpc.ServeRequest函数为每次请求处理一次RPC方法调用。
模拟一次RPC调用的过程就是向该链接发送一个json字符串:
curl localhost:1234/jsonrpc -X POST \
--data '{"method":"HelloService.Hello","params":["hello"],"id":0}'
|