本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循 署名-非商业用途-保持一致 的创作共用协议.
RPC(Remote Procedure Call)是 分布式系统
中的一个关键机制.
// 基于官方的example packagemain import( "fmt" "net" "net/rpc" "log" "net/http" ) typeArgsstruct{// 参数封装 A, B int } typeArithint func(t *Arith) Multiply(args *Args, reply *int) error { *reply = args.A * args.B returnnil } funcmakeService() { /* func Register(rcvr interface{}) error 将Service(Arith)注册到默认的Server中 */ rpc.Register(new(Arith)) /* func HandleHTTP() RPC消息有HTTP Handler来处理, Handler注册到默认的Server */ rpc.HandleHTTP() /* func Listen(net, laddr string) (Listener, error) 第一个参数为面向流的网络("tcp", "tcp4", "tcp6", "unix", "unixpacket"). 第二个参数为字符串形式的地址, 如"127.0.0.1:1234", 省略host表示可以监听所有host */ l, e := net.Listen("tcp",":1234") ife !=nil{ log.Fatal("listen error:", e) } /* func Serve(l net.Listener, handler Handler) error */ gohttp.Serve(l,nil) } funcmakeClient() { /* func DialHTTP(network, address string) (*Client, error) 参数类似于net.Listen */ client, err := rpc.DialHTTP("tcp","127.0.0.1"+":1234") deferclient.Close()// 延迟关闭client iferr !=nil{ log.Fatal("dialing:", err) } args := &Args{7,8} varreplyint /* func (client *Client) Call(serviceMethod string, args interface{}, reply interface{}) error client的方法, 第一个参数为调用服务的方法, 第二个参数方法需要的参数, 第三个参数为执行结果 */ err = client.Call("Arith.Multiply", args, reply) iferr !=nil{ log.Fatal("Arith rpc call error:", err) } fmt.Println(reply) } funcmain() { // 只是为了一个启动使用了goroutine,正常情况应该分别启动一个客户端和一个服务器 makeService() makeClient() }
packagemain import( "fmt" "net" "net/rpc" "log" "net/http" "net/rpc/jsonrpc" ) typeArgsstruct{// 参数封装 A, B int } typeArithint func(t *Arith) Multiply(args *Args, reply *int) error { *reply = args.A * args.B returnnil } // 使用json作为rpc funcmakeJSONService() { rpc.Register(new(Arith)) tcpAddr, err := net.ResolveTCPAddr("tcp",":1234") iferr !=nil{ panic(err) } /* ListenTCP 类似于 Listen. func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) 第一个参数为面向流的网络("tcp", "tcp4", or "tcp6"). 第二个参数为字符串形式的地址, 如"127.0.0.1:1234", 省略host表示可以监听所有host */ listener, err := net.ListenTCP("tcp", tcpAddr) iferr !=nil{ panic(err) } gofunc() { for{ conn, err := listener.Accept() iferr !=nil{ continue } // 注意此处的不同 /* func ServeConn(conn io.ReadWriteCloser) 此函数阻塞运行一个JSON-RPC */ jsonrpc.ServeConn(conn) } }() } funcmakeJSONClient() { // JSON-rpc的客户端基本和TCP一样 client, err := jsonrpc.Dial("tcp","127.0.0.1:1234") iferr !=nil{ log.Fatal("dialing:", err) } // Synchronous call args := &Args{17,8} varreplyint err = client.Call("Arith.Multiply", args, &reply) iferr !=nil{ log.Fatal("Arith rpc call error:", err) } fmt.Println(reply) }
数据结构:
Network
用于模拟网络, 使整个RPC调用过程中在内部发生, 不需要真正的执行网路请求 Server
一个RPC Server, 内部包含多个注册的Service ClientEnd
表示RPC客户端的数据结构 Service
用于客户端来注册struct, 然后封装入该数据结构 reqSrc
RPC调用的参数被解析然后重新封装到整个数据结构中 replyMsg
封装RPC调用的返回结果 架构(可以选择性忽略Network部分)