转载:http://space.itpub.net/17007506/viewspace-615570

笔者在闲暇时,偶尔会登录腾讯QQGame玩玩升级游戏。这确实是一款非常优秀的软件作品,腾讯的开发人员在此展现了极高的技术水准。QQ游戏同时在线用户数都在百万到千万之数量级以上,可以想象其在性能方面所面临的挑战有多高。

    QQ升级游戏有一个“快速加入游戏”的功能,方便玩家尽快加入目标牌桌。这本身是个非常人性化的功能,但其实现却存在一个缺陷,当玩家当前所在房间内,同时执行“快速加入游戏”功能的用户数较多时,常常会出现加入失败的情况。笔者碰到的最糟情形是重复5、6次以上,才最后成功加入,其间获得的用户体验自然是不够好。

    (图A)“快速加入游戏”失败示意

    注意:点击图片可以放大观看

    笔者分析这个缺陷的根源,可能是“快速加入游戏”这一功能之实现在服务器端与客户端之间的协作分配方式有问题:

    QQgame的服务器端维护了游戏大厅中所有房间、和每个房间中所有牌桌,及相关玩家在这些牌桌的占位情况;而每个登录QQgame的客户端会实时(因为客户端数目庞大,服务器端提供数据更新服务的实际延迟时间会达到秒级以上,并不能真正做到实时)地从服务器端获取这些数据;玩家(用户)进入某个房间后,当其执行“快速加入游戏”功能时,客户端会先分析当前房间中所有牌桌的占位情况,并选择一个未满桌的牌桌,然后向服务器端发出加入此牌桌的请求;服务器端收到客户端的加入指定牌桌的请求后,开始尝试完成加入操作,然而,因为客户端数据更新的后滞性,造成服务器端在此前可能已经收到其它客户端所发相同的(指定了同一牌桌)加入请求,并为其完成加入,使得此牌桌位满,于是本次加入操作失败。

    (图一)客户端执行“加入未满牌桌”

    显然,解决此缺陷最简单的做法便是改变服务器端与客户端之间的协作分配方式。原来的方式之所以造成可能加入失败,是因为进行“快速加入游戏”,必须先选择一个未满桌的牌桌,这必然依赖于当前房间中所有牌桌的占位数据,这些数据是由服务器端所维护的,如果在客户端完成这一选择,就需要从服务器端实时更新这些数据到客户端,而数据的更新根本实现不了真正的实时,于是有两个以上客户端同时发出向同一牌桌加入的请求就不能避免;那么,如果“选择一个未满桌的牌桌”这个工作不在客户端进行呢?我们可以由客户端向服务器端发出一个自由加入牌桌的请求,这个请求并不指定目标牌桌,服务器端收到请求后,直接找到一个未满桌的牌桌分配给客户端所对应的玩家,并把此结果返回给客户端;在这种协作方式下,无论多少个并发客户端同时发出加入请求,因为服务器端都是排队按顺序来一一加以完成的(可以通过对牌桌的玩家占位数据加同步锁以实现多线程安全来实现),所以总是不会出现争位而因满桌失败的情形。

    (图二)服务器端执行“自由加入未满牌桌”

    (图三)“加入游戏”场景实现的参与类视图

    如何在服务器端与客户端之间正确分配相关的协作,是分布式软件设计中极其关键的环节。由于网络的延迟特性,我们不能将分布式环境下的数据与桌面应用下的等同看待;QQ升级游戏的开发人员有可能忽略了这一点,而没有更深入地思考这一协作分配问题。有个所谓“客户与服务器端协作分配之数据依赖”原则应当尽量遵守--如果某个功能的实现依赖于某些数据,那么这个功能的实现最好分配给数据的直接拥有者(不论是客户端还是服务器端),这实际上就是GRASP之信息专家模式的翻版(GRASP模式中数据的拥有者指的是对象)。

    当然,因为QQGame在高性能方面的要求极高,QQ升级游戏开发者可能有其它的考虑因素而选择目前的做法。例如,每个牌桌在开始进行游戏时,有复杂的游戏逻辑要运行,这些游戏逻辑如果都放在服务器端运行,恐怕需要的服务器集群是个吓人的数目,腾讯或许不愿意投入如此多的资金去购买这些服务器;那么玩家的机器同时充当客户端与服务器端的做法就是一个很自然的选择。游戏开发者可能会这样设计:第一个加入某个牌桌的用户,其主机将自动充当本牌桌的游戏服务器,此后,其它玩家要加入此牌桌,其加入请求应当发往第一个加入的用户主机,而非腾讯的服务器。不管怎样,这些都涉及到极其复杂的分布式架构设计问题,有兴趣的话,笔者将在后续文章中进一步深入探讨这些问题。实际上,升级游戏在可以执行“快速加入游戏”功能前,还有一个进入某个房间的步骤;而同样由于数据更新延迟的因素,造成玩家常常选择加入一个当时显示人数为未满的房间时,结果却为已满的情形。要强调的是,这一问题是无法通过上述调整协作分配的方法来解决的。

    为了改善用户的操作体验,避免加入游戏失败的次数是必要的,实际上,除了上述的做法,还有其它临时性的修复方法。例如,可以增加一个所谓“自动快速加入游戏”的功能,就是客户端自动重复执行原来的“快速加入游戏”的功能,直到加入成功为止(不需用户重复按那个按钮而已,一笑)。另外,还有一个减少“快速加入游戏”失败概率的方法,就是客户端在选择目标牌桌时,不援用固定的策略,而是使用某种随机方式,这样多个客户端同时指定加入同一牌桌的概率大幅降低,争位失败的情形自然也大幅减少了。当然,上述两种途径还可以结合在一起应用。笔者很期待腾讯能尽早修复上述缺陷,给包括笔者在内的玩家们一个更好的操作体验。

从腾讯QQ升级游戏之“快速加入游戏”功能的实现缺陷看C/S之间如何正确分配相关协作的更多相关文章

  1. 腾讯QQ是用什么语言开发的(转)

    腾讯QQ的部分COM组件用的VC6,用exescope看其中几个dll的依赖,依赖于MFC42.dll,MSVCRT.dll,MSVCP60.dll都说明是VC6写的. 还有一部分用的VS2005,包 ...

  2. QQ 腾讯QQ(简称“QQ”)是腾讯公司开发的一款基于Internet的即时通信(IM)软件

    QQ 编辑 腾讯QQ(简称“QQ”)是腾讯公司开发的一款基于Internet的即时通信(IM)软件.腾讯QQ支持在线聊天.视频通话.点对点断点续传文件.共享文件.网络硬盘.自定义面板.QQ邮箱等多种功 ...

  3. S01-晓亮的电脑软件安装过程文档 腾讯QQ 595076941 2019年10月

    S01-晓亮的电脑软件安装过程文档 腾讯QQ 595076941 2019年10月 本文档的创建作者的腾讯QQ聊天号码是 595076941 S02-电脑软件安装过程中不要随意关闭窗口除非必需关闭窗口 ...

  4. 腾讯QQ 8.9.3体验版发布 在线文档多端同步实时保存

    感谢N软网的投递 腾讯体验中心迎来QQ8.9.3首个维护体验版发布,详细版本号为v8.9.3.21006,上一个体验版v8.9.2.20717发布于4月20日,时隔34天又迎来了更新.本次升级主要是在 ...

  5. 电子设备的使用方法-第5版(佳明智能腕表小米手机联想轻薄笔记本群晖存储)我的腾讯QQ电子邮箱地址是 595076941@qq.com - 2021年9月5日

      电子设备的使用方法-第5版   (佳明智能腕表小米手机联想轻薄笔记本群晖存储) 2021年9月5日 我的腾讯QQ电子邮箱地址是  595076941@qq.com 前言 大家好,我叫徐晓亮,今天我 ...

  6. 仿腾讯QQ竖直滑动导航菜单

    菜单就像qq软件的分组,鼠标经过自动显示相应组的内容. 效果体验网址:http://keleyi.com/a/bjad/nf86w2dv.htm 以下是源代码: <html> <he ...

  7. 奇虎360诉腾讯QQ垄断案之我见(3Q大战之我见)

    这两款软件我都在用,要说时间最长感情最深的应该是腾讯QQ,1999年诞生的那年就在用QQ了! 不过感情归感情,个人看法归个人看法,不能用感情来判断. 正所谓外行看热闹,内行看门道.从事实上讲在使用这两 ...

  8. 腾讯QQ认证空间4月27日已全面开放申请,欲进军自媒体

    今天看到卢松松的博客上爆出,腾讯QQ认证空间4月27日已全面开放申请的消息,这一消息出来, 马浩周根据提示方法进行申请,下面先说说腾讯QQ认证空间的申请方法: QQ认证空间开放申请公告地址:http: ...

  9. 腾讯qq的发展史

    腾讯qq的发展史 即时通信软件的历史并不久远,但是它一诞生,就立即受到网民的喜爱,并风靡全球.    在其发展史上,以色列人功不可没.正是四位以色列籍的年轻人,在1996年7月成立的Mirabilis ...

随机推荐

  1. C++ Prime:函数

    局部静态对象: 某些时候,有必要令局部变量的生命周期贯穿函数调用及之后的时间.可以将局部变量定义成static类型从而获得这样的对象.局部静态对象在程序执行路径第一次经过对象定义语句时初始化,并且直到 ...

  2. 【pm2】

    告别node-forever,拥抱PM2 pm2及forever模块是目前较常用的nodejs进程守护模块,前者更常用些.功能也更强大(提供负载).其原理主要是pm2开启一个主进程,另行再开子进程运行 ...

  3. 【转】如何使用TestFlight进行Beta测试 -- 不错

    原文网址:http://www.cocoachina.com/ios/20141022/10009.html 假如你现在完成一个App的开发并准备进行真机测试,那么请问你会怎么做呢?难道是直截了当的把 ...

  4. EF框架搭建

    EF框架搭配lambda表达式使用起来非常高效便捷,有两种方法使用EF框架: 一是.添加“ADO.NET Entity Data Model”项,绑定配置数据库链接,勾选表和存储过程等,自动生成实体: ...

  5. LR(1)表驱动语法分析程序

    /* * LR(1) 语法分析 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #inc ...

  6. ARC __bridge modifiers demystified

    http://stackoverflow.com/questions/14207960/arc-bridge-modifiers-demystified Because I learned what ...

  7. 找回linux丢失的磁盘空间

    最近一台服务器空间总是报警,磁盘空间不足. 使用 df 命令查看,磁盘空间耗用接近 100%,将机器上过期的数据以及日志清理掉,但是空间很快又是接近 100%. 使用 du 查看,想找出磁盘空间被耗用 ...

  8. Yii框架tips(转)

    yii的一些小的技巧 http://www.yiichina.com/topic/151 db组件 'schemaCachingDuration'=>3600, 为什么不起做用?需要开缓存 如何 ...

  9. 微信开发 提示 Redirect_uri参数错误解决方法

    出现这个问题有多种原因: 1.没有配置网页授权 我们可以根据微信的开发者文档http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d ...

  10. mvn创建web项目

    1. 新建maven项目,选择maven骨架maven-archetype-webapp来建立web项目 2. 选择next,输入groupid:MavenWebTest, artifactid:cn ...