这是一个叫OAR-01的《我的世界》公益服务器,从今年6月份开始运行,至今已经3个月了。主要玩法为生存和粘液科技,在暑假“高峰期”曾有过20人(其实不是什么高峰)同时在线的情况。
由于是公益服,主要资金来源是玩家(也是群友)的捐赠,以及自己用爱发电。所以维护一个性能卓越、成本低廉并且还有较强可玩性的服务器是我的主要目标。当然了,在这一切实现之前,还有一个更大的目标,就是使用云原生进行游戏和相关服务的部署。
云原生是指所有的互联网服务都是在云服务器上部署的,不涉及本地机房或IDC机房托管之类。云原生有很多好处,具体的优势挖个坑,等会儿细说。
首先是服务端的选择。服务端主流有原版、插件和模组三种。原版就是官方推出的Vallina版本的核心。原版没有对性能优化,同时也有很多的bug/特性,这肯定是不能用的。
模组服是Forge架构作为核心,并且添加大量模组以供游玩的服务器。这类服务器好处在于游戏内容多样,玩家能够体验更多的不同于原版的游戏内容。但问题也很大,一方面,一些热门的模组大多数玩家都玩过,没有新鲜度,另一方面,冷门的模组往往学习成本高昂,玩家玩了也不知道怎么玩。同时,模组服还需要高主频的处理器,这一点在成本有限的云原生部署中很难做到。
那么我的目光就转向了插件服。插件服中最具代表性的是一款叫PaperMC的开源服务端。其修复了大多数的官方bug和不合理特性,还提供了大量的性能优化和客制化选项。
选择完软件就要选择硬件了。由于本人最早接触公有云是腾讯云,域名注册也是在腾讯云,所以本文中用到的公有云服务提供商均为腾讯云。其实其他云厂商的服务也是一样的,只不过可能价格、优惠力度会有不同。
在游戏服务器的选择上,我最终选择了腾讯云的SA2竞价实例(Cloud Vitrual Machine, CVM),使用AMD霄龙Rome架构,性能不错,并且价格方面比Intel的至强系列便宜不少。同时,竞价实例价格是按量计费价格基础上的2折,不可谓不便宜。
有些小伙伴可能会问,竞价实例难道不会发生回收事件吗?首先,只买一台竞价实例,被回收的概率的基数就小;其次,只要做好了核心业务的分离,做好硬盘镜像,可以在短时间内切换回按量计费,并且没有数据的丢失;最后,竞价实例的2折优惠价是任何其他服务无法比拟的,这个风险值得冒险。同时,我自己的服务器已经连续运行了3个月,暂时还没有发生过回收的情况。
在带宽方面,原来我使用的是按量计费,一个G需要0.8元。与按量计费相对的是按带宽包月计费,带宽计费也不便宜,或者说对于小规模业务来说很贵,尤其是对于5Mbps以上的带宽,甚至要100元每Mbps,这就意味着如果同时在线人数较多,那必然会增加带宽峰值,峰值越高费用上升的速度越高。所以我只能选择按量计费,虽然一个G需要0.8元,但好处是没有带宽的限制,速度要多快有多快,比较适合业务初创期对流量还不确定的情况。
做了一个简单的计算,对于《我的世界》,每天的最高同时在线人数乘以30,即是一个月所需要的带宽费用。而随着玩家的不断增多,流量成本飞涨。终于在今年(2021年)的8月的某一天,我陷入了焦虑……原因是玩家飞快增长,原本预计一个月流量费用在100左右,突然变成了预计一个月流量费用需要1000+。这也是我遇到的第一个困难。
是困难就需要克服,克服困难的唯一办法就是创新。经过一整晚的深思熟虑,在对腾讯云产品的反复斟酌之后,我找到了解决出路——使用轻量应用服务器的廉价带宽,搭建应用层代理。
腾讯云最近主推一款轻量应用服务器(lighthouse, LH),其价格一般很便宜,但配置也比较死板不能调整。其中,网络方面最具有性价比的LH是一款5Mbps带宽、每月50元的实例,换算下来每Mbps带宽只需要10元,而拥有更高带宽的LH实例,单位带宽的价格都比这贵得多。同时,由于友商的不断竞争,LH还有很多优惠,最便宜的可以到3元每Mbps每月。这价格已经远远比大多数的托管便宜了,更何况这带宽资源还是网络中的王者——BGP线路。
BGP线路是国内最优质的公网带宽资源,对所有网络环境不分移动电信,均有最低的延迟。问题就出在如何利用将游戏核心的接入点迁移到性价比更高的LH上。显然不能直接把游戏拷贝过去,因为便宜的LH配置都比较低,前文也提到,竞价实例是性价比最高的计算资源。也不能简单买一台LH就完事,因为带宽显然比5Mbps要高得多,肯定要买很多个LH实例,然后各个实例负责接入一部分的玩家。一方面多个IP是个问题,玩家需要自行选择某个人数比较少的LH接入游戏,这并不优雅,也没有操作性;另一方面,简单地转发流量也不可行,因为游戏核心会认为所有的玩家都是从某个内网的LH实例地址加入游戏,无法获取源客户端的IP信息,这样就无法实现基于IP的任何操作:比如将不良口碑的玩家封禁,比如限制每个IP的登陆数量,以及地图的一些功能。
一方面,使用BungeeCord或Velocity等应用进行游戏应用层的反向代理。这两款软件都是转为Minecraft开发的第七层代理程序,可以直接读取游戏数据包内的IP地址信息,并且添加转发信息之后转发到指定地址;另一方面,使用域名解析(Domain Name System, DNS)作为负载均衡(Load Blance, LB),DNS智能地将将一个域名随机解析为多个LH接入点中的某一个IP地址,这样玩家理论上会随即进入一个实例,而不用记录复杂繁琐的IP地址信息。这里要注意的细节是需要购买一款TTL较低的套餐,以防止过长的缓存导致大量玩家挤入一个接入点。
以上解决方案都是依托云原生的部署才能实现,LH接入点是公有云才有的独家的服务,而DNS负载均衡也是依托公有云的DNS解析才实现的,继续阅读您将看到更多的关于云原生的部署在成本和性能体验上的优势利好。
解决了带宽问题游戏就正常运行了。为了更好的体验,我给我的世界加入了网页地图插件(dynmap)。网页地图插件读取地图文件,并且进行渲染,将渲染好的地图“瓦片(tiles)”存储到文件系统或数据库中。 一开始我是使用数据库来存储的。因为对于海量数据,数据库的访问响应速度比文件存储高的多。但是数据库并不是用来存储图片的,因为这会占用大量的硬盘空间,导致主从备份由于开销太大难以进行,同时MySQL使用的innoDB引擎在删除记录时是“虚删除”,只是将被删除的记录标记为被删除,并不会真正的删除,等到下次有数据要写入的时候才会写入,这虽然加速了删除速度,但也导致了磁盘空间的浪费——尤其是在存储大量图片的时候,人们将这种碎片空间叫做“数据空洞”。
为了整理碎片空间,需要执行“重构数据表”的操作,而这一操作更是我的噩梦——需要和当前已使用容量一样大的存储空间进行暂存。总的来说数据库在存储地图瓦片时会大量的浪费磁盘资源,并且删改不灵活。云硬盘价格还是比较贵的,先前的方案需要硬盘200G的空间给网页地图,在618的优惠并且按一整年购买优惠之后,价格在每月40元,并且这些数据还需要快照备份,快照每月20元,还是挺贵的。
解决问题首先要认识问题。地图“瓦片”的读写有个特点,就是写入速度不需要多少,而读取时需要大量并发加载,因为渲染地图往往很慢,而玩家在浏览器中打开地图往往一秒就是几百个请求。如果使用文件系统,不使用数据库,前面的问题虽然是没有了,但导致系统资源因为大量的IO而被挂起,系统最终会失去响应。数据库的初衷就是解决这一类问题的,但是由于成本受限,这里我不想用数据库进行存储。
这次解决问题的灵感来自于我的网盘项目:网盘设计初衷就是利用对象存储(Cloud Object Store, COS)以达成无限存储的目的。而对像存储可以应对大量的读请求。但是在我要说的案例中,地图渲染会大量的读写工作目录,对象存储又不适合直接用做写入介质,因为每一个更改都会产生一个请求,对象存储有一个计费项目就是请求数量,大量的读写导致读写请求费用飙升。
于是,我又将目光转向了混合存储:使用按每小时存储量计费的文件存储(Cloud File System, CFS)作为地图渲染的工作目录,使用cos_migrate_tool定期将渲染好的地图“瓦片”上传至对象存储中,再给对象存储单独配置内容分发网络(Content Delivery Network, CDN),访问者在请求地图“瓦片”时会被最外层的CDN重定向到瓦片对象存储的CDN域名中,然后瓦片资源的CDN根据单独配置的规则返回对应资源。
这样有三个好处,一是费用便宜。CFS在没有优惠的情况下每100GB每月35元,但这是每小时按量计费的,如果这个月平均只用了10G那就只要3.5元,非常灵活;而对象存储则更加便宜,标准存储100GB一个月只需要8元,而在地图渲染期间内的瓦片上传(每小时40000“瓦片”生成)是一次性的,彻底完成后只会有少许的文件更新(每小时约2000个“瓦片”更新)上传,对象存储的请求费用也是可控的。以上方案通过充分利用云原生带来的产品红利,彻底解决了使用数据库存储中出现的问题。同理,使用CFS存储世界存档也是一样的。
以上就是从2021年6月到9月OAR-01世界运维的主要内容。
如果你也想来体验原版生存,可以看这个网页,这里面有一键开始游戏的方法。
评论区
共 19 条评论热门最新