关于手游
概要
2015 年第一季度,中国网络游戏市场规模达到 320.8 亿,环比增长 8.0%,同比增长 24.7%。其中移动游戏占比 31.0%。相对于传统的端游,手游的兴起给运维工程师的技术能力和运维理念都带来了巨大的挑战。这是因为手游在技术架构、运维体系方面存在众多特殊的要求。本文首先分析手游运维的特点,然后再从手游的架构、容量规划两大方面给出最佳实践的推荐。
在手游运维领域,我们经常会听到一些专用名词,在这里我们首先对这些专用名词进行简单说明以期读者能对手游运维有个概念的认识:
-
手游开发商:也叫 CP,即 Content Provider,内容提供商的英文首字母缩写。顾名思义,就是指制作手游产品的研发公司或者团队。例如研发《刀塔传奇》的莉莉丝团队等。
-
手游发行商(运营商):即代理手游 CP 开发出来的手游产品,在部分渠道或者全渠道发行 CP 手游产品的公司。一般由手游发行商进行手游运维工作的实施。例如盛大游戏、龙图游戏等。
-
手游渠道:拥有手机端手游和 APP 用户,能够进行手游和 APP 流量分发的公司,即可成为渠道。所有可以获取手游用户的平台都可以称为渠道。例如苹果应用商店、Google 应用商店、腾讯应用宝、百度手机助手等。
-
下载数:手游客户端被下载的次数。
-
激活数:用户下载安装游戏后,打开游戏,但未进行注册前,记录的终端数。
-
注册数:用户激活后,进行了自动或者手动注册有 ID 信息或者账户信息的账户数。
-
日活跃登陆数 (每日登陆用户数 DAU):用户输入完身份信息后,进入到游戏内的账户数。同一日多次登陆的同一个玩家计数为 1。
-
日最高在线数:每日每个时刻,同时进行手游操作的玩家数量的最高值。
上述几个指标中,下载数、激活数、注册数是预估手游公测首日可能带来的用户导入量的最重要评估依据。
日活跃登陆数,特别是公测首日的活跃登陆数,是评估手游发行效果的重要数据。
日最高在线数的承载能力是进行容量规划时需要满足的服务能力。
手游和端游运维的异同点
在推荐手游架构之前,我们需要深入了解手游运维和端游运维的异同点,以此分析为基础,再推导出合理的手游架构。
手游运维和端游运维的共同点和区别主要体现在下述四个方面:
-
操作系统层面:手游运维和端游运维,都需要对底层操作系统有较深的理解。区别是手游运维中使用 Linux 等开源操作系统的较普遍;端游运维根据不同的开发商可能 Microsoft Windows 和 Linux 都占有一定的比例。
-
联网方式:在客户端和服务器端通信方式上,端游要求客户端强联网,一般使用在 TCP 协议之上实现私有协议。这样的好处是可以实现长连接和提高交互性;手游一般采用弱联网方式,使用 HTTP 协议进行通讯。
-
游戏周期:手游生命周期较短,玩家涌入的时间比较集中。因此在架构设计时,需要充分考虑横向扩展的需求。
-
游戏是否分区:手游开放公测时,一般不使用分区的方式,即所有玩家直接在一个大区里面进行游戏;而端游往往采用分区制,各个分区的玩家之间无数据交互。手游不分区的运营方式,使得服务器压力集中,对于运维要求更高。例如,如何解决数据库的集中压力问题及游戏服务器的压力分担问题等,都是运维人员需要考虑的。
最佳实践:推荐的手游架构
目前的大部分手游在设计客户端和服务器端通信模型时,采用了 HTTP 协议。
使用 HTTP 协议的优点
使用 HTTP 协议的通信方式,有以下的优点:
-
HTTP 协议是成熟的应用层协议,有丰富的客户端和服务器库函数加以复用,相对于完全自主开发基于 TCP 的通信协议,开发效率更高,可能遇到的 bug 更少。
-
使用 HTTP 协议更容易利用到现有成熟的周边基础设施,例如通用的负载均衡软件或者硬件等。
-
易于实现压缩。HTTP 协议本身支持应用程序以外的由 Web 服务器提供的压缩功能,减少客户端和服务器端的数据传输量。
-
利用 HTTP 的 Session 和 Cookie 机制,易于实现会话保持机制。
-
易于实现加密。在 HTTP 层之上,直接使用 SSL 协议(HTTPS)即可实现关键信息的加密传输。
推荐的网络架构
基于上述分析,并结合盛大游戏在运维大型手游过程中的实践经验,我们推荐实施这样的网络手游架构:
图 1 推荐的手游架构图
在设计这样的手游架构时,我们重点考虑的几个方面如下:
- 负载均衡器:
-
使用商业硬件实现。采用商业硬件的负载均衡可以最大程度的保障业务稳定性。
-
使用双机热备(HA),规避单点故障。
-
使用 NAT 模式。在手游架构中,实际负责游戏逻辑的 Web 服务器组和玩家之间的数据流量,一般不大。根据我们的经验,在 5 万人同时在线的手游,带宽使用 800Mbs 左右。使用 NAT 模式的负载均衡方案完全可以满足需求;同时对于 Web 服务器来说,不需要配置外网 IP,节省 IP 费用及提高安全性。
-
- 双上联的链接方式:
- 负载均衡器和核心交换机使用双上联,避免单一核心交换机故障导致的网络中断。
- 接入层交换机接入核心交换机时,采用双上联,并且做 PortChannel,保障双链路可用的情况下,同时提高吞吐量。
- Web 服务器组: 配置高频 CPU。作为手游逻辑的主要处理单元,Web 服务器往往执行大量的 CPU 运算,比如玩家攻击能力计算、攻击效果计算等。
- Memcached 服务器组: 这个服务组的作用一般包括预加载配置项以及缓存数据库查询结果等。使用 Memcached 提供的高效内存缓存,可以提高响应速度。
- 数据库服务器组:为游戏数据提供持久存储。 在这样的架构设计中,体现手游运维对于高可用性、安全性、高性能的要求。在运维人员设计相关规划时,可以参考该架构进行实施。
最佳实践:手游容量规划
如上文所说,手游相对于端游的生命周期更短,因而留给运维人员的准备时间也就更少。这就要求我们在短时间内对手游运营需要的各种资源规划到位,手游容量规划是一个必不可少的环节。
容量规划(Capacity Planning),是指在系统上线前或系统运营过程中,通过分析业务走向,对系统需要的各种网络、计算、存储资源进行提前规划和准备。目的是在这种业务变化时,系统承载能力可以随着要求变化进行灵活的应对。
多线机房的选择
为了用户在 3G、4G、WIFI(中国电信接入、中国联通接入、中国移动固网接入)等终端网络切换时得到良好的游戏体验,手游服务器需要部署在多线机房,由此可以很好的满足用户多种方式上网的需求。
如下图所示是我们某个手游玩家按照 ISP 来源的分布情况:
图 2 手游玩家 ISP 分布
由上图,也验证了我们必须把服务器部署在多线机房,以满足不同接入的手游玩家。
多线机房的实现原理和特点如下:
- 多条光缆:数据中心为适应不同用户对不同网络访问量的不同需求,采用多条高带宽(例如 40G)光纤链路连接到 Internet。
- 10G 出口带宽:连接到中国电信、中国联通的出口带宽均超过 10G 以上。
- BGP4 收取路由:各条链路均采用 BGP4 收取路由,并进行相应的策略设置,保证用户访问不同网络的访问速度。
- 各条出口互为备份:在其中一条链路出现故障的时候,所有流量通过其他链路出入,不会出现单链路故障,提高了可靠性。
- 突破限制:突破了 ISP 出口受中国电信和中国联通互连带宽瓶颈及访问国际网站的限制。
高速 Internet 接入、冗余的网络和带宽管理系统保证接入带宽可根据用户流量的需求随时扩充,充分满足用户日益增长的网络应用需求。
在选择和对比多个多线机房时,机房的冗余带宽、对抗 DDOS 攻击的能力,是评估的 2 个最重要方面。高冗余带宽(10G 以上)、高抗 DDOS 能力(20G 以上),是我们倾向的选择。
网络带宽容量规划
网络带宽规划的数据来源主要有两个:一个是在小规模测试时收集到的玩家平均带宽使用量,以 kbps/ 每玩家计算;另一个是使用机器人(指能够模拟玩家进行游戏内容测试的自动化程序)测试时收集到的类似数据。
在进行网络带宽规划时,需要对以下三个方面的内容分别进行评估:
-
正常流量规划。评估方法是根据玩家在正常进行游戏时,每玩家带宽使用量与预估的同时在线人数的乘积。
-
手游客户端更新容量规划。评估方法是根据手游客户端的更新内容大小乘以预估的公测当日导入的手游玩家数量。手游客户端更新通过接入外部 CDN 可以适当分担流量压力。
-
异常流量规划。这个主要是指在手游运维中,受到大规模 DDOS 攻击时的处理规划。在进行这种容量规划时,需要充分考虑到机房运营商接入的带宽,采用分级规划。在第一级小规模 DDOS 时(小于 5G),启用自有的流量清洗设备。在更大规模的 DDOS 时,启用运营商级别的保护,以降级服务的方式,阻止来自某一方向的攻击流量(该方向的正常访问也会受到影响)。
Web 服务器承载能力规划
在规划 Web 服务器承载能力前,需要分析目前的计算瓶颈。
以 PHP FPM 类型的 Web 应用程序为例,有以下的两个参数务必需要设置:
-
slowlog /var/log/php-fpm-slow.log。用于指定 PHP 执行时慢日志的记录位置。PHP 慢日志,用于定位 PHP 程序执行慢的原因,是最重要的日志。
-
request_slowlog_timeout 1s。用于指定对于执行时间超过 1s 的 PHP 脚本,记录程序执行调用情况(backtrace)到 slowlog 指定的位置。
在 Java 程序中,可以使用 Log4j 在关键调用处记录相应的执行时间,如对外部 API 请求、对数据库调用、对缓存服务器调用、排名计算等等。通过这些数据,我们能够获取到可能影响系统性能的关键信息,在有针对性的解决后,再进行相应的容量规划。
Web 服务器负责对手游业务逻辑的处理,对 CPU 要求较高。因有负载均衡设备调度,单台服务器对可靠性要求不高。如果服务器宕机,由于调度系统的存在,系统会自动把请求切换到其他服务器上,给玩家造成的影响较小,这点就和端游不一样(端游上玩家会掉线)。对单服务器要求较低,服务器选型上可有更多的选择,比如说采用一些多节点服务器。在压力测试时,我们首先在负载均衡器上设置流量只分配给一台服务器,然后评估它的压力情况。以此数据作为支撑,可以计算出总计需要的 Web 服务器数量为预计最大同时在线玩家数除以单台承载能力。
Memcached 承载能力规划
Memcached 服务器组为 Web 服务器组提供缓存服务,同时减轻了数据库的查询压力。
Memcached 是基于内存的 key-value 型缓存,无磁盘 IO 读写,效率非常高。在对 Memcached 进行容量规划时,我们需要关注的是热点缓存数据的分布情况。
热点缓存数据,是指 Web 服务器程序请求次数最多、产生最大网络流量的缓存数据。如果热点数据比较分散,我们可以部署多台 Memcached 同时使用客户端对 key 哈希的方法(如一致性哈希算法)进行压力分担。盛大游戏遇到过一个极端情况是,热点缓存数据集中在某个 key 上。此时,使用客户端哈希是没有效果的(因为一个 key 只能分布在一台服务器上),达不到压力分担的效果。
如下图所示,其中一台在线 Memcached 的带宽使用已达到瓶颈:
图 3 单台 Memached 带宽使用量
单一热点数据产生大量带宽需求的情况下,可以使用的方案是对缓存服务器进行网络端口 Bonding。关于使用 Bonding 方法提高带宽吞吐量的方法,请参阅《Linux 运维最佳实践》一书“第 3 章 概述负载均衡和高可用技术”的内容。
对 Memcached 热点数据的分析,推荐使用 memkeys 工具( https://github.com/bmatheny/memkeys )。memkeys 是 tumblr 开源的类似 top 的工具,可用于实时查看 memcached 的 key 使用情况。
memkeys 的安装命令如下:
-
wget http://ftp.gnu.org/gnu/autoconf/autoconf-latest.tar.gz #下载 autoconf
-
tar zxvf autoconf-latest.tar.gz
-
cd autoconf-2.69/
-
./configure
-
make
-
make install
-
yum -y install gcc-c++ pcre-devel libpcap-devel #安装依赖库
-
git clone https://github.com/tumblr/memkeys.git #下载 memkeys 源代码
-
cd memkeys
-
export CXX=g++44
-
./autogen.sh
-
./configure
-
make
-
make install
memkeys 的使用方法如下:
- /usr/local/bin/memkeys -i eth0 -r 10 #-i 指定网络端口,-r 指定输出的刷新频率
由此,我们可以按照单位时间内请求次数、带宽使用率来排序分析出热点数据。如下图所示,memkeys 的输出格式为:
通过对当前 Memcached 的请求情况分析,可以有效的判断是热点数据的分别是否均衡。
另外一个需要注意的事项是 Memcached 的启动参数,默认情况下,它支持的并发连接数是 1024,如下所示:
-
memcached -h
-
-c
max simultaneous connections (default: 1024)
在上线前,务必要提高该值。在我们的实践中,曾经发生过因为前端服务器过于繁忙导致连接数用光的情况。Memcached 当前的连接数情况,使用如下命令获取:
-
[root@master ~]# telnet 127.0.0.1 11211
-
Trying 127.0.0.1…
-
Connected to 127.0.0.1.
-
Escape character is ‘^]’.
-
stats
-
STAT pid 23341
-
STAT curr_connections 2000 #当前连接数
数据库承载能力规划
数据库存储了手游中的持久化数据,提高数据库的响应效率对提高手游体验起到关键作用。进行数据库容量规划时,需要严格按照以下的规则进行:
1、数据库配置参数、表结构和 SQL 语句评估。
进行数据库评估的目的是分析数据库软件配置参数与硬件能力是否匹配、分析表设计与 SQL 语句的效率关系。
以 MySQL 为例,在数据库配置参数方面,主要考虑增加 innodb_buffer_pool_size 为系统可用内存的 60%。分析数据库表结构设计时,对主键、索引是否完整、有冗余、表引擎的一致性、字段类型的高效性进行分析。SQL 语句评估时,考虑对多表联合查询、limit、复杂查询语句进行优化。在无法直接进行 SQL 语句优化的条件下,可以考虑通过业务逻辑的调整来减小数据库压力(这一步可能涉及到游戏策划、产品经理的沟通,一般比较难)。
2、数据库分库分表设计。对于访问频繁的数据量巨大的表,如用户注册表,必须采用拆分的方法,使其分布在不同的数据库服务器上。对于 log 库,由于其对于游戏来说,是非核心数据,也需要单独拆分,以缓解核心数据库的压力。
3、使用数据库读写分离技术。数据库读写分离技术,在数据库分库分表的基础上,又进行了一层压力分解。在 MySQL 中,通过配置主从复制(Replication)可以获得以下的好处:
-
在从库上进行读取操作,可以进一步减少主库的读压力。
-
在专用的从库上进行数据备份时,不影响在线业务。
-
在专用的从库上进行数据分析和挖掘时,不影响在线业务。
4、使用 SSD 提高随机读写 iops。手游的大区制,使得数据库的压力被集中起来,同时不同等级的玩家所具有的不同的游戏行为也加剧了对数据库的压力。使用 SSD 可以最大限度的提高服务器的 iops,以应对这种读写压力。
5、存储容量规划。在数据库中,一般会记录较长时间的玩家游戏日志,这一部分数据随着运营时间的增加,对存储容量要求越来越多。评估方法是根据内测期间玩家数量和日志数据量计算出,每日每玩家大概产生的数据量。所需要的存储容量为每日每玩家大概产生的数据量乘以保留天数再乘以每日预估玩家数量。
官网论坛访问能力规划
在手游运维时,除了考虑到手游系统之外,还应该考虑官网、论坛等的访问能力。
在游戏维护期间,玩家往往会转向到官网和论坛,此时会产生大量的并发请求。官网和论坛基本都是基于 Web 的服务,考虑容量规划时,可以参照本文 Web 服务器承载能力规划的内容。
人数曲线接入
人数曲线实时地反映了在线玩家的情况,也同时能够反映游戏系统运行状态。
在设计人数曲线接入时,我们使用了基于 Web 请求日志分析的方式。人数曲线的接入步骤如下:
-
在 Web 服务器上记录玩家客户端的 Cookie 字符串。
-
分析 5 分钟内的 Cookie,去除重复值后的数量作为当前在线人数。
-
统计数据写入人数数据库。
-
图表展示。
小结
手游是近年来网络游戏领域中异军突起的一个重要分支,得到越来越多游戏公司的重视。掌握手游运维的关键技术,是提高运维人员自身价值的必要手段。本文从架构角度切入,给出了盛大游戏推荐的设计思路。希望能够帮助读者从宏观上把握手游运维体系的特点。手游上线前的容量规划,是保障手游系统不被过载、保障业务稳定性的关键环节。文章从机房、网络到各种角色服务器组的容量规划进行了深入探讨,如果读者在进行容量规划时能够遵循这些建议,那么我们可以对系统承载能力做到胸有成竹、从容不迫。
作者简介
胥峰,《Linux 运维最佳实践》主要作者,盛大游戏高级研究员,微信订阅号《运维技术实践》维护者。关注领域:开源技术、运维自动化、DevOps 实践、及系统容量规划。
感谢木环对本文的审校。
给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ , @丁晓昀),微信(微信号: InfoQChina )关注我们。
评论