服务中没有listen_Go语言微服务框架实战:2.Go语言实现RPC编程绍
Go語言實(shí)現(xiàn)RPC編程
@author:Davie 版權(quán)所有:北京千鋒互聯(lián)科技有限公司
上節(jié)課我們對RPC知識做了介紹,講解了RPC的原理,通過圖示方式講解了RPC的內(nèi)部執(zhí)行過程。本節(jié)課,我們繼續(xù)來學(xué)習(xí)RPC相關(guān)的內(nèi)容。
RPC官方庫
在Go語言官方網(wǎng)站的pkg說明中,提供了官方支持的rpc包,具體鏈接如下:https://golang.org/pkg/net/rpc/。官方提供的rpc包完整的包名是:net/rpc。根據(jù)官方的解釋,rpc包主要是提供通過網(wǎng)絡(luò)訪問一個(gè)對象方法的功能。
本節(jié)課,我們就來學(xué)習(xí)如何使用go語言官方提供的RPC包實(shí)現(xiàn)RPC調(diào)用編碼。
net/rpc庫實(shí)現(xiàn)RPC調(diào)用編程
前文我們已經(jīng)講過rpc調(diào)用有兩個(gè)參與者,分別是:客戶端(client)和服務(wù)器(server)。
首先是提供方法暴露的一方--服務(wù)器。
一、服務(wù)定義及暴露
在編程實(shí)現(xiàn)過程中,服務(wù)器端需要注冊結(jié)構(gòu)體對象,然后通過對象所屬的方法暴露給調(diào)用者,從而提供服務(wù),該方法稱之為輸出方法,此輸出方法可以被遠(yuǎn)程調(diào)用。當(dāng)然,在定義輸出方法時(shí),能夠被遠(yuǎn)程調(diào)用的方法需要遵循一定的規(guī)則。我們通過代碼進(jìn)行講解:
func (t *T) MethodName(request T1,response *T2) error上述代碼是go語言官方給出的對外暴露的服務(wù)方法的定義標(biāo)準(zhǔn),其中包含了主要的幾條規(guī)則,分別是: 1、對外暴露的方法有且只能有兩個(gè)參數(shù),這個(gè)兩個(gè)參數(shù)只能是輸出類型或內(nèi)建類型,兩種類型中的一種。 2、方法的第二個(gè)參數(shù)必須是指針類型。 3、方法的返回類型為error。 4、方法的類型是可輸出的。 * 5、方法本身也是可輸出的。
我們舉例說明:假設(shè)目前我們有一個(gè)需求,給出一個(gè)float類型變量,作為圓形的半徑,要求通過RPC調(diào)用,返回對應(yīng)的圓形面積。具體的編程實(shí)現(xiàn)思路如下:
type MathUtil struct{ } //該方法向外暴露:提供計(jì)算圓形面積的服務(wù) func (mu *MathUtil) CalculateCircleArea(req float32, resp *float32) error {*resp = math.Pi * req * req //圓形的面積 s = π * r * rreturn nil //返回類型 }在上述的案例中,我們可以看到: 1、Calculate方法是服務(wù)對象MathUtil向外提供的服務(wù)方法,該方法用于接收傳入的圓形半徑數(shù)據(jù),計(jì)算圓形面積并返回。 2、第一個(gè)參數(shù)req代表的是調(diào)用者(client)傳遞提供的參數(shù)。 3、第二個(gè)參數(shù)resp代表要返回給調(diào)用者的計(jì)算結(jié)果,必須是指針類型。 4、正常情況下,方法的返回值為是error,為nil。如果遇到異常或特殊情況,則error將作為一個(gè)字符串返回給調(diào)用者,此時(shí),resp參數(shù)就不會再返回給調(diào)用者。
至此為止,已經(jīng)實(shí)現(xiàn)了服務(wù)端的功能定義,接下來就是讓服務(wù)代碼生效,需要將服務(wù)進(jìn)行注冊,并啟動請求處理。
二、注冊服務(wù)及監(jiān)聽請求
net/rpc包為我們提供了注冊服務(wù)和處理請求的一系列方法,結(jié)合本案例實(shí)現(xiàn)注冊及處理邏輯,如下所示:
//1、初始化指針數(shù)據(jù)類型 mathUtil := new(MathUtil) //初始化指針數(shù)據(jù)類型//2、調(diào)用net/rpc包的功能將服務(wù)對象進(jìn)行注冊 err := rpc.Register(mathUtil) if err != nil {panic(err.Error()) }//3、通過該函數(shù)把mathUtil中提供的服務(wù)注冊到HTTP協(xié)議上,方便調(diào)用者可以利用http的方式進(jìn)行數(shù)據(jù)傳遞 rpc.HandleHTTP()//4、在特定的端口進(jìn)行監(jiān)聽 listen, err := net.Listen("tcp", ":8081") if err != nil {panic(err.Error()) } go http.Serve(listen, nil)經(jīng)過服務(wù)注冊和監(jiān)聽處理,RPC調(diào)用過程中的服務(wù)端實(shí)現(xiàn)就已經(jīng)完成了。接下來需要實(shí)現(xiàn)的是客戶端請求代碼的實(shí)現(xiàn)。
三、客戶端調(diào)用
在服務(wù)端是通過Http的端口監(jiān)聽方式等待連接的,因此在客戶端就需要通過http連接,首先與服務(wù)端實(shí)現(xiàn)連接。
- 客戶端連接服務(wù)端go client, err := rpc.DialHTTP("tcp", "localhost:8081") if err != nil { panic(err.Error()) }
- 遠(yuǎn)端方法調(diào)用 客戶端成功連接服務(wù)端以后,就可以通過方法調(diào)用調(diào)用服務(wù)端的方法,具體調(diào)用方法如下:
```go var req float32 //請求值 req = 3
var resp float32 //返回值 err = client.Call("MathUtil.CalculateCircleArea", req, &resp) if err != nil { panic(err.Error()) } fmt.Println(resp) ```
上述的調(diào)用方法核心在于client.Call方法的調(diào)用,該方法有三個(gè)參數(shù),第一個(gè)參數(shù)表示要調(diào)用的遠(yuǎn)端服務(wù)的方法名,第二個(gè)參數(shù)是調(diào)用時(shí)要傳入的參數(shù),第三個(gè)參數(shù)是調(diào)用要接收的返回值。 上述的Call方法調(diào)用實(shí)現(xiàn)的方式是同步的調(diào)用,除此之外,還有一種異步的方式可以實(shí)現(xiàn)調(diào)用。異步調(diào)用代碼實(shí)現(xiàn)如下:go var respSync *float32 //異步的調(diào)用方式 syncCall := client.Go("MathUtil.CalculateCircleArea", req, &respSync, nil) replayDone := <-syncCall.Done fmt.Println(replayDone) fmt.Println(*respSync)
多參數(shù)的請求調(diào)用參數(shù)傳遞
上述內(nèi)容演示了單個(gè)參數(shù)下的RPC調(diào)用,對于多參數(shù)下的請求該如何實(shí)現(xiàn)。我們通過另外一個(gè)案例進(jìn)行演示。
假設(shè)現(xiàn)在需要實(shí)現(xiàn)另外一個(gè)需求:通過RPC調(diào)用實(shí)現(xiàn)計(jì)算兩個(gè)數(shù)字相加功能并返回計(jì)算結(jié)果。此時(shí),就需要傳遞兩個(gè)參數(shù),具體實(shí)現(xiàn)如下:
將參數(shù)定義在一個(gè)新的結(jié)構(gòu)體中,存放在param包中:
type AddParma struct {Args1 float32 //第一個(gè)參數(shù)Args2 float32 //第二個(gè)參數(shù) }在server.go文件中,實(shí)現(xiàn)兩數(shù)相加的功能,并實(shí)現(xiàn)服務(wù)注冊的邏輯:
func (mu *MathUtil) Add(param param.AddParma, resp *float32) error {*resp = param.Args1 + param.Args2 //實(shí)現(xiàn)兩數(shù)相加的功能return nil } mathUtil := new(MathUtil)err := rpc.RegisterName("MathUtil", mathUtil)if err != nil {panic(err.Error())}rpc.HandleHTTP()listen, err := net.Listen("tcp", ":8082")http.Serve(listen, nil)在本案例中,我們通過新的注冊方法rpc.RegisterName實(shí)現(xiàn)了服務(wù)的注冊和調(diào)用。
至此,我們已經(jīng)完成了net/rpc包的最基礎(chǔ)的使用。
總結(jié)
以上是生活随笔為你收集整理的服务中没有listen_Go语言微服务框架实战:2.Go语言实现RPC编程绍的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 已知旋转矩阵求角度_如何推导旋转矩阵
- 下一篇: 网页加载出现没有合适的负载均衡器_终于讲