go語言遊戲服務端開發(三)——服務機制

五邑隱俠 2021-09-18 21:36:12 阅读数:104

五邑隱俠,本名關健昌,12年遊戲生涯。 本教程以Go語言為例。
 
P2P網絡為服務進程間、服務進程與客戶端間通信提供了便利,在這個基礎上可以搭建服務。
在服務層,通信包可以通過定義協議號來確定該包怎樣處理。每個協議號對應一個Processor,Processor定義為一個interface
type Processor interface {
    OnHandleRequest(req *Request, resp *Response) (int32, error)
}

協議號又可以拆分為模塊號和命令號。一個模塊對應一個Service,該模塊下每個命令對應一個Processor,通過map結構做映射

type Service struct {
    mapCmd2Processor map[uint16]Processor
}
Service提供方法添加、删除、獲取Processor
func AddProcessor(cmd uint16, p Processor) error
func GetProcessor(cmd uint16) Processor
func RemoveProcessor(cmd uint16) error
提供個入口方法,把該模塊的Service的請求分發到對應的Processor
func (s *Service) OnHandleRequest(req *Request, resp *Response) (int32, error) {
p, ok := s.mapCmd2Processor[req.Cmd]
    if ok {
        return p.OnHandleRequest(req, resp)
    }
}
服務 Server 是 Service 的集合,通過模塊號進行映射
type Server struct {
    mapMod2Service map[uint16]*Service
    rpc            *Rpc
}
同樣提供方法添加、删除、獲取Service
func AddService(mod uint16, srv *Service) error
func GetService(mod uint16) *Service
func RemoveService(mod uint16) error
這樣當收到一個請求包,對協議號拆分為模塊號和命令號,通過模塊號獲取到對應的Service,調用Service的 OnHandleRequest 進行處理
serv := s.GetService(req.Mod)
if serv != nil {
code, err := serv.OnHandleRequest(req, resp)
}
Server 基於 P2P 層,P2P的包是通用的格式,不同的遊戲服務端進程,都有可能有不同的包格式,例如,客戶端包格式和服務內部通信的包格式是有差別的。為了讓服務通用,引入服務適配器,在請求和響應時做預處理,轉化為通用的 Request 和 Response
type ServerAdapter interface {
    OnRequest(payload []byte) (*Request, error)
    OnResponse(pack *Response) ([]byte, error)
}
type Server struct {
    mapMod2Service map[uint16]*Service
    rpc            *Rpc
adapter        ServerAdapter
}
這樣在服務層都是基於 Request 和 Response進行處理,由具體業務對業務包做轉換
type Request struct {
    Mod      uint16
    Cmd      uint16
    Payload  []byte
}
type Response struct {
    Mod      uint16
    Cmd      uint16
    Payload  []byte
}
服務 Server 還可以提供攔截器,攔截器的好處是對一些階段進行統一處理,而且可以通過插入新攔截器進行擴展,隨時都可以替換這個階段的邏輯(例如從 json 包變成 proto 包、增加二進制頭等),攔截器可以針對3個階段: 請求處理前,請求處理後,響應發送後
type Interceptor interface {
    OnPreHandle(req *Request, resp *Response) (int32, error)
    OnHandleCompletion(req *Request, resp *Response) (int32, error)
    OnResponseCompletion(req *Request, resp *Response) error
}
除了全局攔截器,還可以添加針對某個模塊 Service 的攔截器,對某個 Service 做特殊攔截處理
type InterceptorList []Interceptor
type Server struct {
    mapMod2Service map[uint16]*Service
    rpc            *Rpc
adapter        ServerAdapter
globalInterceptors InterceptorList
mapMod2Interceptors map[uint16]InterceptorList
}
這樣一個請求的處理過程就變成
// adapter
req, err := s.adapter.OnRequest(payload)
resp := NewResponse(req)
// prehandle
interList, ok := s.mapMod2Interceptors[req.Mod]
s.prehandle(interList, ok, req, resp)
// handle
serv := s.GetService(req.Mod)
code, err := serv.OnHandleRequest(req, resp)
// handle complete
s.handleCompletion(interList, ok, req, resp)
s.push(resp)
// response complete
s.responseCompletion(interList, ok, req, resp)
服務機制介紹到這裏,接下來聊聊 RPC 機制

 

版权声明:本文为[五邑隱俠]所创,转载请带上原文链接,感谢。 https://gsmany.com/2021/09/20210918213611596o.html