五邑隐侠,本名关健昌,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 机制

go语言游戏服务端开发(三)——服务机制的更多相关文章

  1. Swift3.0服务端开发(三) Mustache页面模板与日志记录

    本篇博客主要介绍如果在Perfect工程中引入和使用Mustache页面模板与日志记录系统.Mustache页面模板类似于PHP中的smarty模板引擎或者Java中的JSTL标签.当然Mustach ...

  2. kafka客户端和服务端开发(三)

    前面我们已经搭建了kafka的单机和集群环境,分别写了简单的实例代码,对于代码里面使用到的参数并没有做解释.下面我们来详细说一下各个参数的作用. 1. 创建kafka生产者 kafka生产者有3个必选 ...

  3. 俯瞰 Java 服务端开发

    原文首发于 github ,欢迎 star . Java 服务端开发是一个非常宽广的领域,要概括其全貌,即使是几本书也讲不完,该文将会提到许多的技术及工具,但不会深入去讲解,旨在以一个俯瞰的视角去探寻 ...

  4. Swift3.0服务端开发(一) 完整示例概述及Perfect环境搭建与配置(服务端+iOS端)

    本篇博客算是一个开头,接下来会持续更新使用Swift3.0开发服务端相关的博客.当然,我们使用目前使用Swift开发服务端较为成熟的框架Perfect来实现.Perfect框架是加拿大一个创业团队开发 ...

  5. 微服务项目开发学成在线_day01_CMS服务端开发

    05-CMS需求分析-什么是CMS 什么是CMS?CMS (Content Management System)即内容管理系统,不同的项目对CMS的定位不同.CMS有哪些类型? 每个公司对每个项目的C ...

  6. Day01_搭建环境&CMS服务端开发

    学成在线 第1天 讲义-项目概述 CMS接口开发 1 项目的功能构架 1.1 项目背景 受互联网+概念的催化,当今中国在线教育市场的发展可谓是百花齐放.如火如荼. 按照市场领域细分为:学前教育.K12 ...

  7. Swift3.0服务端开发(五) 记事本的开发(iOS端+服务端)

    前边以及陆陆续续的介绍了使用Swift3.0开发的服务端应用程序的Perfect框架.本篇博客就做一个阶段性的总结,做一个完整的实例,其实这个实例在<Swift3.0服务端开发(一)>这篇 ...

  8. 如何有效快速提高Java服务端开发人员的技术水平?

    我相信很多工作了3-5年的开发人员都会经常问自己几个问题: 1.为什么总是感觉技术没有质的提高? 2.如何能够有效和快速的提高自身的技术水平? 3.如何进入到一个牛逼的大公司,认识牛逼的人? 这篇文章 ...

  9. 从架构师视角看是否该用Kotlin做服务端开发?

    前言 自从Oracle收购Sun之后,对Java收费或加强控制的尝试从未间断,谷歌与Oracle围绕Java API的官司也跌宕起伏.虽然Oracle只是针对Oracle JDK8的升级收费,并释放了 ...

  10. RTSP服务端开发概述

    一 概述 RTSP(Real Time Streaming Protocol),RFC2326,实时音视频流传输协议,是TCP/IP协议体系中的一个应用层协议.该协议定义了一对多应用程序如何有效地通过 ...

随机推荐

  1. 记一次 .NET 某WMS仓储打单系统 内存暴涨分析

    一:背景 1. 讲故事 七月中旬有一位朋友加wx求助,他的程序在生产上跑着跑着内存就飙起来了,貌似没有回头的趋势,询问如何解决,截图如下: 和这位朋友聊下来,感觉像是自己在小县城当了个小老板,规律的生 ...

  2. CentOS帮助类语法

    目录 一.man获取帮助信息 二.help获得shell内置命令的帮助信息 三.history查看所有命令历史 补充:Linux常用快捷键 一.man获取帮助信息 基本语法:man [命令或配置文件] ...

  3. Spring学习笔记--面向切面编程(AOP)

    什么是AOP AOP(Aspect Oriented Programming),意为面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的 ...

  4. 关于Tomcat服务器的笔记

    javaWEB的概念: a)什么是 JavaWeb:             JavaWeb 是指,所有通过 Java 语言编写可以通过浏览器访问的程序的总称,叫 JavaWeb. JavaWeb 是 ...

  5. Java服务突然失败:A fatal error has been detected by the Java Runtime Environment的总结

    服务启动以后过段时间自动失败:A fatal error has been detected by the Java Runtime Environment 控制台中的错误信息 A fatal err ...

  6. JavaSE-常用类

    JavaSE-常用类 Obeject Java Object类是所有类的父类,也就是说Java的所有类都继承了Object,子类可以使用Object的所有方法. Object类位于java.lang包 ...

  7. 【Azure 应用服务】App Service For Container 配置Nginx,设置/home/site/wwwroot/目录为启动目录,并配置反向代理

    问题描述 通过Docker Desktop for Linux,配置Nginx镜像后,自定义nginx.conf文件,修改启动目录和对 /out 路径的反向代理到博客园的博文地址 (https://w ...

  8. Linux第一个动态库

    动态库一般以.so结尾,就是shared object的意思. 其基本生成步骤为   ⑴编写函数代码   ⑵编译生成动态库文件,要加上 -shared 和 -fpic 选项 ,     库文件名以li ...

  9. mfc HackerTools防止程序双开

    来自:https://github.com/TonyChen56/HackerTools 1 HANDLE hMutex = CreateMutexA(NULL, FALSE, "GuiSh ...

  10. Best Cow Line

    给定长度为N的字符串s,要构造一个长度为N的字符串T.起初,T是一个空串,随后反复进行下列任意操作. -从S的头部删除一个字符,加到T的尾部 -从S的尾部删除一个宇符,加到T的尾部 目标是要构造字典序 ...