游戏服务器开发的基本体系与服务器端开发的一些建议

来源:小新 时间:2022-06-23 09:12:22阅读:0

这几年身边有很多朋友web转向游戏开发。他们以前从未开发过游戏服务器,更不用说任何经验了,而从互联网上找到的例子或游戏知识是如此的少和分散。当他们进入游戏公司时,他们看起来很困惑。如果大公司更好,至少有人可以学习一些经验,但有些人直接进入小公司,甚至这些小公司只有他一个背景。他们肩负着公司游戏后端的研发和公司的成败。他们也尽了最大努力,他们也想把游戏后端做好。但因为我没有经验,我以为一开始我会做游戏服务器web差不多,但是过了一段时间,才发现代码太多,太乱了。当我看到代码时,我想重坑往前走。

游戏服务器开发的基本体系与服务器端开发的一些建议

在这里整理一些游戏开发的东西,希望对想开发游戏服务器的朋友有所帮助。

首先要明确游戏服务器的开发和传统web开发有着本质的区别。游戏服务器开发,如果没有经验,一开始根本没有一个明确清析的目标,不像web那样,有些明确MVC架构往往是为了尽快满足规划的需要,尽快实现功能,让游戏尽快运行。然而,随着功能的增加,旧代码的修改越来越频繁,游戏测试中暴露出一堆bug,更让人觉得无奈。这时,我们想到了重构和架构设计。

游戏的框架设计非常重要。良好的框架代码分析,责任明确,可扩展性强,易于调试。这将为我们的发展节省大量时间。如何设计游戏框架?也许每个游戏都不一样,但本质上是一样的。

对于游戏服务器的框架设计,我们首先需要了解游戏服务器框架的组成部分?游戏在线需要什么功能?有些人可能会说,只要游戏运行,访问服务器就没有问题吗?答案是否定的,游戏框架本身代表一个系统,包括:

  1. 系统初始化

  2. 游戏逻辑

  3. 数据库系统

  4. 缓存系统

  5. 游戏日志

  6. 游戏管理工具

  7. 公共服务组件

这个系统是必不可少的,它们共同为游戏的整个运行过程服务。让我们一点一点地介绍每个系统的功能。

一、系统初始化

在没有客户端连接的情况下,系统初始化是服务器启动时需要做的工作。基本上是读取配置文件,初始化系统参数。

但必须考虑的是:

系统初始化所需的参数配置在哪里,是在本地服务器还是数据库中;

服务器启动时,去数据库取;

修改配置是否需要重启服务器等。

二、游戏逻辑

游戏逻辑是游戏的核心功能实现,也是整个游戏的服务中心,它被开发的好坏,直接决定了游戏服务器在运行中的性能。那在游戏逻辑的开发中我们要注意些什么呢?

游戏是一种强大的网络交互业务。良好的底层通信可以最大限度地提高游戏的性能,增加单个服务器处理的在线数量,为游戏带来更好的体验,至少不容易因网络层而导致数据交互堵塞。我建议在这里使用它Netty,它是目前最流行的NIO框架,它的用法可以在我之前的文章中查看,这里就不多说了。

有些人怀疑代码也需要分层?当然,不同的代码代表不同的功能实现。目前的开发语言是面向对象的。如果我们把功能代码堆在一起码,它似乎很快就实现了功能,但在后期,如果我们想修改需求,或增加原始代码的新需求,它真的被我们自己打败了。因此,代码必须分层,主要包括以下层:

  1. 协议层,又称前后交互层,主要负责与前台交互协议的分析和返回数据。在这个层面上,基本上没有业务逻辑实现。与前台交互的数据从这个层面开始,并在这个层面结束。例如,您使用它Netty框架,那么Netty的ChannelHandlerContext即Ctx只能出现在这一层,他不能出现在游戏业务逻辑代码的实现中,收到客户的请求,在这一层分析所需的参数,然后将参数传输到业务逻辑方法,业务逻辑方法处理后,返回到客户数据,组织数据,返回到客户,使业务逻辑和网络层分离,业务逻辑只关心业务实现,也方便业务逻辑单元测试。

  2. 业务逻辑层,在这里处理真正的游戏逻辑,计算价格,清关,计时。保存数据的保存数据。但这一层并不直接操作缓存或数据库,而是处理游戏逻辑计算。由于业务逻辑层是整个游戏事件的核心,他的处理是否正确直接决定了游戏的正确性。所以这一层的代码应该尝试使用面向对象的方法来实现。不要复制和粘贴重复代码或类似的功能,所以修改非常不方便,可能是修改某个地方,忘记修改相同的代码。还要考虑每种方法都是可测试的,一种方法的行数最好不要超过100行。此外,你可以阅读更多关于设计模式的书籍,它可以帮助我们设计一个灵活整洁的代码。

三、数据库系统

数据库是存储数据库的核心,但游戏数据通过网络和磁盘存储到数据库IO,与内存相比,其访问速度非常慢。一般来说,每次访问数据库数据库建立连接。访问完成后,为了节省数据库的连接资源,应断开连接。

这实际上增加了服务器的成本,在大量的数据访问中,可能会更慢,游戏需要低延迟,那么我们该怎么办呢?我们想到了数据库连接池,即将访问数据库的连接放在一个地方进行管理。用完后,我继续打开它,去那里拿,然后把它放回去。所以你不必每次都建立一个新的连接。

然而,如果我们想自己实现一套连接池管理组件,我们需要时间不说,技术控制也是一个测试,但也通过测试等等,幸运的是,今天的互联网开源,有一些现成的可以使用,这里推荐Mybatis,即实现代码和SQL有足够的分离SQL灵活性是一个不错的选择。

四、缓存系统

在游戏中,客户端和服务器之间的交互需要较低的延迟。延迟越低,用户体验就越好。正如我之前所说,低延迟要求服务器处理业务尽可能快,客户端要求在最短的时间内响应结果,最低不得超过500ms,因为加上来回的网络传输耗时,基本上是600ms-到700ms再长玩家也会觉得游戏卡。

如果您直接从数据库中获取数据,并在处理后将其存储回数据库,则该性能无法跟上。在服务器中,数据在内存中处理最快,因此我们应该提前将一些常用数据加载到内存中,如游戏数据配置表、经常登录的玩家数据等。这样,在处理业务时,您就不需要访问数据库,直接从内存中获取,速度更快。

游戏中有两种常见的缓存:

  1. 直接存储数据jvm或服务器内存

  2. 这里推荐使用第三方缓存工具Redis,详细用法可自行查询。

五,游戏日志

日志是一件好事。日志在游戏中不可或缺,日志必须详细记录。这是玩家在整个游戏中的行为记录。有了这个记录,我们可以分析玩家的行为,发现游戏的不足。在处理游戏中玩家的问题时,日志也是一种很好的凭证和快速处理方法。

日志在游戏中分为:

  1. 系统日志,主要记录游戏服务器的系统情况。例如:数据库是否正常连接,服务器是否正常启动,数据是否正常加载;

  2. 玩家行为日志,比如玩家发送了什么请求,得到了什么,花了多少钱等等;

  3. 统计日志是对游戏中所有玩家某些行为的统计。根据这个统计数据,分析大多数玩家的行为,得出一些共性或差异,通过操作不同的活动来吸引用户。

在框架设计中,日志记录必须被视为一种强制性行为,因为如果不是强制性的,可能会因为某个功能而忘记添加日志,所以当这个功能出现问题时,或者操作一些向我们索要这个功能的数据库,这是愚蠢的。您必须添加需求并更改代码。日志必须设计一个良好的格式,日志记录的数据应该很容易读取和分解。日志行为可以用枚举来描述,并将这个枚举添加到功能的最终处理方法中作为参数,这样无论谁调用该方法,都必须添加参数描述。

俗话说,如果一个工人想做好事,他必须首先磨利他的工具。游戏管理工具是处理游戏运行中一系列问题的工具。它不仅用于开发人员,也用于运营。游戏上线后,我们需要对在线问题进行不同的处理。程序员不可能处理所有的问题,所以程序员想出了一种方法,为你制作一个工具,你喜欢处理谁。

六、游戏管理工具

由于游戏中遇到的问题,游戏管理工具是一个不断增长的系统。

但根据经验,必须有一些功能,如:

  • 服务器管理,主要负责服务器的开关,服务器配置信息,玩家信息查询;

  • 玩家管理,如踢人、封号;

  • 统计查询、玩家行为日志查询、统计查询、次留率查询、邮件服务、玩家数据修改等。

根据游戏的不同要求,所有可以通过工具实现的都可以在游戏管理工具中实现。它是为所有服务器管理的。

游戏管理工具好,可以提高游戏运营中遇到问题的效率,为玩家提供更好的服务。

七、公共组件

公共组件是为游戏运行提供公共服务。

  • 充值服务器,我们不需要服用一个充值,你不能提供多个充值服务器地址,与第三方公司对接,他们绝对不做,这是疯狂的啊;

  • 还有运营活动时的礼包码;

  • 还有注册用户的管理,玩家可以进入不同的区域。

这些都是为所有区域服务提供的服务,所以要单独做,与游戏逻辑分开,便于管理、部署和负载平衡。

还有SDK登录验证,现在手机游戏更多,与渠道对接验证,这往往很多http请求,速度慢,所以也要单独拿出来做,不要在游戏逻辑中验证,因为网络IO访问时间无法控制,http是阻塞请求。

因此,综上所述,游戏服务器至少由几个大功能模块组成:

  • 游戏逻辑工程;

  • 日志处理工程;

  • 充值工程;

  • 游戏管理工具工程;

  • 用户登录项目;

  • 公共活动工程等。

根据游戏的不同需要,可能还有其他的。在框架设计中,必须考虑系统的分布式部署,并尝试拆卸公共功能,以提高系统的可扩展性。

开发服务器端的一些建议

本文作为游戏服务器端开发的基本大纲,是游戏实践开发的总结。

第一部分——专业基础,用于指导招聘和实习考核;

第二部分-游戏入门,讲述游戏服务器端开发的基本要点;

第三部分-服务端架构,介绍架构设计中的一些基本原则。

希望能大家有所帮助!

一、专业基础

1.1网络

1.1.1理解TCP/IP协议

网络传输模型

滑窗技术

三次握手与断开连接的四次握手建立连接

在建立和断开连接过程中的各种状态

TCP/IP协议的传输效率

思考:

请解释DOS攻击与DRDOS攻击的基本原理

一个100Byte数据包,精简到50Byte,其传输效率提高了50%

TIMEWAIT如何解释状态?

1.1.2掌握常用的网络通信模型

Select

Epoll,边缘触发与平台出发点的区别和应用

Select与Epoll区别与应用

1.2存储

  • 计算机系统存储系统

  • 程序运行时的内存结构

  • 计算机文件系统,页面结构

  • 实现内存池和对象池的原理,应用场景和差异

  • 关系数据库MySQL的使用

  • 共享内存

1.3程序

  1. 对C/C 对语言有深刻的理解

  2. 对刻理解界面、包装和多样性,并有实践经验

  3. 对常用数据结构的深刻理解:数组、链表、二叉树、哈希表

  4. 熟悉常用算法及相关复杂性:冒泡排序,快速排序

二、游戏开发入门

2.1防御式编程

不要相信客户数据,一定要检查。作为一个服务器端,你不能确定你的客户端是谁,你也不能假设它是善意的,请保护自己。(这是判断服务器端程序员是否进入的基本标准)

一定要判断函数的传输参数和返回值的合法性,不要过于信任内部子系统和功能模块,要求低耦合、高内聚。

在插件式模块设计中,应建立模块功能的强度,以尽量减少模块间耦合。

2.2设计模式

自然的道法。不要迷信,迷恋设计模式,更不要生搬硬套

简化、简化、再简化,用最简单的方法解决问题

借大宝一句话:设计本天成,妙手偶得之

2.3网络模型

自造轮子:Select,Epoll,Epoll一定比Select高效吗?

开源框架:Libevent,libev,ACE。

2.4数据持久化

  • 自定义文件存储,如梦幻西游

  • 关系数据库:MySQL

  • NO-SQL数据库:MongoDB

  • 存储系统的选择应考虑稳定性、性能和可扩展性等因素

2.5内存管理

  • 禁止在运行过程中动态分配内存池和对象池

  • 严格检查输入输出的指针参数,宁滥不缺

  • 写内存保护,使用带内存保护的函数(strncpy,memcpy,snprintf,vsnprintf等)

  • 严格防止数组下标越界

  • 防止读取内存溢出,确保字符串\0结束

2.6日志系统

  • 简单高效,大量日志操作不应该影响程序性能

  • 日志不会丢失稳定,使服务器崩溃

  • 完整,玩家必须记住日志的关键操作,理想情况是通过日志在任何时候重建玩家数据

  • 开关、开发日志应加级开关控制

2.7通信协议

  • 采用PDL(ProtocolDesignLanguage),如Protobuf,可同时生成前后端代码,降低前后端协议联调成本,扩展性好

  • JSON,文本协议,简单,自解释,无协调成本,扩展性好,包装过滤和写日志也很方便

  • 自定义二进制协议,精简,传输性能高效,完全可控,几乎没有扩展性

2.8全局唯一Key(GUID)

  • 准备好合服

  • 便于跟踪道具,设备流向

  • 每一个角色、装备、道具都应该是全局唯一的Key

2.9多线程与同步

  • 同步处理消息队列

2.10状态机

  • 强化角色的状态

  • 检查和验证前置状态

2.11数据包操作

  • 合并,合并同帧中的数据包,减少IO操作次数

  • 单副本,尽量只保存一个包,减少内存复制次数

  • AOI中间过程无用数据包同步减少

2.12状态监控

  • 随时监控服务器的内部状态

  • 使用内存池和对象池

  • 帧处理时间

  • 网络IO

  • 包处理性能

  • 处理各种业务逻辑的次数

2.13包频率控制

  • 瘫痪变速齿轮是基于每个玩家每个协议的包频率控制

2.14开关控制

  • 每个模块都有开关,可以紧急关闭任何有问题的功能模块

2.15反外挂反作弊

  • 变速齿轮可以通过包频控制

  • 包id可消除自增校验WPE

  • 可以消除或拦截篡改的包校验码

  • 图形识别码可以踢掉99%的非人操作

  • 魔高一尺,道高一丈

2.16热更新

  • 防沉迷系统、包频控制、开关控制等核心配置逻辑的热更新

  • 代码基本热更新,如Erlang,Lua等

2.17防刷

  • 关键系统资源(如元宝、能量值、道具、设备等)的输出记录日志

  • 尽量依靠两个或两个以上的独立条件来检测资源的产出和消耗

  • 严格检查各项操作的前提

  • 验证参数的合法性

2.18防崩溃

  • 该系统的底层与具体的业务逻辑无关,可以通过大量的机器人压力测试来暴露bug,确保稳定

  • 建议使用脚本进行业务逻辑

  • 系统地保证游戏不会崩溃

2.19性能优化

  • IO操作异步化

  • IO操作合并缓写(事务性提交)db操作、包合并、文件日志慢写)

  • Cache机制

  • 减少竞态条件(避免频繁进出切换,尽量减少锁定使用,多线程不一定是单线程),多线程不一定比单线程快

  • 减少内存复制

  • 自己测试,用数据说话,不要猜

2.20运营支持

  • 接口支持:实时查询、控制指令、数据监控、客服处理等

  • 提供考虑http接口

2.21容灾及故障预案

三、服务器端架构

3.1什么是好的结构?

  • 满足业务要求

  • 能够快速实现规划需求,响应需求变化

  • 保证系统级的稳定性

  • 简化开发。将复杂性控制在架构底部,降低对开发人员的技术要求,逻辑开发不依赖于开发人员强大的技术实力,提高开发效率

  • 完善的运营支撑体系

3.2思考架构实践

  • 简单,满足需求的架构是好的架构

  • 设计性能,抓住重要的20%,不需要从程序代码中挖掘性能

  • 热更新是必要的

  • 人难免会犯错,尽量用一套机制来保证逻辑的健壮性

游戏服务器的设计是一项具有挑战性的工作,游戏服务器的发展也从以前的单一服务结构转变为多服务机构,甚至出现bigworld最近了解到了发动机的分布式解决方案Unreal服务器解决方案atlas也以集群为基础。

负载均衡是一个非常复杂的话题,这里就不谈了bigworld和atlas这种服务器的设计更多的是基于功能和场景来划分服务器结构。

首先,服务器划分基于以下原则:

  1. 在游戏中分离系统资源(cpu,内存,IO等)更多功能,独立成为服务器。

  2. 在同一服务器架构下的不同游戏中,应尽可能多地重用某些服务器(进程级重用)。

  3. 多核处理器适用于多线程并发编程。

  4. 宁愿在服务器之间复制更多的数据,也不愿保持清晰的数据流。

  5. 根据场景划分过程,如果需要按功能划分,则必须保持整个逻辑足够简单,并满足上述1、2点。

服务器结构图:

简要说明:

  1. Gateway主要用于维护和应用网关client该服务器需要两种连接IO:

  2. 对client采用高并发连接,低吞吐量的网络模型,如IOCP等

对服务器采用高吞吐量连接,如堵塞或异步IO。

网关主要有以下用途:

  • 分担了网络IO同时,还分享了网络消息包的加解密、压缩解压等cpu密集操作。

  • 隔离了client和内部服务器组,对client它只需要知道网关的相关信息(ip和port)。client切换场景服务器等操作是正确的,因为它一直与网关保持连接client透明。

  • 保持玩家登录状态。

WorldServer它是一个控制中心,负责将各种计算资源分配给各种服务器,其职责如下:

  • 多种管理和维护SceneServer。

  • 多功能服务器的管理和维护主要是将数据同步到功能服务器。

  • 其他服务器和服务器的复杂转发Gateway之间的数据。

  • 实现团队、聊天、帮派等需要跨场景的其他功能。

PhysServer主要用于玩家移动、碰撞等检测。

所有玩家的移动操作都在服务器上进行检查,因此服务器本身具有所有地图的地形和其他相关信息。具体的检查过程如下:首先,Worldserver收到移动信息,WorldServer收到后向PhysServer请求检查,PhysServer检查成功后返回worldServer,然后worldserver传递给相应的SceneServer。

SceneServer场景服务器,按场景划分,每个服务器负责的场景应该是可以配置的。理想情况下是可以动态调节的。

ItemMgrServer物品管理服务器负责所有物品的生产过程。在服务器上存储一个物品掉落数据库,并在服务器初始化时输入内存。任何需要生产物品的服务器都直接与服务器通信。

AIServer另一个负责管理一切的功能服务器NPC的AI。AI通常有两个输入:

  • 一个是SceneServer相关操作信息发送给玩家

  • 另一个时钟Timer驱动

对于其他服务器,AIServer一个有很多个NPC的客户端。AIserver所有和都需要同步AI相关的数据,包括很多玩家数据。由于AIServer的Timer可在很大程度上使用驱动特性TBB发挥多核性能的程序库。

将网络游戏服务器分为多个过程,分别部署。

  • 该设计的优点是模块自然分离,可单独设计。负荷分担可以提高整个系统的承载能力。

  • 缺点是网络环境不那么可靠。跨过程通信具有一定的不可预测性。服务器之间的通信通常很难建立一个调试环境,而且很容易把事情搅拌成一团糊状。正确和高效的管理对程序员来说也是一个挑战。

几年前,我还写了几篇与之相关的设计。这几天我在想一个问题:如果要做一个底层通用模块,后续开发会更方便。需求应该解决什么?这个需求应该是单一的、基本的,每个应用都需要。

正如TCP该协议解决了在互联网上稳定可靠的点对点数据流通信。游戏世界实际上需要的是游戏系统中稳定可靠的点对点通信需求。

我们可以在一个TCP做到这一点。一旦实现,就能给游戏服务的开发带来极大的便利。

游戏系统中的所有服务,包括不限于登录、拍卖、战斗场景、数据服务等,都可以被视为网络上的几个终端。每个玩家也可以是一个独立的终端。它们一起形成一个网络。在此网络上,终端可以可靠地连接和通信。

实现可以是这样的:

  • 每个虚拟终端都在游戏虚拟网络中(GameNetwork)有一个唯一的地址(GameNetworkAddress,GNA)。这个地址可以提前设置,也可以动态分配。每个终端都可以通过游戏网络的多个接入点(GNAP)通过唯一的TCP连接到网络。

  • 接入过程需要通过鉴权。

  • 识别过程依赖于内部安全机制,可以包括密码证书或特殊的访问点。(例如,玩家需要一个特定的访问点来访问网络,该访问点的终端必须是玩家)

  • 鉴权通过后,网络为终端分配一个固定的游戏域名。例如,玩家将被分配到player.12345数据库访问可以分配这样的域名database。

  • 游戏网络默认提供一个域名查询服务(这个服务可以通过鉴权的过程注册到网络中),让每个终端都能通过域名查询到对应的地址。

  • 然后,游戏网络中所有合法访问的终端都可以通过其地址相互连接和通信。

  • 基于整个协议TCP在协议之上,工作在唯一的一个TCP连接。直接使用TCP连接是不同的。游戏网络中每个终端之间的相互启动连接是可靠的。玩家不仅可以连接到某个服务,反过来也可以。玩家之间的直接连接也是可行的(是否允许这取决于具体的设计)。

  • 因为每个虚拟连接都是基于单一的TCP以上连接。因此,互联网的发起减少了TCP各种连接的不可靠性。鉴权过程也是一次性唯一的。

  • 而且我们提供域名反查服务,我们的游戏服务可以清晰、安全地知道连接到谁。

  • 该系统可以设计为离开游戏网络上的每个终端,域名服务将通知所有人广播这个消息。这种广播服务在互联网上很难实现,但在这个虚拟游戏网络中,无论是广播还是集体广播都是可行的。

  • 在这个设计中。在逻辑层面上,我们可以让玩家直接将聊天信息从玩家客户发送到聊天服务器,而无需建立多余的信息TCP连接不需要对转发和处理聊天信息进行额外处理。聊天服务器可以独立存在于游戏网络中。广播服务也可以主动将信息推送给玩家,并由服务器连接到玩家,而不是所有的连接请求都由玩家和客户发起。

  • 虚拟游戏网络的构成是一个独立的层次,完全可以撇开具体游戏逻辑来实现,并能够单独去按承载量考虑具体设计方案。非常利于剥离出具体游戏项目来开发并优化。

  • 最后,我们可能需要一套C用于游戏网络中的通信。api可以和socketapi类似。额外的两个访问和离开游戏网络。

微云网络IDC提供香港服务器美国服务器全球海外服务器租赁托管是区域链、直销、流媒体、外贸、游戏等服务器解决方案的首选品牌。微云网络已为许多企业提供区块链服务器租赁托管解决方案,为他们的区块链安全提供支持!咨询在线客服!

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:shawn.lee@vecloud.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

本站原创内容未经允许不得转载,或转载时需注明出处:https://news.kd010.com/fwqjs/10966.html

TAG标签:游戏服务器游戏服务器租用

相关推荐

返回顶部