go語言遊戲服務端開發(四)——RPC機制
阿新 • • 發佈:2021-10-08
五邑隱俠,本名關健昌,12年遊戲生涯。 本教程以Go語言為例。
RPC指遠端方法呼叫,遊戲裡引入RPC目的是降低跨程序互動的複雜度。 遊戲業務設計為多go routine,一個玩家一個go routine。遊戲裡RPC客戶端阻塞式呼叫遠端(服務程序)方法,這樣處理的好處是跨程序互動的業務也可以按照單執行緒順序執行的思路實現。 RPC請求包由以下幾部分組成:標記(字串,用於區分是哪類呼叫)、序列號(一次呼叫的唯一標記)、方法編號(用於對映呼叫的方法)、引數。 RPC響應包由以下幾部分組成:標記、序列號、方法編號、返回值。typeRpcRequeststruct{ Mark[]byte FuncNouint16 SerialNouint16 Params[]RPC建立在P2P網路之上,在 P2pListener interface 的 OnP2pCall(p2p*P2pNet,pack*P2pPack) 實現方法,根據包頭前幾個位元組與 Mark 對比,如果一致則呼叫對應的RPC客戶端/服務端進行處理。 對於RPC服務,可以參考http服務,建立方法編號到處理方法的對映。byte } typeRpcResponsestruct{ Mark[]byte FuncNouint16 SerialNouint16 ReturnVal[]byte }
typeRpcHandlerfunc(params[]byte)([]byte,error) typeRpcServ當收到請求後,解析出funcNo和引數Params,呼叫對應的處理器進行處理。struct{ p2p*P2pNet mark[]byte mapFuncNo2Handlermap[uint16]RpcHandler } func(s*RpcServ)HandleFunc(funcNouint16,handlerfunc(params[]byte)([]byte,error)){ ifhandler==nil{ return }
s.mapFuncNo2Handler[funcNo]=handler }
handler,ok:=s.mapFuncNo2Handler[rpc.FuncNo]RPC服務對請求的處理可以是非阻塞的。 一般只對RPC客戶端做成阻塞的,這樣在客戶端呼叫遠端方法時,客戶端會一直等待服務端返回才繼續往下執行,整個邏輯流程跟單執行緒執行一樣。 通過序列號SerialNo、方法號 FuncNo 雙重確認響應包對應於當前請求。 在go語言裡,可以通過定義一個長度為1的 chan byte,請求發出後,讀取通道,如果還沒有收到響應就會阻塞,響應返回時往通道里寫個1,喚醒呼叫流程繼續執行。if!ok{ returnfmt.Errorf("nohandlerforfuncNo%d",rpc.FuncNo) }
returnVal,err:=handler(rpc.Params)
funcWait(e chan byte){ <-e } func Signal(e chan byte) { e <- 1 }呼叫方法的引數和返回值都是二進位制,業務可以根據自己的需要用json或 protobuff 進行序列化/反序列化。
func(c*RpcClient)invoke(params[]byte)([]byte,error)RPC呼叫介紹到這裡。接下來介紹下游戲業務程序的實現。