golang RPC 應用(1) :net/rpc的應用

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

RPC(Remote Procedure Call)—遠端程序呼叫,它是一種通過網路從遠端電腦程式上請求服務,而不需要瞭解底層網路技術的協議。RPC協議假定某些傳輸協議的存在,如TCP或UDP,為通訊程式之間攜帶資訊資料。在OSI網路通訊模型中,RPC跨越了傳輸層和應用程式層。RPC使得開發包括網路分布式多程式在內的應用程式更加容易。---百度百科
實際後台開發中,rpc是伺服器與伺服器互動的方式之一,隱藏底層網路實現,代碼程式化,開發效率高,BUG少。

通過一個簡單的demo來說明go官方rpc包的應用。
項目結構:

rpc    ----Makefile    ----src        ----client            ----main.go        ----protocol            ----type.go        ----server            ----main.go

rpc/Makefile

GOPATH := $(shell pwd)all:    GOPATH=${GOPATH} go install client    GOPATH=${GOPATH} go install server

rpc/protocol/type.go

package protocolconst(    RPC_ADDITION = "Calculator.Addition"    RPC_SUBTRACTION = "Calculator.Subtraction"    RPC_MULTIPLICATION = "Calculator.Multiplication"    RPC_DIVISION = "Calculator.Division")type Param struct {    A int32    B int32}

RPC用戶端實現,包含同步(Call)和非同步(Go)調用方式,通常為了效率會使用非同步方式。
rpc/src/client/main.go

package mainimport "net/rpc"import (    . "protocol"    "fmt"    "time")var (    _CLIENT  *rpc.Client    _RPC_MSG chan *rpc.Call    _CAN_CANCEL chan bool)func main()  {    DialRpcServer()    //起個協程處理非同步rpc調用結果    go loop()    //測試同步的方式調用rpc服務    param := Param{A:int32(10),B:int32(30)}    reply := int32(0)    SyncCallRpcFunc(RPC_ADDITION, &param, &reply)    fmt.Printf("Sync Call Addition Result %d \n", reply)    SyncCallRpcFunc(RPC_SUBTRACTION, &param, &reply)    fmt.Printf("Sync Call Subtraction Result %d \n", reply)    ////測試非同步方式調用rpc服務    ASyncCallRpcFunc(RPC_MULTIPLICATION, &param, &reply)    ASyncCallRpcFunc(RPC_DIVISION, &param, &reply)    //阻塞等待非同步呼叫完成    <- _CAN_CANCEL}func init(){    _RPC_MSG = make(chan *rpc.Call, 1024)    _CAN_CANCEL = make(chan bool)}func DialRpcServer(){    c, e := rpc.DialHTTP("tcp", "127.0.0.1:2311")    if e != nil {        fmt.Errorf("Dial RPC Error %s", e.Error())    }    _CLIENT = c}//重連RPC伺服器func ReDialRpcServer() bool{    c, e := rpc.DialHTTP("tcp", "127.0.0.1:2311")    if e != nil {        fmt.Printf("ReDial RPC Error %s \n", e.Error())        return false    }    _CLIENT = c    fmt.Println("ReDial Rpc Server Succ")    return true}//同步rpc調用func SyncCallRpcFunc(method string, args interface{}, reply interface{}){    if nil == _CLIENT{        for{//如果斷線就等到重連上為止            if ReDialRpcServer(){                break            }            time.Sleep(5000 * time.Millisecond)        }    }    _CLIENT.Call(method, args, reply)}//非同步rpc調用func ASyncCallRpcFunc(method string, args interface{}, reply interface{}){    if nil == _CLIENT{        for{//如果斷線就等到重連上為止            if ReDialRpcServer(){                break            }            time.Sleep(5000 * time.Millisecond)        }    }    // Go(serviceMethod string, args interface{}, reply interface{}, done chan *Call)的done如果填nil會構建個新的channel用於接受結果    _CLIENT.Go(method, args, reply, _RPC_MSG)}//接收非同步呼叫的返回func loop(){    for{        select {        case rpcMsg, ok := <- _RPC_MSG:            if !ok{                fmt.Errorf("Rpc Call Error")            }            rpcMsgHandler(rpcMsg)        }    }    _CAN_CANCEL <- true}// 處理非同步rpc的傳回值func rpcMsgHandler(msg * rpc.Call){    switch msg.ServiceMethod {    case RPC_ADDITION:        reply := msg.Reply.(*int32)        fmt.Printf("Addtoion Result [%d] \n", *reply)    case RPC_SUBTRACTION:        reply := msg.Reply.(*int32)        fmt.Printf("Subtraction Result [%d] \n", *reply)    case RPC_MULTIPLICATION:        reply := msg.Reply.(*int32)        fmt.Printf("Multiplication Result [%d] \n", *reply)    case RPC_DIVISION:        reply := msg.Reply.(*int32)        fmt.Printf("Division Result [%d] \n", *reply)    default:        fmt.Errorf("Can Not Handler Reply [%s] \n", msg.ServiceMethod)    }}

RPC伺服器的實現。
rpc/src/server/main.go

package mainimport "net/rpc"import (    . "protocol"    "errors"    "net"    "fmt"    "net/http")type Calculator struct {}var (    _DATA *Calculator    _CAN_CANCEL chan bool)func main()  {    runRpcServer()}func init(){    _DATA = new(Calculator)    _CAN_CANCEL = make(chan bool)}func runRpcServer(){    //rpc包裡面定義了個DefaultServer,預設的Register和HandleHTTP均是對DefaultServer作的操作,如果想定製新的Server,就自己寫    rpc.Register(_DATA)    rpc.HandleHTTP()    l,e := net.Listen("tcp","127.0.0.1:2311")    if e != nil{        fmt.Errorf("Create Listener Error %s", e.Error())    }    go http.Serve(l, nil)    //阻塞主進程,等待用戶端輸入    <-_CAN_CANCEL}//輸出方法的格式要求:func (t *T) MethodName(argType T1, replyType *T2) errorfunc (*Calculator) Addition(param *Param, reply *int32) error{    *reply = param.A + param.B    return nil}func (*Calculator) Subtraction(param *Param, reply *int32) error{    *reply = param.A - param.B    return nil}func (*Calculator) Multiplication(param *Param, reply *int32) error{    *reply = param.A * param.B    return nil}func (*Calculator) Division(param *Param, reply *int32) error{    if 0 == param.B{        return errors.New("divide by zero")    }    *reply = param.A/param.B    return nil}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.