• 手机游戏服务器该如何开发呢?

    春节以来新型肺炎蔓延全国,而为了防止病毒的传播,各地封路封城,国民基本都是宅在家里面足不出户,受此影响国内养殖、娱乐、零售、旅游、餐饮等众多行业都遭受到重创。 不过有一个行业却在这个假期迎来了爆发。 什么行业呢?既然只能在家,那么精神方面的娱乐就便不能少。于是在国内许多行业受疫情影响处于低迷之时,游戏行业却逆势实现了增长。毕竟无聊的时候,打游戏是不错的选择。 手游上线,手游服务器也要与时俱进,及时做好数据备份工作。那么,手机游戏服务器该如何开发呢? 下面MMCloud小编就随便聊聊手机手机游戏服务器开发需要的技术。 一.聊聊手游服务器开发有哪些东西要考虑。 1.开发语言的选择: 工欲善其事,必先利其器,选择一门适合的开发语法对后期开发有着事半功倍的作用。 业界主要的是c/c++ + Python/lua模式做手机游戏服务器。c/c++做网络通讯数据传输,python/lua做业务逻辑。这样既保持了网络传输的效率(c++),又提升开发效率(Python/lua),同时也支持热更新。 当然,也有其他服务器开发语言,erlang(没用过,页游公司用的多),c#(大棒子国喜欢用,神奇的民族),Java(第一次听说时我惊呆了),node.js(少量游戏用的,还有一个node.js写的引擎叫pemolo),php(做http协议通讯的游戏时php+mysql也不失为一种好选择) 看过两个手机游戏服务器引擎  1.firefly(9秒社团开发的一款python手机游戏服务器框架)  2.kbengine(按bigworld的架构来设计的,c++ + python的)  2.数据库 现在比较流行的两种数据库,关系型数据库mysql和非关系型数据库mongodb。这是我用的最多的两个数据库。 关于两者之间的各种比较,网上有很多,当然你也可以用其他数据库,至于sql server,不怕被坑你就用吧(我向来对微软的东西没好感)。 3.服务端架构 讲一下我用过的其中一种架构模型,也是公司按照bigworld架构设计的: 1.Gate:首先要有一个Gate(网关)服务器,负责客户端连接及消息转发到Game(游戏服),保持客户端到服务端的连接 没有任何逻辑,只做消息加密和解密,以及客户端和服务器消息的转发(相当于两者之间的桥梁). 2.GameServer:GameServer是游戏进程,提供游戏逻辑功能(采用单进程(或者单线程)模型,手机游戏服务器的瓶颈从来不在CPU,所以只做逻辑功能的话单线程足够了,在这里没必要用多线程或多进程)。 3.DBManager:实现数据库的读写,方便Game服务器异步读写数据库的数据(有些把数据库读写放在游戏服,没有单独的服务器,那恐怕游戏服单进程就不够用了)。 4.GameManager:负责管理所有的GameServer,GameServer之间消息转发,提供广播到所有Game的功能。 4.协议 客户端与服务器之间协议通信,可以用tcp或者http。主要看游戏模型,如果是那种弱联网单机玩法,用http足够了,像天天酷跑之类,只在需要的时候处理一条http请求响应。 不过tcp用的比较还是比较多的。现在的网络游戏大多数都是tcp,像MMORPG类游戏。我们现在的游戏就是同时用了http和tcp,客户端和游戏服采用http协议。只有多人战斗转向战斗服才采用tcp长链接。 udp:其实游戏是有udp的,在一些高效率的场景下比如pvp即时战斗,tcp的拥塞控制和超时重传并不适合,有些就用的udp,然后自己做丢包重发,拿网络公平性换游戏局部的效率。 现在参与开发的游戏就同时使用了http协议和tcp协议,在游戏服是单机玩法用http协议,战斗服需要长连接保存协议状态,用的tcp。 5.存盘 有数据库就肯定有数据库读写操作,最主要的还是存盘(save),周期存盘还是即时存盘 即时存盘就是每一次操作数据都进行存到数据库,当然这样会导致对数据库的操作过于频繁,毕竟这是效率的瓶颈之一。 周期存盘也叫固定存盘,就是每隔固定时间存盘一次,比如10秒或者15秒,这样数据库的压力就会小很多,当然自己就要在内存中做好数据操作,防止数据污染或者存盘不上导致回档。 MMCloud游戏服务器解决方案图 二.开发一个手机游戏服务器需要掌握的开源技术 1.libevent,boost.asio等网络库,网上有很多开源网络库,与其自己造轮子,不如就用开源网络库作为自己服务器的通讯库。最出名的就属libevent和boost.asio了。 Boost的ASIO是一个异步IO库,封装了对Socket的常用操作,简化了基于socket程序的开发。支持跨平台。 libevent是一个C语言写的事件驱动的开源网络库。 至于二者之间的效率,仁者见仁。 当然还有很多:比如云风写的skynet(c + lua),陈硕写的muduo(c++)。都写得很好,云风写的东西简单好用,陈硕在秀他的c++技术。 2.protobuf:全称Google Protocol Buffers,是google开发的的一套用于数据存储,网络通信时用于协议编解码的工具库。它和XML或者JSON差不多,也就是把某种数据结构的信息,以某种格式(XML,JSON)保存起来, protobuf与XML和JSON不同在于,protobuf是基于二进制的。主要用于数据存储、传输协议格式等场合。 protobuf他的优势是对于传输比较大的数据产生的数据很紧凑很小,可以明显减小传输量。 而且处理速度也比较快,又有各种编程语言的实现,例如C++,Java,PHP等等。 缺点是不能明文编辑(数据是二进制的)。 用protobuf rpc进行数据传输很方便,所以是一个不错的选择。google protobuf只负责消息的打包和解包,并不包含RPC的实现,所以需要自己实现。 3.zeromq:消息队列,一个稳健,简洁的多进程通讯方案的基础。ZeroMQ 并不是一个对socket的封装,不能用它去实现已有的网络协议。它有自己的模式,不同于更底层的点对点通讯模式。它有比 tcp 协议更高一级的协议。(当然 ZeroMQ 不一定基于 TCP 协议,它也可以用于进程间和进程内通讯。)它改变了通讯都基于一对一的连接这个假设。 在这里它更适合服务器与服务器之间的通信,比如逻辑服和战斗服之间进行通信。 4.memcached:一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。 可以用来做缓存,比如客户端本来每次操作都需要操作数据库,会严重影响效率,这时在中间加一层缓存系统,就提升了性能。基于http协议的通信用memcached是一个不错的选择,如果是tcp长链接,直接维护一个在线的内存对象就可以了。 类似的技术还有redis等。 5.glog/zlog:你肯定需要记录日志,看爱好喽。 6.tcmalloc:内存性能分析 7.distcc:分布式编译工具,之前每次修改代码都要make半个小时,用distcc进行多台电脑同时帮你编译,快很多。 MMCloud拥有超15年游戏运营经验,全球50+ CN2顶级网络,1300+个CDN节点资源,包括并不仅限于中国香港,美国,日本,韩国,新加坡,马来西亚等10多个国家直接CN2高速专线接入。无条件免备案,提供智能化DDOS防护升级,负载均衡优化,数据库集群服务及建议,高防CDN节点布局优化等一系列高品质服务,打造适合企业稳抓客户布局全球的全能型游戏解决方案。详询MMCloud客服QQ95015688 。

    2021.12.21 浏览:251
  • 游戏服务器常见问题的解决方法分享

      在游戏开发中,我们经常会遇到一些技术难题,而其引发的bug则会影响整个游戏的品质。 过载保护、集群、服务器通信、并发选型等方面的问题,是中小团队常常的技术难题,本文分享了一些专家在坐诊过程中提到的解决方法,希望对大家有所帮助。 问题一:玩家登录时拉取好友信息,但好友服务繁忙导致登录失败。 解决方法: 1、分离关键路径上非关键调用,缩短事务流程,避免周边服务异常阻塞登录。 2、服务熔断机制,超出处理能力快速失败,防止雪崩。 3、按用户隔离事务,避兔单个用户请求阻塞影响到其他用户。 问题二:压测并发登录对redis产生很大压力。 解决方法:redis数据表数量多,一次事务会产生多个 redis请求,小表合并为大表。 Wade:服务器进程的管理一般比较简单,有很多还是用配置文件静态组织的。同时往往进程间通信的手段比较缺乏,没有使用消息队列中间件,甚至还有用 Redis 来做通信组件使用的。为了提高集群管理的自动化水平,使用 ZooKeeper 是一个比较常见的方法。 Zc:redis一般做为内存缓存来使用,不宜将关键数据存放在redis中.其数据安全性并不如一般的DB。在使用过程中也需要参考性能基线,控制访问频率和流量。 问题三:外部服务有延迟,调用到的业务流程中产生卡顿。 解决方法:业务侧增加缓存:同玩好友msdk+最近角色id+角色信息。 Wade:很多团队对于过载保护不够重视,往往只在最外层接入客户端一侧有最大连接数或者最大会话数的限制。而对于内部的多个进程,比如访问数据库的进程,就没有太多的负载保护。由于游戏是带状态的进程比较多,所以负载均衡往往也做的不多,基本上是按状态所在进程去转发处理请求。 Zc:注意缓存和降级处理。外部平台数据,尽量缓存,提高访问体验。当发现外部服务出现故障,或本身出现负载风险时,应降级服务。 Jovi:msdk midas平台特权等api接入工作,游戏业务可以建立一个隔离层专门处理这块需求,避兔过分侵入游戏逻辑,更容易控制。 问题四:运营和客服接口修改玩家数据,会与正常游戏的数据回写产生竞争。 解决方法:使用类似邮件机制去修改数据。 Zc:多线程开发中,经常会有线程池用尽或线程死锁导致服务质量下降。建议将线程池根据业务需求合理分类,不同业务间有合理的负载配比,不会相互影响。非关键流程需要延后或者异步化处理,避免卡死关键流程。 同时,合理的线程模型可以有效减少线程间竞争。对确实需要竞争的资源在流程入口处统一有序加锁,避免在逻辑过程中,随意嵌套取锁竞争。并且,给锁加个超时时间,避免业务中断。 Jovi:确保同一时刻只有单个数据修改点,有助于避免数据竞争。建议设计时采用CQRS方式,采用独立的数据表和服务记录事件,汇总到单一修改服务上执行。 Wade:并发编程是服务器端最常见的问题,一般会用多线程或者非阻塞两种方法之一解决。对于天然支持多线程的语言,如JAVA,很多开发者倾向多线程,好处是代码编写起来比较方便,但是这就要很清醒的对各种对象进行锁的操作,或者熟练使用类似 java.util.concurrent 这种多线程工具库。而如果使用非阻塞,好处是不会有锁的问题,但代码被分割到各个回调函数中,可读性非常糟糕,所以有的团队会使用“协程”或者 Promise 之类的工具来缓解这个问题,但这也引入了更多的复杂性。 下面详细介绍一下游戏服务器端架构中的调度架构,方便大家理解。 a) 单进程游戏服务器 最简单的游戏服务器只有一个进程,是一个单点。这个进程如果退出,则整个游戏世界消失。在此进程中,由于需要处理并发的客户端的数据包,因此产生了多种选择方法:    [图-单进程调度模型] 同步-动态多线程 每接收一个用户会话,就建立一个线程。这个用户会话往往就是由客户端的TCP连接来代表,这样每次从socket中调用读取或写出数据包的时候,都可以使用阻塞模式,编码直观而简单。有多少个游戏客户端的连接,就有多少个线程。但是这个方案也有很明显的缺点,就是服务器容易产生大量的线程,这对于内存占用不好控制,同时线程切换也会造成CPU的性能损失。更重要的多线程下对同一块数据的读写,需要处理锁的问题,这可能让代码变的非常复杂,造成各种死锁的BUG,影响服务器的稳定性。 同步-多线程池 为了节约线程的建立和释放,建立了一个线程池。每个用户会话建立的时候,向线程池申请处理线程的使用。在用户会话结束的时候,线程不退出,而是向线程池“释放”对此线程的使用。线程池能很好的控制线程数量,可以防止用户暴涨下对服务器造成的连接冲击,形成一种排队进入的机制。但是线程池本身的实现比较复杂,而“申请”、“释放”线程的调用规则需要严格遵守,否则会出现线程泄露,耗尽线程池。 异步-单线程/协程 在游戏行业中,采用Linux的epoll作为网络API,以期得到高性能,是一个常见的选择。游戏服务器进程中最常见的阻塞调用就是网路IO,因此在采用epoll之后,整个服务器进程就可能变得完全没有阻塞调用,这样只需要一个线程即可。这彻底解决了多线程的锁问题,而且也简化了对于并发编程的难度。但是,“所有调用都不得阻塞”的约束,并不是那么容易遵守的,比如有些数据库的API就是阻塞的;另外单进程单线程只能使用一个CPU,在现在多核多CPU的服务器情况下,不能充分利用CPU资源。异步编程由于是基于“回调”的方式,会导致要定义很多回调函数,并且把一个流程里面的逻辑,分别写在多个不同的回调函数里面,对于代码阅读非常不利。——针对这种编码问题,协程(Coroutine)能较好的帮忙,所以现在比较流行使用异步+协程的组合。不管怎样,异步-单线程模型由于性能好,无需并发思维,依然是现在很多团队的首选。 异步-固定多线程 这是基于异步-单线程模型进化出来的一种模型。这种模型一般有三类线程:主线程、IO线程、逻辑线程。这些线程都在内部以全异步的方式运行,而他们之间通过无锁消息队列通信。 b) 多进程游戏服务器 多进程的游戏服务器系统,最早起源于对于性能问题需求。由于单进程架构下,总会存在承载量的极限,越是复杂的游戏,其单进程承载量就越低,因此开发者们一定要突破进程的限制,才能支撑更复杂的游戏。 一旦走上多进程之路,开发者们还发现了多进程系统的其他一些好处:能够利用上多核CPU能力;利用操作系统的工具能更仔细的监控到运行状态、更容易进行容灾处理。多进程系统比较经典的模型是“三层架构”: 在多进程架构下,开发者一般倾向于把每个模块的功能,都单独开发成一个进程,然后以使用进程间通信来协调处理完整的逻辑。这种思想是典型的“管道与过滤器”架构模式思想——把每个进程看成是一个过滤器,用户发来的数据包,流经多个过滤器衔接而成的管道,最后被完整的处理完。由于使用了多进程,所以首选使用单进程单线程来构造其中的每个进程。这样对于游戏程序开发来说,结构清晰简单很多,也能获得更高的性能。    [图-经典的三层模型] 尽管有很多好处,但是多进程系统还有一个需要特别注意的问题——数据存储。由于要保证数据的一致性,所以存储进程一般都难以切分成多个进程。就算对关系型数据做分库分表处理,也是非常复杂的,对业务类型有依赖的。而且如果单个逻辑处理进程承载不了,由于其内存中的数据难以分割和同步,开发者很难去平行的扩展某个特定业务逻辑。他们可能会选择把业务逻辑进程做成无状态的,但是这更加加重了存储进程的性能压力,因为每次业务处理都要去存储进程处拉取或写入数据。 除了数据的问题,多进程架构也带来了一系列运维和开发上的问题:首先就是整个系统的部署更为复杂了,因为需要对多个不同类型进程进行连接配置,造成大量的配置文件需要管理;其次是由于进程间通讯很多,所以需要定义的协议也数量庞大,在单进程下一个函数调用解决的问题,在多进程下就要定义一套请求、应答的协议,这造成整个源代码规模的数量级的增大;最后是整个系统被肢解为很多个功能短小的代码片段,如果不了解整体结构,是很难理解一个完整的业务流程是如何被处理的,这让代码的阅读和交接成本巨高无比,特别是在游戏领域,由于业务流程变化非常快,几经修改后的系统,几乎没有人能完全掌握其内容。 游戏解决方案。详询MMCloud客服QQ95015688 。

    2021.12.21 浏览:143