赞
踩
网页游戏又称Web游戏,无端网游,简称页游。是基于Web浏览器的网络在线多人互动游戏,无需下载客户端,不存在机器配置不够的问题,最重要的是关闭或者切换极其方便,尤其适合上班族。
页游的运行环境不光有操作系统,还有浏览器,所以兼容性测试在操作系统以及系统运行库的基础上还需包括各种浏览器(与浏览器热键是否冲突:网页全屏、网页上右键等)以及页游特性的运行库(不同版本的JDK以及不同版本的flashplayer等)当然,现在U3D遍布天下,fiashplayer什么的已经不用关心了。
做页游的一些特性:
1. 快速:页游里面如果玩一个RPG或者ARPG的游戏,这样的产品新手引导基本上都很快的。这样的感觉很好。但是,新手引导玩了以后迷茫了。
2. 苛刻:就拿掉落和杀怪来说,在里面玩是一种煎熬。对于几类用户可以排除:有经济来源(有一个额度条件)、接触产品少、题材的粉丝、经典游戏的广告(传奇)、小白用户等。
3. 载体:不得不说浏览器在PC上面的重要度。用简单快捷方便都不能概括得了。
在页游里面固态化了玩法,因为游戏本来是让玩家来创造玩法的。页游里面的限制条件很多,直接扼杀了这样思维。说PK战术在上面不值得一提(部分产品除外)。感觉页游付钱基本上就是开外挂的行为。
混搭式类型成主流
中国页游规模不断扩大,每年均以高增长速度推出新游戏,用户量也是与日俱增。继承了端游的优良传统,起初角色扮演RPG类型游戏最受欢迎,代表作为《热血三国》,后来是模拟经营和休闲竞技类游戏接过了主流接力棒,代表的游戏有:《商业大亨》、《弹弹堂》。09年-10年角色扮演类游戏如《明朝时代》、《傲剑》,游戏结合了角色扮演、策略、冒险等多种游戏模式,使得微创新的混合型游戏大热,这种趋势也已经演变成当前的主流元素。
网页游戏优点
网页游戏的优点。它不需要客户端,比如战争策略类网页游戏《铸剑》就可直接通过网页进行游戏,它采用Java网页技术,在IE 浏览器上输入游戏网址,不需下载客户端,即可进行游戏。游戏拥有精美的画面、庞大的战争系统和高级趣味性。玩家在游戏中扮演一名乱世中崛起的将领,逐步建设城池,提升科技,招募军队,并开拓新的城池和领地,成为一代天骄。这种方便的游戏方式无疑扩大了针对人群,也是网页游戏爆发的根本原因之一。再则网页游戏形式简单,内容丰富,对玩家的吸引力和黏度也得到了很大的提高,很多网页游戏的玩家其实每天只是习惯地做着重复的简单操作,但是他们依然乐此不彼。[
策略游戏不断丰富
游戏内容多样化
市场不再是体育游戏,策略游戏称霸的局面,各种类型的网页游戏纷纷获得市场的认可,宠物类,仙侠类,RPG类,经营类,游戏不断涌现。讲一改过去单调的市场结构,对于网页游戏市场健康持续的发展将会产生极大的影响。不断推陈出新,开拓创新是页游发展之根本,当前真正实现网页游戏内容突破的当属新游《九龙朝》,以中国九大王朝的历史为背景,极大还原了九朝更替的历史进程,独创网页游戏高清环境引擎系统,游戏中的场景生动逼真、流岚甚至倒影都清晰可见,真正把游戏做得比电影还要精美,开创了电影页游之先河。[
消费群体不断成熟
用户不是不舍的花钱,是你要让他们觉得物有所值。大部分消费者还没有形成主动的消费意识,市场还需要开发商和运营商共同努力来培育。没有消费群里的行业是没有发展基础的。网页游戏市场的消费群里正在不断成熟,一些市场的大作,也都获得了可观的盈利。但是,同时我也要提醒这些厂商们,不要把玩家逼得太紧了,有时候,你们可能适得其反,可能得意一时,不过千万要小心,不要被玩家所抛弃。要知道,网页游戏玩家的忠诚度,真的没有很高。通过自身技术实力的提高,提供更加优秀的网页游戏作品,不断满足玩家新的需求,真正把消费者当作上帝一样对待,这样的企业才能在激烈的市场竞争中取胜。
市场集中度提高
以前的网页游戏市场鱼目混珠,各路神仙都在这里企图捞一把油水。各种小作坊式的游戏屡见不鲜。头一月封测,第二月内测,第三月倒闭,几乎成了这些小游戏的发展定律。市场朝着大国争霸的局面发展,几家大的上市公司,将会依靠自身强大的经济实力,迅速垄断市场的各种资源。在为玩家提供更加专业的服务,更加完美的游戏同时,使整个行业的集中度不断提高,形成几家大的公司联合垄断的情境。当然,不希望看到这种局面,所以也要提醒那些正在企业参与网页游戏开发的小团队们,踏踏实实的搞策划,认认真真的做产品,才是你们发展的王道。这个市场正是因为你们才有了活力,也希望你们能够真正做出让玩家喜爱的游戏作品来。
游戏跨形态融合
得益于FLASH技术成熟以及我研发人才的积累,全像素、即时制游戏已经成为市场主流产品,在体验上已经与主流2D客户端网游相媲美。
页游产品也逐渐与客户端网游相融合,为了满足用户对于画面表现力的需求,部分页游产品也推出了其补充用客户端如《天书奇谈》;亦有网游研发商推出品牌系列的客户端网游,如《梦幻昆仑》&;《梦幻昆仑Onweb》产品策略。网页游戏从单纯的碎片化游戏逐渐向多形态延伸,向深度游戏、手机游戏延伸,如《诛神》。
产品结构渐丰富
中国网页游戏产品类型在2009-2011年的2年之间,完成了类型的全面丰富:2009-2010年,策略战争类游戏独霸市场,而今,产品类型高度丰富,市场上可见的986款游戏之中,角色扮演类占据38%市场份额,而战争策略类占据了36%市场份额,角色扮演类游戏已经成为市场新生力量。而塔防、养成、休闲竞技类新型游戏也在2010-2011年涌现,获得了玩家和市场的认可。
步入全球化运作
随着中国网页游戏市场的成熟和竞争激烈,页游厂商纷纷将视角转向海外市场。由于中国有着良好页游商业化运营经验,产品步入海外市场均获得了良好的成绩:昆仑、乐港等出口领先的网页游戏研运一体商在海外市场的收益已经与国内运营收益相当,且出口覆盖国家及地区也越来越广。
企业品牌意识增强
为了有效的保留自有用户、充分利用海量运营数据、更细致地服务用户,更好的完善产品,延续产品,中国网页游戏研发企业纷纷构建自己的运营平台,以培养自有用户,并代理其他企业产品。在这一过程中,让用户对于精品游戏和研运一体企业有更好的品牌认知,哥们网就是其典型代表。
可以说策略类游戏这是最主流的一类网页游戏,玩家在游戏中扮演的是一块领域(星球/国家/城市等)的统治者,可以招募英雄(将军),通过发展自己的领域去占领周边的领域,或者侵占其他玩家的领域。战争以系统自动计算的方式进行,胜负取决于双方的军事实力,所以不在线的玩家只要建设好防御设施拥有足够的防御兵力就不用担心被别人侵略。
“借鉴”了《OGAME》的作品可谓举不胜举,较为流行的就有:《战千雄》、《卧龙吟》、《战神世界》、《地球帝国网络》、《乱舞春秋》、《图腾三国》、《世界领袖》与《三国风云》等。
这类游戏虽然在玩家数量上不如前面的战争策略类游戏,不过宠物养成类的游戏数量可绝对不比任何战争策略类游戏少,比较知名的如《怪物世界》、《宠物特工》、《创世之光》、《最终幻想WEB》等。这其中MOP的《猫游记》已经成了养宠型网页游戏的代表之作。与其他类型的WEB游戏相比,该类型游戏更注重玩家之间的交流与互动,更接近于一个社区网游。游戏中,玩家可以培养自己的宠物,通过打怪练级来提高宠物的各项属性,还可以和其他玩家的宠物进行PK竞技。同时,宠物还可以拥有自己的技能和装备,可以与其他宠物合成......但从宠物系统上来看《猫游记》已经和普通的网络游戏没什么两样了。
角色扮演类网页游戏中的《笑傲江湖》大概可以算是中国网页游戏的鼻祖级游戏了,《笑傲江湖》从最早的江湖聊天室演变发展而来,早在2000年的时候就曾经风行一时,拥有N多个游戏版本。玩家在游戏中扮演初出茅庐的侠客,通过各种方式(如任务、打怪、PK等)升级提高自己的能力属性,可以购买或打造武器装备、修炼或自创武功技能,可以创建或加入某个门派。基本上武侠题材类网游所拥有的功能,它都能实现。
休闲竞技类游戏是当前最受欢迎的网页游戏之一,用户可以在放松身心的同时获得游戏带来的乐趣,休闲竞技类游戏通常操作简易,画面以卡通形象为主,内容又十分丰富,同时游戏又带有一定的竞争性,是玩家带有娱乐的心态去竞技。比如:弹弹堂,坦克大战,热舞街等。
模拟经营类游戏是由玩家扮演管理者的角色,对游戏中虚拟的现实世界进行经营管理。模拟经营类游戏按游戏载体分,主要包括模拟经营类单机游戏和模拟经营类网页游戏,模拟经营类网页游戏主要表现在体育类型较为多一些,代表作由:足球经理、篮球经理、商业大亨等。
尽管网页游戏应用的是服务器端脚本编写,但是运行还是需要一定的客户端技术支持的,比如网页浏览器,或者浏览器上常用的一些插件,如Flash. 最新的网页游戏典型应用是大型多人在线角色扮演游戏(MMORPG:Massive Multiplayer OnlineRole-Playing Game)。根据开发技术的不同,网页可分为:
浏览器端采用JavaScript/Vbscirpt等开发的网页游戏,这类由于技术限制,多为策略型和简单图片型,90%以上的网页游戏都是采用这种技术开发。
浏览器端采用flash或Flex开发的网页游戏,这类由于flash10的支持,可以做到类似客户端网络游戏的画面,但受限于flash本身,在处理大规模场景的地图、即时战斗、同屏角色效率问题上有很大的局限。但flash对多媒体的支持是比较强的。这类是网页游戏的开发未来方向之一。
另外,还有极少数基于Shockwave、ActiveX插件的网页游戏,但由于难度较高,且限制较多、效果一般,所以使用者更少。
一个是整个行业出现非常严重的版权山寨化,很多游戏企业没有授权也可以用别人的形象、情节;我们看到不同的厂商出来的都是一样的;二是严重同质化,同样的游戏能达到上百种;三是游戏无脑化,很多游戏的战斗过程非常无聊,不重视剧情。
纵观国内游戏市场,端游、页游市场增长放缓,手游强势崛起,在思考页游的未来之路时,很多行业大佬都曾表态,“避免同质化”和“创新”是改变的重要课题。而页游的同质化,除了玩法上难有突破外,因游戏剧情苍白的代入感而引发的用户高流失,也是页游厂商面临的一大难题。
4月中旬,在上海的一次媒体开放日活动上,起点中文网副总周奕(微博)明在活动现场进行了主题为《网络文学与游戏IP合作模式》的干货分享,在提到网络文学对游戏行业的重要性时,曾通过现场举手调研的小活动,引出了这样一个数据:网络游戏玩家与网络文学用户的贴合度,达到了78.4%,并且58.8%的网络文学用户在使用网络游戏时产生付费。由此可见,网络文学用户与游戏玩家,他们所接触到的文化理念和消费习惯都是高度贴合的,而人气网络小说IP与网络游戏的合作,就是提高游戏玩家代入感最有效的手段之一。
周奕明同时认为,网络文学具有IP的组合叠加效果,对网络游戏生命周期的延长有明显的促进作用。例如:热门网络小说的出版,往往会第一时间引发游戏、动漫的改编跟进。刚开始改编游戏的时候,小说本身的书迷只是最初的种子的用户,但随着小说、动漫的陆续出版,以及后续可能的影视改版上映,原本种子用户群体就会不断扩散,而且最终又会回流到游戏和小说上来,这和纯买一部电影、一个综艺节目的改编权有着本质上的区别。
【转自】http://www.cnxct.com/experience-with-webgame-of-security-and-defense/
在这篇日志里,我将以webgame研发者角度,切合游戏业务模块逻辑,从业务需求,数据库设计,程序编写,操作方式上来讲解漏洞形成原理,规避方案,也欢迎大家讨论。
近几年,网页游戏几乎都是以联运方式运营,意味着游戏服务器本身不保存用户密码,用户登录在平台,通过平台跟游戏服务器的接口对接登录。接口做加密认证。故webgame的帐号密码安全问题,这里不提了。但登录认证的hash字符串安全,也还是要注意的。比如登录hash字符串的生效时间,hash字符串的加密参数来源,比如包括用户名、登录IP,浏览器user-agent等数据,以防止改hash被泄漏了,也是很难通过服务器的验证。
页游的游戏充值流程,跟普通网页充值流程一致,没有特殊的地方,其不同点就是跟其他众多平台做联合运营时,势必要每个公司做接口对接,且接口规范各式各样,且游戏厂商没有话语权,必须按照他们的接口规范来,这实在棘手。腾讯的充值接口的验证方式,安全性做的较为突出,大约代码:
-
// 返回参数列表
-
-
$signKey = array(
'openid',
'appid',
'ts',
'payitem',
'token',
'billno',
'version',
'zoneid',
'providetype',
'amt',
'payamt_coins',
'pubacct_payamt_coins');
-
-
$sign = array();
-
-
//从GET参数中,对比找出上面参数的值
-
-
foreach($signKey
as $key ) {
-
-
if (isset($data[$key]))
-
-
{
-
-
$sign[$key] = $data[$key];
//只有 GET里有的参数,才参与sig的计算
-
-
}
-
-
}
-
-
######开始生成签名############
-
-
//1: URL编码 URI
-
-
$url = rawurlencode($url);
-
-
//2:按照key进行字典升序排列
-
-
ksort($sign);
-
-
//3: &拼接,并URL编码
-
-
$arrQuery = array();
-
-
foreach ($sign
as $key => $val )
-
-
{
-
-
$arrQuery[] = $key .
'=' . str_replace(
'-',
'%2D',$val);
-
-
}
-
-
$query_string = join(
'&', $arrQuery);
-
-
//4 以POST方式拼接 1、3 以及URL
-
-
$src =
'GET&'.$url.
'&'.rawurlencode($query_string);
-
-
// ## 构造密钥
-
-
$key = $
this->config->get(
'qq_appkey').
'&';
-
-
//### 生成签名
-
-
$sig = base64_encode(hash_hmac(
"sha1", $src, strtr($key,
'-_',
'+/'),
true));
-
-
if ( $sig != $data[
'sig'] ) {
-
-
$
return[
'ret'] =
4;
-
-
$
return[
'msg'] =
'请求参数错误:(sig)';
-
-
$
this->output->set(json_encode($
return));
-
-
return ;
-
-
-
}
在此基础上,还可以做的严谨点:
增加随机参数名、参数值。随机参数名、参数值由联运方随机生成,按照参数名的字符串所属ASCII码顺序排序,参数名、参数值均参与sign的计算,增加暴力破解密钥(app key)难度。
增加回调验证订单号,金额信息。游戏充值服务器接收到充值请求时,反向到该平台回调接口,确认此笔订单有效性,以防止加密密钥泄漏的问题。
在网页游戏的研发中,多数都是使用框架来做,即使用REQUEST来的参数,作为请求文件名的一部分,来使用,那么很容易形成远程文件引入的漏洞。在我们之前的游戏中,曾出现过一例这样的漏洞问题。
// Load the local application controller // Note: The Router class automatically validates the controller path. If this include fails it // means that the default controller in the Routes.php file is not resolving to something valid. if ( ! file_exists(APPROOT.'controllers/'.load('Router')->getDirectory().load('Router')->getClass().EXT)) { load('Errors')->show404('Unable to load your default controller. Please make sure the controller specified in your Routes.php file is valid.'); } include(APPROOT.'controllers/'.load('Router')->getDirectory().load('Router')->getClass().EXT); load('Benchmark')->mark('load_basic_class_time_end');
页游中的远程文件引入
从代码以及案例图中,可以看到对于REQUEST的参数没有过滤处理,直接作为文件名来include引入的,故导致这种问题,类似上页图中,若PHP version < 5.3.4 ,还会发生Null(%00) 截断的问题,带来更大的安全问题。在我们新的项目中,我们更改了实现方式,我们游戏所有接口都会走gateway,gateway里,对控制器名做类名规范的检测处理,再在指定几个目录下做autoload加载文件,且还会对REQUEST的类名、方法用ReflectionClass反射类的处理,检测到类、方法、参数是否合法。一来避免『远程文件引入』漏洞问题,二来便于前后端联调时,抛出更详细的异常,方便调试。下面为参考代码:
-
require_once CONFIG_PATH .
"/auto.php";
-
-
spl_autoload_register(
"__autoload");
-
-
……
-
-
//默认消息格式
-
$view->clear();
-
$view->error(MLanguages::COM__INVALID_REQUST);
-
$msg =
new Afx_Amf_plugins_AcknowledgeMessage($val->data[
0]->$messageIdField);
-
$msg->setBody($view->get());
-
-
$message->data = $msg;
-
-
…
-
-
$a =
new Yaf_Request_Simple();
-
$a->setControllerName($method[
0]);
-
$a->setActionName($method[
1]);
-
-
$objC =
new ReflectionClass($method[
0].
"Controller");
-
$arrParamenter = $objC->getMethod($method[
1].
"Action")->getParameters();
-
-
$arrRequest = isset($val->data[
0]->body[
0]) ? (array)$val->data[
0]->body[
0] : array();
-
-
$bCanCall =
true;
-
-
foreach ($arrParamenter
as $objParam)
-
-
{
-
$parm = $objParam->getName();
-
-
$bIsOption = $objParam->isOptional();
//是否为可选参数
-
if (isset($arrRequest[$parm]))
-
-
{
-
$a->setParam($parm , $arrRequest[$parm]);
-
-
}
-
-
elseif ($objParam->isOptional())
-
-
{
-
//可选参数
-
}
-
else
-
{
-
$bCanCall =
false;
-
}
-
}
-
if ($bCanCall)
-
-
{
-
$rp = $app->getDispatcher()->dispatch($a);
-
$msg =
new Afx_Amf_plugins_AcknowledgeMessage($val->data[
0]->$messageIdField);
-
$msg->setBody($view->get());
-
$message->data = $msg;
-
}
SQL注入原理、方式,跟普通web应用一样,没什么特别的,在使用REQUEST来的参数时,过滤处理即可。可能在消息格式,以及注入操作简便上,会蒙蔽研发人员的眼睛,被忽略掉了。比如我们项目的AMF消息格式,在前端界面没出来之前,我们后端程序员一般使用Pinta来模拟操作,调试程序。前端界面出来之后,会使用Charles proxy来捕捉http请求。在这些过程中,请求接口、参数的构造,没有普通web那么简单。研发人员也容易忽略对请求参数的过滤,故很容易形成这种问题。形成原理见:《WEB开发安全与运维安全浅见》,防御方式做过滤处理,或SQL预编译。
AMF消息格式的WEBGAME中的SQL注入
AMF消息格式的WEBGAME中的SQL注入
为了提高游戏服务器的吞吐能力,网页游戏的架构也是一直在演变的。在之前以Mysql作为数据存储的webgame架构中,其他节点都是可以水平扩展,或者说依赖简单粗暴的增加服务器来解决,单单作为唯一数据存储中心,不能这么做。为此,很多webgame的数据存储改用Nosql来代替,甚至java、C/C++的游戏数据,直接在内存中操作,游戏关服时,才写入到DB中。故SQL注入的问题,也会越来越少。
网页游戏虽然名字叫网页游戏,但通讯协议并非全是http,也有很多使用socket,以及http+socket并用的做法。我们是http协议+amf消息格式,以及socket并用来实现。在http与https的取舍上,我们考虑到ssl的启用后,大量的ssl解密加密运算,势必会增加服务器大量的CPU计算压力。而传输的内容,多数是游戏业务的操作,响应,是能接受被监听嗅探的行为的(认证信息除外)。站在安全角度,这不能理解。但站在产品角度,考虑一下投入产出,然后选择http通讯,也是可以理解的。socket在我们游戏中,除了在聊天应用上使用外,在一些组队、帮派战之类需要多个玩家之间同步数据信息时,我们也会使用socket来推送数据。在使用socket作为所有业务传输的协议时,协议格式一般都是开源协议,比如msgpack、protobuf之类,或者自定义的协议。使用自定义协议时,务必检测整个消息包的每一个参数,类型范围,避免个别超大数值、边界数值出现,导致主程序内存越界,以至于服务宕机,无法正常服务的情况发生。
在java中,4字节的存放int型变量的范围是-2147483648至2147483647。在java、c的有符号int型中存储时,数的最高位描述符号位,4字节共32位,除去最高位的符号位,剩下31位,每个位上能表示2个数字,4字节的有符号的整数表示范围为:负整数2^31个,范围为『-1至-2147483648』;正整数2^31个,范围为『2147483647至1』。 比如下图(注意十进制数字跟二进制表示的变化顺序):
当开启格子数字为大于31时,比如32,那么所需费用就是2147483647个银两,再买点其他物品,凑成超过2147483647的数字,比如又买了3个银子的其他道具,总共花费2147483650个银子,在4字节的有符号int中表示出来的结果,变成符号位为1,即负整数。数值位为0000000 00000000 00000000 00000010,也就是1000000000000000 00000000 00000010,对应十进制的-2147483646。程序逻辑上,再判断现有银两是否足够支付此笔花费时,是通过的。当使用当前余额减去这笔花费时,将变成减去一个负数,那么实际上就是加上一个正整数。变成了自己银两账户余额的增长。而余额字段类型是long,则正确的存储了这些余额,溢出漏洞被利用。在C中,使用无符号的数值类型,即可完成数值类型溢出刷钱的行为,但在java中,好像没有无符号的类型。这也可以先确定所有参与计算的数值必须为正整数作为必要条件(游戏业务特性,游戏内所有数字,肯定全为正整数,甚至都不包括零),先做大小判断,再做正正相加,不能得负;负负相加,不能得正。来判断是否发生了溢出问题。在PHP中,不用担心溢出问题。 更多信息参考:《溢出,符号与进位》
不光是程序中,整型变量类型得需要注意,使用unsigned int在存储数据的DB中也要做同样的处理,对于存储整型数字的字段,均设置为unsigned int/tinyint/...。在游戏中,数字几乎全是自然数,几乎不会出现负整数的情况。
Rpg类型的网页游戏中,多数都有道具出售的功能,直接卖到商店,以及道具材料从商店买入功能。当玩家同时针对买入、卖出两个操作,瞬间大量并发请求时,在服务器的处理逻辑一般有分别的两个进程处理,共享数据分别数据库中的对应账户余额表,如下图:
页游买入、卖出并发请求处理:
-
//卖出
-
// startTrans
-
$iBalance = $obj->getBalance(
'user1');
//余额50
-
//UPDATE `role_gold` SET gold = 150 WHERE role_id = 1
-
if(!$obj->setBalance(
'user1',$iBalance +
100))
-
{
-
//rollback
-
}
-
//扣除物品
-
if (!$obj->delItems($items))
-
{
-
//rollback
-
}
-
//commit
-
//买入
-
// startTrans
-
$iBalance = $obj->getBalance(
'user1');
//余额50
-
//UPDATE `role_gold` SET gold = 0 WHERE role_id = 1
-
if(!$obj->setBalance(
'user1',$iBalance -
50))
-
{
-
//rollback
-
}
-
//发放物品
-
if (!$obj->addItems($items))
-
{
-
//rollback
-
}
-
//commit
卖出请求的处理进程为1,买入请求的处理进程为2。在进程1还没将结果写入到DB时,进程2也从DB读取到余额为50。这是,两个进程拿到的余额信息都是50。进程1按照逻辑代码,计算出剩余余额是150;进程2计算出的剩余余额是0。最后,不管那个进程最后写入余额,都是错误的结果。(注:这里的代码逻辑操作,跟mysql事务无任何关系,事务只能保证单个进程的事务范围内多条语句都正确执行,或回滚。比如能保证扣钱成功,且物品删除掉的两个语句都正确执行。能保证其中之一的语句执行失败时,都正确回滚。)
其实,在事物开启时候,SELECT语句是否可以取到最新的数据,或者是否需要等待锁释放,取决于MYSQL的事务隔离级别。在MYSQL的事务隔离级别中,有一下几种隔离级别:
对于READ-UNCOMMITTED,可以读取其他事务中未提交的数据,而且据说性能还高不到哪里去,几乎没有在实际应用中使用;对于READ-COMMITTED,在同一事务中,会因为其他事务随时可能有新的commit,导致同一select可能返回不同结果。这个也不适合游戏业务;再说第四个SERIERLIZED,只要事务开启,所有其他查询,均排队等待该事务提交之后,对于上面提到的卖出买入情况,第二个事务的SELECT操作,不会立刻返回,会处于锁等待状态,一直到前一个事务结束。这个隔离级别,虽然能避免上面的问题,但性能较差,一般不会去使用。而REPEATABLE-READ隔离级别,也是mysql默认的隔离级别,从功能上,比较符合游戏业务需要,也应该是广大webgame架构中mysql的默认隔离级别。在使用REPEATABLE-READ隔离级别时,select的数据,都是事务未提交之前的数据,而每个事务都能正常成功执行,故错误的结果被执行出现。
对于这个问题,你可能很快就给出解决办法,把UPDATE语句改为UPDATE`role_gold` SET gold = gold + 100 WHERE role_id = 1或者UPDATE`role_gold` SET gold = 150 WHERE role_id = 1 AND gold = 100来解决,但这种多个事务同时操作修改多个表的多条记录时,还容易引发死锁问题,比如《webgame中Mysql Deadlock ERROR1213 (40001)错误的排查历程》。而且,当条件为跨表内数据是否存在,或者另外条件不在MYSQL中,而在其他网络接口的响应中时,如何做呢?
引用DNF的漏洞新闻 《利用网游漏洞狂刷游戏币赚钱 玩家自曝3天赚17万》
玩家曝出刷币漏洞 一个游戏道具可刷400人民币,该漏洞到底是什么?原来游戏中“云幂袖珍罐”这个道具,可以开出2件一样的游戏装备,还有极少几率开出游戏币,开出的装备不值钱,但如果开出金币了,则分为5000万、8000万以及1亿游戏币。而1亿游戏币,按正常市场行情,可在交易网上卖400多元人民币。据玩家称,在游戏中,角色的装备是需要用包裹来存放的,不过目前角色的包裹最多只有48格,也就是只能存放最多48件装备。漏洞就是利用包裹的有限空间,存放47件装备(存放满了又无法开罐子),只留下一格空位,而在开“云幂袖珍罐”出装备时,就会因包裹空间不足,而导致开罐失败,而罐子还存在。玩家继续开罐,直到出现金币,但金币不会占据包裹的空间,因此开罐成功,然后罐子消失。发现这个漏洞后,部分玩家狂刷游戏币,然后马上在第三方交易平台出售游戏币,兑换成现金。
这种问题,都是研发人员逻辑不严谨导致,这种问题,也较难发现。规避方式可以依赖下面提到的『运营数据监控』。
跟上面的卖出、买入一样,同时穿装备、整理包裹。在设计时,可能会将身上装备设计在装备表中;将不在身上的装备,设计到背包表中。当同时进行穿装备跟整理包裹的请求并发时,也会发生跟上面卖出,买入的情况,线程1读取DB,发现包裹里有这装备,然后准备删除背包表的这条记录,当准备写入到装备表时,另外一个整理包裹请求的线程来了,读取了整个背包表,进行道具的合并、排序。这时,之前的线程将这个装备写入到装备表,并删除了背包表里的数据,并提交事务。这个穿装备的所有操作都是合理、正常,且正确执行的。但另外一个整理背包的线程读取了之前的背包表里的数据,包括那件被穿上的装备。在游戏中,整理背包需要对可堆叠道具做堆叠操作的,意味着需要合并多个道具,删除部分道具。这意味着这里的操作,当前cgi线程的内存中的数据,将都会以覆盖的形式,写入到DB中,那么意味着,之前被穿到身上的那件装备,也会重新被写入到背包中。那就变成两张表里出现了两个相同唯一ID的相同属性的道具。玩家就可以把背包中的这个道具出售给其他玩家。
在java或者C之类程序中,数据放内存中的游戏,也会存在这个问题,除非做读锁,但读锁会带来锁等待,锁等待会导致线程被占用,阻塞后面请求的处理,堆积大量请求。导致系统负载升高,服务器繁忙,以至于无法响应。好了,大约理解道具复制的形成原因了吗?这个问题,我们从根本原因想想,问题到底出现在哪里?如何规避呢?细心的同学不难发现,对于穿装备的操作结果,会对下一个请求产生影响的,当前操作未得到服务端响应之前,服务端是不能处理下一个响应的。对此,我们做了响应处理锁--『用户并发请求锁』。
用户并发请求锁的实现,php中session以文件形式存储时,php会对session文件加锁,不释放(如果不特意执行session_write_close),知道当前响应完成。另外一个线程才可以正常读取,这简介的形成了单个用户的并发请求锁,但是,后面的进程一直处于等待状态,也会占用一个php-fpm进程,阻塞其他用户的正常请求对php线程的使用。为此,我们使用NOSQL的K-V形式结构,以user_name为key的形式,实现用户并发请求锁,比如 redis的setnx接口,原子性判断操作有则返回false,,没有就添加一个,返回true。那么,对于下一个请求,setnx时,返回false,有这个key了,那么立刻抛出异常,结束响应,FLASH根据异常内容,提醒用户不要进行恶意操作。即不会发生并发请求,又不会阻塞请求处理。同时,在请求结束的析构函数里,对这个锁进行删除操作,不影响下一个正常请求。若因为程序异常,发生语法错误,导致析构函数没法执行,没有删除用户锁时,可以在生成锁的时候,设置过期时间,比如5秒,甚至2秒,利用nosql的过期机制,实现用户解锁,避免用户长时间无法正常游戏。
现在研发的项目,是以NOSQL Redis作为DB,来存储数据的,redis并没有成熟的事务处理机制,watch甚至算不上关系型数据库中的事务处理。对此,更需要对表进行加锁解锁。java之类语言的项目,很多都是直接操作内存的,更是需要资源锁,来解决并发问题,解决多个请求操作同一份数据的问题。公司有另外一个项目,出现过一次因为锁的颗粒度较大,带来的锁等待timebomb的问题,也导致了线程繁阻塞忙,请求堆积,系统负载上升,导致宕机的问题。这个项目的锁是针对所有用户的锁,每个用户的请求发来时,当前线程会对所有用户的数据加锁,直到响应完成,才释放掉。这么做,是为了解决因当前操作,会影响到其他用户数据,比如多人PK,多个玩家之间的交互。
当其他请求一并发来时,那么资源会立刻被锁住,直到上一个请求结束,才释放锁,那么其他线程都处于等待状态。用户基数小时,是看不出来锁带来的影响的,内存操作都比较快。当用户基数大时,或者说请求数增大时,后面的请求的等待时间会越来越长,超过webserver的等待时间,直接返回timeout,不能正常提供服务。
这种问题的发生,是因为锁的颗粒太大了,不应该将所有用户都锁住,最好细化到当前请求所影响到的单个用户,只锁住单个用户的数据。这样,才减少timebomb的发生。
知乎里的朋友提到,很多webgame的前端做了判断,而后端没做判断的问题,这种问题,实属不该存在。在我们的项目中,后端做的验证判断,远比前端多的多。有时候,为了界面上的动画表现,前端flash一般会在用户操作之后,立刻渲染,然后,再根据后端响应,决定是否继续做界面元素改动。比如脱装备,玩家操作时,会先渲染装备从角色面板,跳到背包里的动画,然后,再根据后端响应结果,决定是否回滚动画。这样,避免显得操作后,一定时间的反映迟钝假象,以提高用户体验。当然,后端是一定会做判断的,判断角色背包是否有空格之类。现在的webgame研发,一般都不会存在前端判断,而后端不判断的做法了。如果有,也应该是个别遗漏情况。
比如去年的time33算法的hashdos的问题,使用json消息格式的webgame一定要注意,php只是在接收请求时,做了最大数量的限制。但在json解码之后的数据中,是没有处理的。这里千万别忘记了。
再完善的防御措施,都仍会有安全漏洞。适当的监控措施,也一定要有,监控等级、金币、游戏币、经验、珍贵物品的变化等等,一旦发现,立刻报警,在漏洞未扩散之前,第一时间去修复漏洞,以减少损失,维护游戏平衡。
日志系统一定不能漏掉,所有操作,必须写入日志,当安全事件发生后,可以作为各种数据回滚,交易纠纷处理的可靠数据。也是作为数据监控的最准确的数据来源。
1、前端性能的意义
对于访问一个网站,最花费时间的并不是后端应用程序处理以及数据库等消耗的时间,而是前端花费的时间(包括请求、网络传输、页面加载、渲染等)。根据web优化的黄金法则:
80%的最终用户响应时间花在前端程序上,而其大部分时间则花在各种页面元素,如图像、样式表、脚本和Flash等,的下载上。减少页面元素将会减少HTTP请求次数。这是快速显示页面的关键所在。
根据著名的“2-5-8原则”,用户访问一个页面:
当用户能够在2秒以内得到响应时,会感觉系统的响应很快;
当用户在2-5秒之间得到响应时,会感觉系统的响应速度还可以;
当用户在5-8秒以内得到响应时,会感觉系统的响应速度很慢,但是还可以接受;
而当用户在超过8秒后仍然无法得到响应时,会感觉系统糟透了,或者认为系统已经失去响应,而选择离开这个Web站点,或者发起第二次请求。
对于一个网站如果希望抓住用户,网站的速度以及稳定性是首当其冲的。目前性能已经被列入google的网站的排名规则中。
2、前端性能关注的重点
2.1 加载时间指标,主要包括三个时间断
a. Time to First Impression
表示从用户在浏览器键入url按下回车键一刻开始到页面开始有反应(用户可以在页面中看见一点点内容)为止。经常能感觉到的一个信号就是网页开始显示title。
b.Time toonLoad Event
表示从页面开始显示内容,到浏览器开始触发OnLoad函数这一时间段。只有当初始的文本和所引用的对象加载完成,浏览器才开始触发OnLoad函数
c.Time toFully Loaded
表示从上一时间段末到整个网页完全加载完成(所有OnLoad函数以及相关的动态资源加载完成)。在网页中含有timeout或定时刷新之类处理时较为难判断结束点。
2.2 资源情况指标
网页由初始的html文本中嵌入图片以及通过XHR或者修改dom树动态加载的内容组成,css负责样式,js负责行为。所以当网页资源过多为了下载资源,客户端和服务器的网络来回就更多。下面是资源方面相关的指标。
a. Total Number of Requests
包括html网页请求,css、js资源下载及其它网络请求。优化的目标之一是要尽量减少请求数。
b. Total Number of HTTP 300s/400s/500s
表示返回状态为300(重定向)、400(客户端错误)、500(服务器端错误)的http请求。尽量避免这些请求,以提高页面load的时间。造成这些状态的原因经常是服务器的实施、配置和部署问题。
c. Total Size of Web Site
构成网页元素总的大小。图片或者js库的增加都会对下载时间造成重要的影响。
d. Total Size of Images/CSS/JS
image、css、js在网页元素大小中占主要比例。
e. Total Number of XHR(XMLHttpRequest)Requests
通过js异步从服务器端获得数据的请求数。一些js框架提供了跟服务器端的更新机器,就是XHR请求。通过配置可以减少XHR请求的数目
2.3 网络连接指标
浏览器底层的网络连接对资源的下载速度有很大影响。资源的下载过程分为很多阶段。下面介绍这些阶段以及浏览器、网络、请求如何影响这些阶段的时间
a. DNS Time
dns 查询的时间。网页请求会产生一次寻找该网页资源所在主机的dns查询。在同个域名进行网页切换不会造成新的dns查询。
b. Connect Time
指浏览器和服务器之间建立tcp/ip连接的时间,对于ssl连接包括握手的时间。网络连接过慢、使用ssl、使用短连接而非常连接都是造成connect time较多的原因。
c. Server Time
指收到请求后服务器逻辑处理的时间,
d. Transfer Time
这一指标与浏览器和服务器之间的连接速度相一致,通过减小传输内容或使用cdn来降低Transfer Time。
e. Wait Time
等待时间和同一个域中服务资源的数量直接相关。每个域的浏览器的物理网络的限制,导致资源等待可用的连接。减少资源的数量,或将资源散布在不同的域,能将这一时间降低。平均等待时间的大小更能反映等待时间是否需要注意。
f. Number of Domains / Single ResourceDomains
部署网站资源的域主机数量是很重要的,因为它影响的DNS,连接和等待时间。
专门用户资源下载的域是必要的,他将直接减少等待时间。应避免单一的资源域,否则你将为dns查询以及资源下载付出昂贵的代价。
3. 分辨率兼容性测试
分辨率的测试是为了页面版式在不同的分辨率模式下能正常显示,字体符合要求而进行的测试。
用户使用什么模式的分辨率,对于我们来讲是未知的。通常情况下,在我们的需求规格说明书中会建议某些分辨率。对于测试来讲,必须针对需求规格说明书中建议的分辨率进行专门的测试。现在常见的分辨率是1024×768,800×600。对于需求规格说明书中规定的分辨率,测试必须保证测试通过,但对于其他分辨率,原则上也应该尽量保证,但由于这个在需求规格说明书中没有加以约束,所以在一定程度上,开发往往会拒绝进行调整。对于需求规格说明书中没有规定分辨率的项目,测试应该在完成主流分辨率的兼容性测试的前提下,尽可能进行一些非主流分辨率的兼容性测试,在一定程度上保证大部分。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。