【服务器篇】把一款手游服务器从PCU1000调教成PCU18000宝贵经验

 

去年接手一款大世界跳舞类游戏,性能问题一直困扰团队。游戏运营目标是PCU20000概述通过执行以下命令,可以...



最近公司发行一款高PCU的跳舞类游戏。性能问题一直困扰着这个项目。技术目标是PCU18000,运营目标PCU12000。对于一款手游而言,技术要求算是比较高了。那怎么解决这个问题呢?

一、概述

随着移动网络游戏的发展,玩家之间交互性和实时性要求越来越高,那么先看看我们的需求和目标。

1、运营指标:

  • PCU 12000
2、系统目标:

  • 可靠性
  • 实时性
  • 健壮性
  • 可扩展性
  • 可恢复性
  • 安全性
3、调优前:

  • PCU:1000
4、调优目标:

  • PCU:18000
二、系统架构



游戏服务器架构
这款游戏设计之初就是奔着万人PCU而去的。这是一款分布式架构的游戏服务器,把所有能解耦合的模块都进行了解耦合,以满足计算资源。

架构说明:

  • gate server 网关服务,可扩展
  • router server 系统内部消息路由服务,不可扩展(缺少灾备,待后期扩展)
  • monitor server游戏内部监控服务,不可扩展
  • filter server关键字过滤服务,不可扩展
  • info Server角色基础信息服务,不可扩展
  • log server 日志服务,不可扩展
  • GM server 游戏管理服务,不可扩展
  • Account Server 账号服务,用于登录鉴权,不可扩展
  • mail Server游戏内邮件服务,不可扩展
  • game server玩家个人游戏行为服务,不可扩展
  • group server 游戏内社团服务,不可扩展
  • pay server支付服务器,不可扩展
  • pay proxy server 支付代理服务器,可扩展
  • Scene Server 房间服务器,不可扩展
  • stage server 关卡服务器,战斗服务器,可扩展
  • DB proxy DB服务器,不可扩展
  • Game DB 玩家数据DB
  • Log DB 游戏日志DB
三、调优之路

1、服务器环境

①服务器部署在阿里云上,使用18台KVM的虚拟机,配置均为8核心16G wwindows server 2008。其中gate服务器为4核心16G内存,100M带宽。

②技术语言:C#

③通讯协议:基于google protobuffer序列化的自定义二进制

④DB:mysql(阿里云RDS)

2、“望闻问切”

①望

超过PCU>1000逐渐卡段现象:

  • 登录缓慢,甚至超时;
  • 创建房间缓慢,甚至超时;
  • 游戏动作同步超时,严重影响游戏体验;
②闻

使用压测工具模拟机器人压测,分别模拟1000,1500,2000PCU的case。并自己安装真实客户端体验游戏,记录下来体验不良点。

  • 登录偶然超时
  • 切线缓慢(游戏内部是分线设计)
  • 创建房间,以及游戏卡段,提示“通讯中”
  • 聊天卡顿
游戏中设计服务器都表现卡顿,无法正常游戏

③问

这一阶段就是和CP的技术负责人商讨系统瓶颈,问题解决思路达成共识。



④切

  • 增加gate接口耗时日志
  • 增加router主要接口耗时日志
  • 增加gameserver主要接口耗时日志
  • 增加scene Server主要接口耗时日志
  • 增加DB Proxy耗时日志
  • 增加stage server耗时日志
  • 增加accout server耗时日志
  • 使用zabbix对系统各个模块的CPU,内存,IO进行监控和统计
  • 增加DB监控(DB使用阿里云RDS)
2、经验调优

首先对gate和router以及其他服务器进行系统级别的优化,由于windows是基于注册表机制,参考微软官方文档进行了调优。

TCP/IP方面优化:

  • TcpMaxConnectResponseRetransmissions:防止 SYN flooding ,2
  • TcpNumConnections:TCP最大连接数,65534
  • TcpTimedWaitDelay:TCP复用资源超时时间,30
  • MaxUserPort:用户进程可分配最大端口号(5,000–65,534)65534
  • TcpWindowSize:TCP窗口大小,65535微软官方参考链接:
https://technet.microsoft.com/en-us/library/cc938208.aspx

https://technet.microsoft.com/en-us/library/cc938216.aspx

https://technet.microsoft.com/en-us/library/cc938217.aspx

https://technet.microsoft.com/en-us/library/cc938196.aspx

https://technet.microsoft.com/en-us/library/cc938219.aspx

3、取证调优

问题一:登录卡顿

①取证

DB Proxy耗时日志发现一个角色注册后会有大量update SQL操作,造成创建角色缓慢,且SQL耗时大于500MS以上。

②分析问题

经过和CP技术负责人讨论,发现由于系统模块较多,一个角色创建会涉及背包,经验,等级等相关属性更改,模块之间只负责自己属性更改,所以造成角色注册后多个update操作,造成注册缓慢。

③提出问题

DB Proxy直接对数据库操作,DB Proxy算法存在问题。

④提出解决方案

对DB Proxy进行改造,

  • 增加热数据缓存机制;
  • 玩家数据更新使用内存标记,玩家数据增加时间戳,按照玩家延迟落地到数据库,尽量让更新操作平均分布到时间轴上;
  • 敏感数据,立即落地;
  • 增加“玩家影子”机制(默认时间保留60分钟),再次上线后无语重新从数据库load;
方案缺陷:如果宕机,可能造成短暂丢档问题()

  • 把热数据存储到NoSql,redis做主从,可避免此问题(待后续优化)
⑤验证方案

对登录接口进行性能压测

优化前:
样本数
平均值
最小值
最大值
偏差
吞吐
50000
193
1
617
31
251


优化后:
样本数
平均值
最小值
最大值
偏差
吞吐
50000
206
1
353
45
446


问题二:房间内2%概率跳舞卡死

①取证

Stage Server存在异常日志

②分析问题

异常日志在随机歌曲后,抛出异常。

③提出问题

策划配置数据表格式存在问题

④提出解决方案

策划FIX数据表格式问题

⑤验证方案

使用压测平台模拟机器人进行跳舞,不再出现卡死,掉线

问题三:角色2%概率注册重复

①取证

DB proxy抛出主键冲突

②分析问题

Account Server RoleId 分配算法可能存在漏洞

③提出问题

优化Account Server RoleId 分配算法

④提出解决方案

在高并发时对分配ID加锁处理,避免分配重复

⑤验证方案

使用压测平台模拟机器人注册,不在出现角色重复问题

问题四:游戏大厅频繁TCP广播

①取证

经过逻辑日志以及router流量分析,发现router存在指数级别消息转发增长;

②分析问题

分析可能存在广播代码的逻辑

③提出问题

高PCU时,玩家进入游戏大厅后,会对所有玩家广播,自己状态改变

④提出解决方案

显然这是没有任何必要的消息通知,如果1000在线,那么转发量就是1000×1000的消息量,直接去掉此处转发逻辑

⑤验证方案

使用压测平台模拟机器人进出游戏大厅,发现router IO降低,gate消息队列减少,增加通讯效率

问题五:跳舞房间刷新排序问题

①取证

PCU超过1000后,刷新房间列表,超级卡顿,进入跳舞房间也卡顿,且Game Server CPU飚满到100%

②分析问题

刷新房间算法问题?确认使用冒泡排序,且每次请求,都做一次排序

③提出问题



冒泡排序是效率最低排序算法,切排序时机不对,

④提出解决方案

更改成快排,且有数据变化时再排序(按照1000人算,排序次数从1000000降低到3000,且变化才会排序),

⑤验证方案

刷新房间不在卡顿,PCU可以从1000到10000,且不卡顿,可以流畅游戏

问题六:机器人下线后,存在很多无效空房间,造成玩家卡死在房间内

①取证

增加Scene Server分配房间日志,逐步打印

②分析问题

跳舞房间流程:申请创建房间->系统创建房间->进入房间

发现在系统创建房间后,此时玩家正好下线,逻辑未对玩家状态进行检查,进而导致空房间存在

③提出问题

房间分配逻辑存在BUG

④提出解决方案

增加系统创建房间后对玩家状态检查机制,玩家可能随时掉线

⑤验证方案

多次使用压测工具模拟10000同时在线,压测10分钟,同时掉线,不存在空房间问题

问题七:关键字屏蔽卡顿优化

①取证

开启Filter Server后,系统卡顿,尤其聊天

②分析问题

Filter Server采用主循环单线程模型,未重复利用CPU,过滤算法采用关键字循环监测,效率低下

③提出问题

Filter Server线程模型待优化,过滤算法待优化

④提出解决方案

  • 修改Filter Server线程模型多进程多线程模型,充分利用多核
  • 关键字逻辑分成,永久关键字(角色名,舞团名字),临时关键字(聊天,房间名)
  • 过滤算法变成关键字,首字+扫列表方式存储,大大提高效率
  • 临时过滤服务为有损服务,可实时关闭
⑤验证方案

压测工具模拟PCU18000,5%聊天压测模型,关键字过滤效率OK,满足需求

问题八:gate卡队列问题

①取证

日志打印gate发送和接受队列,发现发送队列阻塞到1000-2000之间,IO峰值到80M

②分析问题

Gate Server把正常逻辑消息和聊天消息放在同一个队列,且消息没有优先级之分,如若存在大量世界聊天广播,势必造成发送队列卡顿。例如:18000在线,5%聊天频率。那么会出现:900×18000=16,200,000消息转发量,当前2个gate,每个gate会有8,100,000消息转发量。

③提出问题

gate转发存在瓶颈,以及聊天消息过大会覆盖正常逻辑消息

④提出解决方案

  • 消息增加优先级,聊天消息优先级最低,排在队尾
  • 增加gate到4个
⑤验证方案

压测工具模拟PCU18000,5%聊天压测模型,gate发送队列不存在大量阻塞情况

问题九:心跳检测机制问题

①取证

模拟机器人不发送心跳消息,出现掉线问题

②分析问题

怀疑心跳机制存在问题,gate服务器只是认为心跳消息为有效消息,设计不合理

③提出问题

心跳检测机制存在不合理

④提出解决方案

心跳机制优化成任何为心跳消息,不特定具体某一个消息,客户端可减少心跳消息发送,空闲时再发送心跳消息

⑤验证方案

压测工具模拟PCU18000,不发送心跳消息,不在出现掉线问题

四、优化后

使用压测工具模拟PCU18000跳舞游戏,5%聊天case,不再出现卡顿问题,且router和gate未到达计算资源和IO系统瓶颈,满足上线PCU12000需求。

五、总结

系统最初架构设计是可以满足万人PCU需求。但是由于后期开发人员研发过程没有足够考虑,导致后期上线前各种还债。不过这次优化体现了算法、合理设计、缓存、架构重要性,在以后系统设计和开发之初就好考虑进去,避免上线前期的各种还债。

最后感谢:这次优化历程艰辛,感谢 @点点乐 付大爷,@点点乐-良元  @龙翼 @晁宇 @子青 @丽媛   一起努力才能解决此问题,最后预祝我们游戏《心动劲舞团》大麦~ 大麦~,欢迎大家近期从九游&苹果下载并体验我们的游戏~下周一见~

喜欢的话,就关注一个呗~


    关注 游戏技术那些事儿


微信扫一扫关注公众号

0 个评论

要回复文章请先登录注册