RPC,即 Remote Procedure Call(遠端程序呼叫),說得通俗一點就是:調用遠端電腦上的服務,就像調用本地服務一樣。
我所在公司的項目是採用基於Restful的微服務架構,隨著微服務之間的溝通越來越頻繁,就希望可以做成用rpc來做內部的通訊,對外依然用Restful。於是就想到了golang標準庫的rpc包和google的grpc。
這篇文章重點瞭解一下golang的rpc包。
介紹
golang的rpc支援三個層級的RPC:TCP、HTTP、JSONRPC。但Go的RPC包是獨一無二的RPC,它和傳統的RPC系統不同,它只支援Go開發的伺服器與用戶端之間的互動,因為在內部,它們採用了Gob來編碼。
Go RPC的函數只有符合下面的條件才能被遠端存取,不然會被忽略,詳細的要求如下:
函數必須是匯出的(首字母大寫)
必須有兩個匯出類型的參數,
第一個參數是接收的參數,第二個參數是返回給客- 戶端的參數,第二個參數必須是指標類型的
函數還要有一個傳回值error
舉個例子,正確的RPC函數格式如下:
func(t *T) MethodName(argType T1, replyType *T2)error
T、T1和T2類型必須能被encoding/gob包編解碼。
樣本
舉一個http的例子。
下面是http伺服器端的代碼:
packagemainimport("errors""net""net/rpc""log""net/http")typeArgsstruct{ A, Bint}typeQuotientstruct{ Quo, Remint}typeArithintfunc(t *Arith) Multiply(args *Args, reply *int)error{ *reply = args.A * args.Breturnnil}func(t *Arith) Divide(args *Args, quo *Quotient)error{ifargs.B ==0{returnerrors.New("divide by zero") } quo.Quo = args.A / args.B quo.Rem = args.A % args.Breturnnil}funcmain() { arith :=new(Arith) rpc.Register(arith) rpc.HandleHTTP() l, e := net.Listen("tcp",":1234")ife !=nil{ log.Fatal("listen error:", e) } http.Serve(l,nil)}
簡單分析一下上面的例子,先執行個體化了一個Arith對象arith,然後給arith註冊了rpc服務,然後把rpc掛載到http服務上面,當http服務開啟的時候我們就可以通過rpc用戶端來調用arith中符合rpc標準的的方法了。
請看用戶端的代碼:
packagemainimport("net/rpc""log""fmt")typeArgsstruct{ A, Bint}typeQuotientstruct{ Quo, Remint}funcmain() { client, err := rpc.DialHTTP("tcp","127.0.0.1:1234")iferr !=nil{ log.Fatal("dialing:", err) }// Synchronous callargs := &Args{7,8}varreplyinterr = client.Call("Arith.Multiply", args, &reply)iferr !=nil{ log.Fatal("arith error:", err) } fmt.Printf("Arith: %d*%d=%d\n", args.A, args.B, reply)// Asynchronous callquotient :=new(Quotient) divCall := client.Go("Arith.Divide", args, quotient,nil) replyCall := <-divCall.Done// will be equal to divCallifreplyCall.Error !=nil{ log.Fatal("arith error:", replyCall.Error) } fmt.Printf("Arith: %d/%d=%d...%d", args.A, args.B, quotient.Quo, quotient.Rem)// check errors, print, etc.}
簡單說明下,先用rpc的DialHTTP方法串連伺服器端,調用伺服器端的函數就要使用Call方法了,Call方法的參數和傳回值已經很清晰的表述出rpc整體的調用邏輯了。
我們把伺服器端跑起來,再把用戶端跑起來,這時候用戶端會輸出:
Arith:7*8=56Arith:7/8=0...7
到此,整個rpc的調用邏輯就完成了。