zoukankan      html  css  js  c++  java
  • go语言游戏服务端开发(三)——服务机制

    五邑隐侠,本名关健昌,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 机制
  • 相关阅读:
    图片轮播切换
    php用get_meta_tags轻松获取网页的meta信息
    PHP创建桌面快捷方式实例
    php 获取网站根目录的写法
    php mkdir 创建多级目录实例代码
    php计算剩余时间的自定义函数
    php实现获取汉字的首字母实例
    PDO封装函数
    Struts动态表单(DynamicForm)
    [WPF]静态资源(StaticResource)和动态资源(DynamicResource)
  • 原文地址:https://www.cnblogs.com/niudanshui/p/15309838.html
Copyright © 2011-2022 走看看