Go 基于rpc的游戏服务器 开发笔记 其一
起因是最近在和leader 一起做 游戏服务器框架的研发。
以前的游戏服务器对比起互联网业务来更加落后;可能是因为游戏业务相对固定可控,并且要求高并发低延迟的特点,大多数游戏服务器采用的是c++开发,开发效率低,有大量得异步,回调逻辑,对开发者要求很高;其次编译速度慢,调试困难,且部署困难。
于是我们打算借鉴互联网微服务的概念,以服务为单位构建游戏服务器。引入,协程rpc,以及golang lua等多种语言,分别开发对应的服务。
拓扑结构描述
我们考虑采用最终的服务器拓扑结构为上图所示形式,采用统一的idl文件来描述我们的服务接口,根据服务类型采用不同的语言框架,实现对应的Container;加快游戏服务器的开发效率。
Go语言版本Service 技术调研
要实现对应版本的go语言 service container ,实现与c++版本的通信;需要网络部分,rpc框架,以及对应的脚手架生成代码。go语言在微服务方面,我个人因为年龄有限只阅读使用过 b站的 :
以及腾讯的:
这两个框架都很好的给了我对于go 语言版本框架开发的思路,不过因为协议对接和兼容问题,我都没有采用基于这两个框架进行二次开发;
我需要根据我们的逻辑开发对应rpc框架和网络相关代码,rpc方面grpc-go 是很好的例子,不过不是很能兼容我们的协议和c++那边的对应思路这边打算自研。
对于网络部分,考虑到性能问题,我阅读代码之后决定网络底层最终采用gnet:
这是一个基于epoll实现的高性能网络框架,并且内部采用事件的方式进行传递后期打算对接,其余rpc打算自行实现。
RPC 框架实现
rpc 框架其实go语言版本的已经比较多了,这里再这篇文章中暂时不赘述了,对应的专栏其实知乎有很多,我在这里想记录的主要是自己在开发设计前期所遇到的一些坑点总结,当然也会有详细设计在之后的开发笔记中更新。
我遇到最麻烦的点就是混淆了RPC的Network需要做的事情的范围,因为我最初的设计是打算将网络部分在后期替换为gnet库,那么rpc框架的net service 应该只负责协议的transport,不应该关心 连接tcp等网络底层的问题。
我最早的设计收到了TarsGo的影响,将network和transport放在一起;但是Tars的模型,对于被调用的服务可以简单的看作这么一个结构:
ServiceImpl是生成的服务实现接口,ServerProtocol是Transport层,Tcphandle 是网络监听,这里就导致了我最开始设计最麻烦的一个问题,Tars是根据服务为单位构建,网络端口监听和连接的;而我们期望的设计监听和连接是根据ServiceContainer为单位,导致我这里TcpHandle中写了大量得代码来描述conn和调度,以及有大量的锁,最终不得不重写。
现在RPC中的网络部分我采用了如下设计:
网络以连接为单位,生成对应的transport,每个transport可以用ringbuffer实现,用来调度send和recv的消息,transport将收到的消息发送到Container,然后Container在分发到Service中进行执行。
这篇笔记基本到到此结束了,go语言采用的编程,我现在最大的体验就是要转变为基于接口编程的思路,设计接口和package,这两天实现了对应的设计之后在继续更新吧。