转载: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#4.0新特性之协变与逆变

    1.C#3.0以前的协变与逆变 如果你是第一次听说这个两个词,别担心,他们其实很常见.C#4.0中的协变与逆变[1](Covariance and contravariance)有了进一步的完善,主要 ...

  2. EF中使用SQL函数

    SqlFunctions引用命名空间:using System.Data.Objects.SqlClient; db.Favorite.Where(_ => SqlFunctions.PatIn ...

  3. VS2010+Oracle11+Entity Framework4.1环境搭建及常见问题(转)

    一,开场白: 在微软的实体数据模型中存在四种查询方式:SQL字符串:Linq:Linq to SQL:Linq to Entity(ESQL) 对于Linq SQL目前微软虽然仍在支持,但微软已经声明 ...

  4. Java---XML的解析(2)-DOM4J解析/Xpath

    Dom4j: Dom SUN dom在加载时,将所有元素全部加载内存 DOM4j - 第三方. Dom4j是一个开源.灵活的XML API. 目前很多开源框架如struts,hibernate都使用d ...

  5. HTML5 Canvas核心技术—图形、动画与游戏开发.pdf3

    路径与子路径 在某一时刻,canvas之中只能有一条路径存在,Canvas规范称之为“当前路径”(current path),这条路径却可以包含很多子路径(subpath),子路径是由两个或者更多点组 ...

  6. ambari的重新安装

    ambari是什么呢? 这里我简单说一下ambari的目的,他的目的就是简化hadoop集群的安装和管理.对于安装简化到什么地步呢?只需要几个命令,在页面上配置几个参数,几百几千个节点的集群就能安装成 ...

  7. xcode7下开发ios9等相关问题记录

    1.默认使用HTTPS请求如果在Xcode 9之前使用的时http请求,那么在XCode 9上编译的App是不能联网的,会提示如下错误:App Transport Security has block ...

  8. canvas 时钟

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. ActiveForm

    ActiveForm要和Model一起使用 我想在你的控制器的action中,至少应该这么写: /*action*/ $model = new Comments(); //实例化 Comments m ...

  10. (4/18)重学Standford_iOS7开发_框架和带属性字符串_课程笔记

    第四课(干货课): (最近要复习考试,有点略跟不上节奏,这节课的内容还是比较重要的,仔细理解掌握对今后的编程会有很大影响) 本节课主要涉及到Foundation和UIKit框架,基本都是概念与API知 ...