关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

游戏服务器如何实现全球同服

发布时间:2020-11-22 12:51:52

刚从东家离职,得知之前设计的服务端架构被阿里和ucloud以及第八云计算推荐,看起来不怎么普及解决方案,本着开源精神分享一下思路吧。


既然面对全球用户,必然是要做到服务的动态拓展,自动化部署,归根结底还是如何改造成分布式服务器,老话题了。


服务器的不同业务分别在不同模块运行应该是共识吧,要是所有业务堆在一起,无法让核心业务实现分布式,也就失去全球服的意义。


不同模块的通讯协议定制,简单说就不同业务分布在不同进程,他们之间的通讯能在局域网范围内也能彼此连接。


然后要做的是业务最大程度解耦。比如邮件业务压力比较小,只需要一台服务器就能满足需求,而战斗服务器在同样量级需要两台服务器,如果这两个业务放在一起就不太合理了。


如此带来的问题是,面对繁多的业务类型如何部署。我能想到的方案是所有服务都打包进docker,启动时加入环境变量来区分不同服务。


关于服务发现,有现成的开源方案consul+registrator,consul为核心,registrator监听docker.sock文件将新启动的服务注册到consul内,docker.sock内有container启动参数,这样获取类型版本都能实现了,具体实现官方都有,这里就不介绍了。


这样通过consul就能获得所有的服务类型以及每个服务类型下的所有地址和端口。


解耦完业务部分以后,游戏存储的分布式也有现成的解决方案,最新版本的redis已经有cluster集群模式,这里需要在redis前端加一层代理用来计算key值的分布,随着slot增加,redis会重新分配所有key,而访问一个slot时,key在另一个slot会返回所在slot节点的地址,如果在业务层反复尝试读取用户数据并不合理,在所有slot前面写一层代理计算key值所在slot保存业务层到数据库的一次通讯可以得到结果,redis本身是开源的,他的key值分布的算法可以参考,github也有代理项目,自行搜索。


之后必须要考虑的是所有服务的缓存问题,如果一个业务节点有用户缓存,用户访问到这个业务的另一个节点就无法保证数据一致,因此在做业务设计时最大限度保证服务无状态,如果某个服务必须有状态可以在某个kv存储服务存下一个用户对应服务节点信息,在服务集群前面再加一层代理解析用户信息获取节点信息再做转发,目前nginx已经支持tcp连接转发,还有haproxy也能用。代理需要做的是解开第一个包找到节点再做转发。这里有个小trick,登录服务如果作为一个代理转发到业务服务可以控制根据客户端发来的信息做不同版本区分从而实现业务服务器的灰度更新。



总结下来所谓的全球方案只是解耦和服务发现,根据需求使用不同工具,具体的坑还要踩,整体方案还是挺靠谱的,毕竟之前设计的架构已经成为成功案例了,呵呵哒,但是不论架构多好都救不了业务出现问题。架构层面能做的就是这些,当然要真正做到全球同服还要服务提供商的支持,如何保证全球玩家连接通一服务器的延迟可以不影响游戏等等。全球服的架构带来的不仅仅是可以将所有玩家集中到一起,也可以降低服务器成本,运维成本,维护成本。当然也可以基于这样的架构做分服,只是把不同服的玩家分开处理业务,可以说是能够兼容分服,业务层面可以完全实现。

Q.png


/template/Home/D8Cloud/PC/Static