1、RPC (Remote Procedure Call) 远程过程调用 (一个节点请求另一个节点提供的服务)
2、对应 RPC 的是本地过程调用,函数调用是最常见的本地过程调用
3、将本地过程调用,变成远程过程调用会面临各种问题
go 内置简单 rpc 调用
server 端
package main import ( "net" "net/rpc" ) type HelleService struct { } func (s * HelleService) Hello (request string, reply * string) error { *reply = "hello" + request return nil } func main() { // 实例化一个 server listener, _ := net.Listen("tcp",":1234") // 注册处理逻辑 handler _ = rpc.RegisterName("HelloService", &HelleService{}) // 启动服务 conn,_ := listener.Accept() rpc.ServeConn(conn) }
client 端
package main import ( "fmt" "net/rpc" ) func main() { // 建立连接 client, err := rpc.Dial("tcp","localhost:1234") if err != nil { panic("连接错误") } var reply string err = client.Call("HelloService.Hello","liang", &reply) if err != nil { panic("调用失败") } fmt.Println(reply) }
替换 rpc 的序列化协议为 json (原 Gob)
server 端
func main() { // 实例化一个 server listener, _ := net.Listen("tcp",":1234") // 注册处理逻辑 handler _ = rpc.RegisterName("HelloService", &HelleService{}) // 启动服务 for { conn,_ := listener.Accept() go rpc.ServeCodec(jsonrpc.NewServerCodec(conn)) } }
client 端
func main() { // 建立连接 conn, err := net.Dial("tcp","localhost:1234") if err != nil { panic("连接错误") } var reply string client := rpc.NewClientWithCodec(jsonrpc.NewClientCodec(conn)) err = client.Call("HelloService.Hello","liang", &reply) if err != nil { panic("调用失败") } fmt.Println(reply) }
任何语言都能进行 rpc 访问,如python
替换 rpc 传输协议为 http (原 tcp)
server 端
func main() { // 实例化一个 server _ = rpc.RegisterName("HelloService", &HelleService{}) http.HandleFunc("/wahaha",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) }
测试