首页 存档 技术 查看内容

让我们谈谈游戏服务器开发(上)

2018-3-30 13:00 |来自: 互联网 294 0

摘要:   从毕业至今,大约从事了4年的游戏服务器开发工作。其中页游2年,手游2年,端游虽然没有接触过实质的开发,但是同从事端游服务器开发朋友闲聊中也或多或少了解一些。想整理一些思路,沉淀成文字,以讨论页/手游服 ...


  从毕业至今,大约从事了4年的游戏服务器开发工作。其中页游2年,手游2年,端游虽然没有接触过实质的开发,但是同从事端游服务器开发朋友闲聊中也或多或少了解一些。想整理一些思路,沉淀成文字,以讨论页/手游服务器开发为主,端游为辅助。首先谈谈很有争议的开发语言选择吧。


1、开发语言


  我们先看一张2016年6月编程语言排行流行榜


  这里不讨论语言的优劣,讲一个故事:
  朋友就职一个创业公司做互联网APP的,当时技术合伙人使用的是Ruby搭建了服务器。1年半过去,到手投资花的差不多但产品却没什么起色,技术合伙人因为私事要离职,公司需要找一个资深的Ruby开发来接替他的位置,但是在中国这个环境,Ruby资深且符合他们那个团队风格确实难招。
  等到第二轮投资都到位了,合适的人还没招来(当然可能一部分原因钱权没给够,这里细节不明),最后只能狠心请人用Java进行服务器重构,其过程对产品影响是不言而喻的。
  现在各类招聘网站上,游戏服务端程序员一般是C/C 居多,Java,node.js,erlang占有一席之地,python与php也可以分到一杯羹,还有对lua有要求的服务端职位。并不是表示C/C 要好用、高级,造成这样的原因很多,可能要用一篇文章来分析,我们这里只从环境上来看:远一点,大学教育对C/C 的推崇,用人单位笔试面试侧重C/C ;近一点,在页/手游还没火起来时,传统服务器开发底层相关基本是C/C 一家独大,包括BAT里的,B和T都是以C/C 作为主流语言;更近一点,正是这种中国语言人才的基数导致了,开始一部分创业成功的服务器使用了上述语言,然后培养了一代又一代使用该语言的相关从业人员 比如我。
  还听闻过一个端游服务端用纯C实现,他们需求就是服务端要快,尽一切可能的快,因为多人场景PVP的存在,服务端转发校验负载重,所以他们选择了C。为什么不选C 或者Java?选C 或者Java不能满足需求吗?这个结果不得而知。个人猜测这个选择一方面和大公司语言环境有关,一方面出于对纯C效率的认可,也有可能是主程对技术选型的判断,所以选择纯C满足了他们的需求。
  大公司肯定有自己成熟的框架体系,没有很多的选择权,创业公司、小公司一般都会在满足需求前提下选择基数大(好招人的)语言,基数小容易作死。


2、进程,线程,协程


  个人比较喜欢这样的服务器框架


  Master管理全局,Worker要是挂了负责拉起并且记录(会遇见一直挂的情况,要记录次数,满足多少后不拉起)。Worker负责主逻辑,Thread是功能线程,比较常见的是异步日志的Thread,逻辑处理Thread。
  协程是又是一个容易引起争议的东西,对于游戏服务器明显好处是在异步调用时可以简化逻辑(下一节会详细说明),要说明显缺点可能就是万一出了BUG,会增加查找BUG的复杂度。但是既然选择了多进程多线程,协程其实不是必须的,就和goto一样,它不是异类,用在合适的地方最合适。

3、同步,异步,阻塞


  解释这些概念,举个生活中的例子,去一餐厅吃饭,人很多得排号,那么有  以下几种结果:
  同步阻塞:门口等,一直等到叫自己;
  同步非阻塞:去附近逛逛,但是得时刻关注是不是排到了,万一排到人不在门口…;
  异步阻塞:店家提供短信通知服务,但是自己还是选择门口等(基本不会这样做吧:D);
  异步非阻塞:店家提供短信通知服务,我可以附近逛逛,干干自己的事情,随时等候短信通知
  游戏服务器经常会遇见这样的场


int32_t procTask()

{

//do something

return asyncGetScoreFromXXSvr(); //需要去其他Svr处理一些数据

}

int32_t getScoreFromXXSvrCallBack() //其他Svr处理完毕回调

{

//continue do something

return 0;

}


  比较典型的异步非阻塞策略,前后逻辑在不同的接口。对于性能要求不太高的程序可以采用同步阻塞简化逻辑代码,或者使用协程达到“异步非阻塞”


int32_t procTask()

{

//do something

syncGetScoreFromXXSvr(); //同步处理数据,会造成阻塞

//coGetScoreFromXXSvr(); //协程处理,假阻塞

//continue do something

return 0

}


  具体如何选择策略要根据具体的需求,异步非阻塞策略一般来说可以满足各种需求,追求代码逻辑简洁可以考虑同步阻塞(前提是使用多线程处理逻辑)或者协程,还有一种Future/Promise的模式也可以简化异步逻辑。
  这里多插一句,socket相关阻塞接口的协程要注意在阻塞之前加入poll/epoll事件,然后yield出去(例如recv),处理完毕后resume回来。机制比较复杂,可以参考:
  微信开源的libco协程组件


4、支持服务器平行扩容(非单点负载均衡)


  服务端开发支持服务的平行扩容在设计之初十分关键,譬如一台服务器的处理能力有限,达到这个上限该怎么办?若服务支持平行扩容我们增加对应处理服务器即可,一般情况在部署之初就设置至少2台服务器,一台不幸宕机,另外一台继续提供服务。当然还有一种情况是:业务不给力,需要消减服务器成本,原本有3台运行的服务器,现下架一台,2台就可以完全满足需求的情况。
  服务器平行扩容要点是:逻辑服尽量不存储和处理对象相关的内容,游戏服务器处理对象最直接的就是玩家信息。玩家数据放入缓存,每次请求进入逻辑服从缓存重新拉取信息,如果服务一定会对逻辑相关内容的处理 比如游戏排行榜,必须考虑到平行服务器之间的数据同步,可以参考这篇博文。
  附一个平行服务处理的框架图:



  step1(请求)-

声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

相关分类

返回顶部