图数据库在游戏开发中使用思考(下)

在游戏开发设计中,玩家作为一个游戏对象,他们之间可能会存在多种关系,比如:

  • 好友关系;
  • 组队关系;
  • 公会关系;
  • 买卖关系;
  • ……

无论是使用关系型数据库还是key/value型的NoSQL ,按照传统思路对于这些关系的存储结构实现大同小异。例如:玩家会有独立的好友关系数据块,数据块内部至少存储着好友唯一ID,可以通过好友ID索引到好友相关信息;公会存在唯一ID,通过这个ID拉取公会成员信息和其他信息;组队与公会类似…

传统数据库与图数据库思路比对

我们列举一下好友与公会的常规操作,在不考虑合法性校验的情况下:

操作传统方式图数据库方式
玩家A和B成为好友玩家A和B分别在好友数据块增加对方ID两对象A和B之间增加
玩家A和B解除好友 玩家A和B分别在好友数据块删除对方ID 两对象A和B之间删除
玩家A加入公会C玩家A记录所属公会ID,公会C在成员列表加入玩家A两对象A和C之间增加
玩家A离开公会C 玩家A删除所属公会ID,公会C在成员列表删除玩家A 两对象A和C之间删除

直观感觉上使用图数据库方式更简洁一些,传统方式若做得严谨一些可能还需要考虑事务的支持,根据数据库的选型不同会导致数据一先一后写入,需处理先写入成功后写入失败的场景。

为了凸显差异性,这次我们再假设一些更复杂的操作,比如在推荐系统中常见的场景,同样也是不考虑合法性校验的情况下:

Read More →

图数据库在游戏开发中使用思考(上)

图数据库,从概念的出现到现今蓬勃发展跨度几十年,它可以细分为NoSQL(Not Only SQL)非关系型数据库的一种:

图的概念

图数据库这里的“图(Graph)”并非指的风景、人物照片或者GIF动图,而是指类似于“网络拓扑图”或者“股权关系图”这类结构的图,目的用来表示节点之间的关系,这类结构图也可以称之为属性图模型

还有其他概念分类,例如:资源描述框架(Resource Description Framework,RDF)。这里我们不做延伸,本文后续图的概念均围绕属性图展开。

Read More →

基于QUIC的HTTP/3

大概几个月前,HTTP/3被标准化(RFC 9114),它最大改变是将HTTP传输协议从TCP变成了基于UDP的QUIC,这意味着HTTP不在是绝对的基于TCP的应用层协议。

新技术标准的成立必然有它的使命和原因,关于HTTP/3相关概念、原理的介绍在互联网上很多,本篇文章会减少这方面的介绍,更多聚焦于为什么会出现这种技术,我们为什么需要它的思考,从不一样的角度来看待这个新技术标准。

Read More →

排查Https请求超时的一些建议(下)

上篇内容我们介绍了排查Https请求超时的大体思路,主要强调了自查的重要性,以及一般情况下超时问题的排查流程与关注点。

下篇我们将内容聚焦到超时自查中一块十分重要的内容:在请求通过网卡发出之前,如何有效获取Https请求各阶段Trace记录。目的是为了更好的进行问题归因和为后续排查收集关键信息。

客户端发起Https请求的流程

我们还是以Golang语言作为背景,其标准库客户端请求流程如下:

对于上面每个步骤来说,我们既需要关注耗时,还需要关注它们是否存在错误,特别针对DNS解析我们还需额外关注DNS解析的结果

每个步骤的目地和原理这里不做介绍,比如:链接复用是什么;DNS解析是做什么用的,解析结果会影响什么等等。这里我们更加聚焦于怎么Trace每个步骤需要关注的信息。

Trace方案

Read More →

排查Https请求超时的一些建议(上)

超时问题

Https请求超时一般指的是从Https请求发起计时,在规定时间内没有返回响应,造成请求超时。使用Golang语言为例,默认客户端没有设置超时时间,即请求一直等待返回,我们可以通过下面代码设置客户端的请求超时为5秒:

var client = &http.Client{
    Timeout: time.Second * 5,
}

绝大多数情况下,超时请求会返回关键词为“context deadline exceeded (Client.Timeout exceeded while awaiting headers)”的错误信息,少数情况下也会因为超时导致的其他信息返回。

Golang语言也支持设置更细粒度的超时机制,例如在TCP链接建立阶段,在SSL握手阶段等等,主要是根据Https请求阶段来进行分解的。可以参考这边文章(The complete guide to Go net/http timeouts),文中讲解的比较透彻,借里面的一张图来说明更细粒度的请求超时拆解:

其中http.Client.Timeout就是文章开头代码所设置的超时时间,本文讨论的超时也是从这个点延伸出去的。其余的超时机制以及Trace它们方式会在下篇里做详细介绍。

问题发现

Read More →

聊聊服务端架构演化

我们先从一个需求入手:需要实现一个游戏好友系统。

比较常规的做法:

(为了更清晰讲述,这里屏蔽了一些模块细节:比如接入层、服务器框架、储存读写分离、分表、分桶、集群模式等,也未考虑异地互备与大陆外数据等细节)

简单的名词解释:

  • GameServer:用来接收、处理客户端常规请求的模块(根据游戏是否分区部署策略会有所不同,这里简化成单分区);
  • FriendServer:用来处理所有和好友相关内容的模块,可以多进程部署进行负载均衡;
  • RoleBaseInfo:用来储存用户简要信息;(这里可以简单理解成需要在好友列表上展示的信息)

那么整个处理流程如下:请求从GameServer转发至FriendServer,FriendServer根据好友列表信息拉取对应好友的RoleBaseInfo返回至客户端显示。

将来会引发的问题:

随着用户的增多,每次请求通过FriendServer去DB实时拉取系统整体负载会加大。

解决方案:所以为了成本考虑增加缓存,牺牲一定的实时性,空间换时间的策略。

新流程接入了缓存机制会把好友数据做缓存,分钟级定期更新(缓存也可以放GameServer,可以减少内网带宽消耗,但是造成模块边界模糊)。

Read More →

GameAISDK的UI识别点击

游戏对不同分辨率手机的适配没有统一的标准或者固定方案,这样会引发一些微妙的问题,我们先拿简单的分辨率缩放举例。

在传统的图像缩放中,对于目标点的偏移都是等比的。比如:从(100×200像素)->(200×400像素)图像中的UI坐标变化过程是这样:

矩形坐上角坐标原点,横向x轴,纵向y轴,后面均沿用此规则

传统图像缩放

对于游戏来说,因为大屏、异形屏的原因较难按照等比的方法来进行适配,而且部分游戏可能有自己独特的分辨率适配规则。实际情况可能如下:

游戏图像适配

这会导致一个什么样的问题?比如你有一段程序或者代码需要ClickUI(40,50)。在100×200原始分辨率下是有效的,但是换了200×400分辨率的手机可能会有适配问题,原本期望的ClickUI(80,100)无效了。实际需要ClickUI(80,120)才有效。

当然这里有一些其他的方式能取到不同分辨率下UI的精确坐标,游戏可以利用引擎,android原生app可以利用底层接口等等,但是这些不是本文讨论的内容。

GameAISDK点击UI的过程

Read More →

GameAISDK模仿学习研究

模仿学习(Imitation Learning,后面简称IL)的思想就和它的名字一样,借助“专家”示范样例,机器会记住这些样例,并模仿着做。

GameAISDK中的IL沿用了上述思路,使用训练集和验证集两个样本集,样本由截屏与行为的映射信息组成。训练成模型后传入截屏进行行为预测,预测结果为对应需要执行的行为。

一些名词解释

  • UI – 用户界面,这里指游戏里用户可以点击、滑动的特定按钮与区域;
  • SDKTool – GameAISDK自带的客户端工具,用来设置UI识别行为与样本录制;
  • Adb – Android调试工具;
  • Minicap – 效率很高的截屏工具;
  • LSTM – 长短期记忆人工神经网络;
  • GRU – LSTM变体,有比较优于LSTM;
Read More →

腾讯GameAISDK试用报告

腾讯在今年8月份的时候开源了自家基于AI的游戏自动化测试工具GameAISDK(https://github.com/Tencent/GameAISDK)。这个东西最吸引人的地方就是使用了CV+AI的技术来实现游戏自动化。

区别与以前的脚本或者UI自动化工具,对业务代码侵入少,技术前沿。

总体结论(个人主观)

总分100分的话,我给60分,主要槽点如下:

  • 各种BUG,文档教程与实际不一致;
  • 环境安装有些复杂,而且对安装环境限制比较死,如果不是Ubuntu或者Windows需要花大力气才能安装成功使用;
  • 强化学习DQN的方式基本是鸡肋;
  • 源代码里面很多tricky的地方,给阅读理解造成困扰;

下面我选取一下典型的例子来分析一下,可能每个点都提一下核心问题和总结,因为要展开说每个点都可以形成单独文章。

后面简称GameAISDK为工程。

Read More →

Mysql数据库被盗

九月初的时候,安装在云服务器上的Mysql被人盗了,数据被删,留下了一段勒索信息,所幸是Mysql除了我的博客数据外并没有什么重要的数据。

勒索信息大概意思是付0.06个比特币(当时行情价差不多4000RMB)就把Mysql数据还给我。这绝对是过高的预估了我的数据价值,这些数据去个0,顶多值400。

比较遗憾的一点是,因为我的疏忽,云服务器Mysql没有开启binlog,若直接通过Mysql数据文件恢复,会存在数据损失(因为库表内容已经被盗取者覆盖过了)。

硬盘快照自动短期备份设置只保留7天,但是数据库的修改是在7天之外,求助了官方说备份删除了就删除了,无法恢复(这点我是存疑的)。最终无奈只能恢复二年前的备份,然后云上的硬盘镜像最后一次永久备份是二年前,若恢复这个备份,会有若干评论交互和十几篇博文信息缺失。权衡之下无奈恢复了二年前的备份,再通过“外部网站备份”拷贝回原有的文章信息。

事情过程不复杂,只是思考了几点:

站在黑客角度

  • 瞎估值导致没收到勒索款。如果黑客只勒索200~300RMB我可能为了省事就付了,不过每个人心中都有一个哈姆雷特,这些数据值多少没一个标准;

站在受害者角度

  • 数据备份的重要性,即使是个人不重要的数据。定期的持久化备份,已经短期备份的数据覆盖率,最多能承受多少天的数据损失,最好心中有数;
  • 自己搭建的服务注意公网安全性。比如mysql,redis这些敏感的存储,需要注意里面账号的权限配置,尤其是安装第三方软件需要用到这些存储,如果需要自定义账号通过公网访问,一定要记得使用复杂密码。

这次mysql被盗可能是因为使用了Tars教程推荐公网权限的账号,并未修改密码导致的。

站在云服务角度

  • 没什么槽点。虽然无法恢复硬盘镜像,但是也是按照约定规则来,没什么好说的。

(全文结束)