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 机制