<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/2.3.2" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

<channel>
	<title>Zhiyong's Blog</title>
	<link>http://canremember.com</link>
	<description>blog of a game developer</description>
	<pubDate>Sat, 04 Apr 2009 15:46:26 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.3.2</generator>
	<language>en</language>
			<item>
		<title>随便聊聊网游和数据挖掘</title>
		<link>http://canremember.com/?p=22</link>
		<comments>http://canremember.com/?p=22#comments</comments>
		<pubDate>Sat, 04 Apr 2009 15:46:26 +0000</pubDate>
		<dc:creator>zhiyong</dc:creator>
		
		<category><![CDATA[开发杂谈]]></category>

		<category><![CDATA[data mining]]></category>

		<category><![CDATA[MMORPG]]></category>

		<category><![CDATA[数据挖掘]]></category>

		<category><![CDATA[服务器]]></category>

		<category><![CDATA[网游]]></category>

		<category><![CDATA[网络游戏]]></category>

		<category><![CDATA[行为分析]]></category>

		<guid isPermaLink="false">http://canremember.com/?p=22</guid>
		<description><![CDATA[<p>看到一篇旧闻 Video game Everquest 2 provides new way to study human behaviour ，说<a href="http://www.sciencecentric.com/news/article.php?q=09030120-video-game-everquest-2-provides-new-way-study-human-behaviour" target=_blank>SOE把EQ2的三年的服务器运行日志交给一群<del datetime="2009-04-04T15:22:52+00:00">叫兽</del>教授去研究</a>，研究关于个体、群体行为、社会关系等等。还不只是<del datetime="2009-04-04T15:22:52+00:00">叫兽</del>教授关注这些，还有个新闻说美国人还<a href="http://blog.wired.com/27bstroke6/2008/02/nations-spies-w.html" target=_blank>打算从WOW里面挖出几个恐怖份子来</a>，看起来很有意思，看来<a href="http://zh.wikipedia.org/wiki/%E6%8B%89%E7%99%BB" target=_blank>拉登</a>先生还是不要玩WOW的好。</p>
<p></p>
<p>顺手放狗一找，发现大量巨人和SUN合作在网游里头搞数据挖掘的<a href="http://news.17173.com/content/2009-03-26/20090326150654422.shtml" target=_blank>新闻</a>，还提出了“二次策划”的研发模式，看来此公司确有能人。放狗不止找回这些东西，行业内盛大、网易、渡口等等都有相关信息，包括不少中小公司，这些信息包括公司的招聘广告、新闻，当然也有些可能是软文，是啥文倒是都无所谓，关键是——突然发现这个行业确实已经进步了很多。数据挖掘在MMORPG上面的应用确实非常有吸引力，举例来说，可以用来验证游戏设计、平衡性、部分甚至完全地替代代价高成效低的用户调研等等。</p>
<p>还可以更神奇，举个例子，当你在一个MMORPG游戏里头奋战几个月之后突然感到很无聊，做任务、下副本、打装备都已经让你疲倦，不打算玩下去了，这个时候有人来找你聊天，你聊下来觉得这人很投缘，简直可以成为你现实世界的终身伴侣，并且感叹——“啥也别（四声）说了，都是缘分啊！”，你很<del datetime="2009-04-04T15:22:52+00:00">鸡冻</del>激动，但这可能根本就不是缘分而是‘系统’为你做了一次‘红娘’，目的是让你获得更好的游戏体验。作为一个程序员，我并不是在开玩笑，‘系统’做这个事情的方法很简单，只需要先找到适合你的那个人，然后用你的id向他（她/它）发一句——“hi”，当然他（她/它）可能也只回复了一句“hi”，但是——很可能一段轰轰烈烈的爱情就这样开始了，-_______-</p>
<p>作为一个生活在现实世界的程序员，从技术的角度来说，前面这个例子关键要解决两个个问题：哪些人感觉无聊了、也就是说哪些人潜在的流失用户，可能还得知道是为什么。</p>
<p>像是你眼神呆滞、茶饭不思、内分泌失调这一类的情形，‘系统’肯定是没法知道地，因为你和‘系统’之间的交互是通过键盘鼠标，一般来说键盘鼠标无法捕捉这些信息传递给‘系统’。那么系统怎么办呢？查找哪些用户的每小时操作指令数量偏低？查看哪些玩家的单位时间收益偏低？与其他玩家交流频度低？刚刚损失一件以上的极品装备？</p>
<p>我几乎可以肯定——能利用google和baidu搜到我这篇Blog的人们，现在已经想出很多论据来质疑前面这些方法的可行性了，程序员都很擅长质疑 :) 。但是‘系统’可以利用数据挖掘方法来做这个事情，例如‘系统’把玩家行为数据集分为‘活跃用户’、‘流失用户’两类，也就是作为训练数据，怎么区分‘活跃用户’还是‘流失用户’这个不多说了。然后再利用分类（classification）器（例如kNN），对你的游戏行为做分类。再进一步说，前面这个过程需要‘领域专家’来‘提取’玩家行为使程序能获得向量化数据，而且为了处理效率，还很可能需要对玩家行为数据做降维(dimension reduction)处理再输入分类器，否则可能就变成——只是理论上可行了。</p>
<p>太忙没精力，很久都没写blog居然还记得网站后台的密码，不容易。</p>
<hr /><h2>comments,文章评论</h2><ul><li><a href="http://canremember.com/?p=22#comment-29">2009.11月.6</a>, Chengbin comment: 很久没更新了。。。</li><li><a href="http://canremember.com/?p=22#comment-30">2009.12月.2</a>, zzping comment: 无缝怎么样子了</li><li><a href="http://canremember.com/?p=22#comment-31">2009.12月.7</a>, Tom comment: 先生，
  您好！
  我们在寻找幼儿美术画师,可以在家上班。我们看了您的新浪博客，认为不错。请回复信息。133加6195家3852，msn：yu_pengju@hotmail.com .为了争取您尽早看到，所以我们在多处作了留言，请谅。</li><li><a href="http://canremember.com/?p=22#comment-33">2010.05月.5</a>, <a href='http://www.80lunwen.com' rel='external nofollow'>论文发表</a> comment: 支持博主！</li><li><a href="http://canremember.com/?p=22#comment-37">2010.08月.26</a>, <a href='http://www.shenjieshi.net' rel='external nofollow'>南京肾结石的治疗</a> comment: 你好，我是解放军414医院的医生，刚学会写博，可以交换个链接吗？</li></ul><hr /><h2>Related posts,相关文章</h2><ul>
<!-- Generated by Simple Tags 1.3.8 - http://wordpress.org/extend/plugins/simple-tags -->
	<h4>Related posts</h4>
	<ul class='st-related-posts'>
	<li><a href="http://canremember.com/?p=10" title="无缝世界网游服务器架构的设计思路（续） (2008.02月.15)">无缝世界网游服务器架构的设计思路（续）</a> (4)</li>
	<li><a href="http://canremember.com/?p=8" title="无缝世界网游服务器架构的设计思路 (2008.02月.12)">无缝世界网游服务器架构的设计思路</a> (4)</li>
	<li><a href="http://canremember.com/?p=16" title="技术主义者的网游观点 (2008.03月.23)">技术主义者的网游观点</a> (11)</li>
	<li><a href="http://canremember.com/?p=4" title="服务器组架构设计需要考虑的一些关键因素 (2008.02月.5)">服务器组架构设计需要考虑的一些关键因素</a> (6)</li>
	<li><a href="http://canremember.com/?page_id=2" title="关于我 (2008.02月.3)">关于我</a> (0)</li>
</ul>

</ul><hr /><small>Copyright &copy 2008 Wang Zhiyong, Some Rights Reserved ;)<br /> all content of this site is under Creative Commons License <br />
 此网站所有内容采用 知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。(digitalfingerprint: e71076c267f520b120f4bb81270fe189)</small>]]></description>
		<wfw:commentRss>http://canremember.com/?feed=rss2&amp;p=22</wfw:commentRss>
		</item>
		<item>
		<title>DIY了一个寻星一体机</title>
		<link>http://canremember.com/?p=17</link>
		<comments>http://canremember.com/?p=17#comments</comments>
		<pubDate>Sun, 24 Aug 2008 11:58:50 +0000</pubDate>
		<dc:creator>zhiyong</dc:creator>
		
		<category><![CDATA[未分类]]></category>

		<guid isPermaLink="false">http://canremember.com/?p=17</guid>
		<description><![CDATA[<p>玩儿卫星接收已经快一年了，一直想做个寻星一体机，也就是寻星仪，用来调星。买各种配件、工具前前后后就花了不少时间，幸好有淘宝，否则到处去找还不得跑断腿。和上高中时候自己DIY功放等等小东西相比，现在想买点儿东西、想找点儿资料实在太容易了，不过也没那么多时间了，这就是代价，有钱没时间，有时间没钱。</p>
<p></p>
<p>寻星仪无非是小体积的卫星接收机＋锂电池组＋液晶屏，本打算再集成一个寻星频谱仪进去的，这样更方便找信号，没时间就暂时搁置了。首先要做个外壳，先是买了个铝铸压防水外壳，电钻做了开口之后才发现这实在是个错误决定，铸铝外壳太难加工了，而且又太厚重，后来只好放弃，又买了个铝合金的外壳，事实证明这个决定很正确。</p>
<p>钳工活儿开始——和做软件一样， 先做好规划设计，量好尺寸，划线，然后用电钻做初步的开口，然后再用电磨装上钨钢旋转锉修到大致平滑，然后再用钢锉、砂纸……总之这个钳工的活儿就做了两天。</p>
<p>上图：</p>
<p><img src="http://canremember.com/wp-content/uploads/2008/08/20080803_f3202ca44637a9952eedodhoalracbmethumb.jpg" alt="完成品图" /></p>
<p><img src="http://canremember.com/wp-content/uploads/2008/08/20080803_b46c55e2a0ad1215b090thg9baos98vcthumb.jpg" alt="完成品" /></p>
<p><img src="http://canremember.com/wp-content/uploads/2008/08/20080803_3363373df5103907ca1ac3ssxug6rojwthumb.jpg" alt="20080803_3363373df5103907ca1ac3ssxug6rojwthumb.jpg" /></p>
<p>用下来感觉很不错，顺利地用它重调了天线。</p>
<hr /><h2>comments,文章评论</h2><ul><li><a href="http://canremember.com/?p=17#comment-22">2008.11月.11</a>, tester comment: test</li><li><a href="http://canremember.com/?p=17#comment-28">2009.05月.9</a>, yubing comment: 你可以告诉我手机号吗</li></ul><hr /><h2>Related posts,相关文章</h2><ul>
<!-- Generated by Simple Tags 1.3.8 - http://wordpress.org/extend/plugins/simple-tags -->
	<h4>Related posts</h4>
	<ul class='st-related-posts'>
	<li>没有相关的日志</li>
	</ul>

</ul><hr /><small>Copyright &copy 2008 Wang Zhiyong, Some Rights Reserved ;)<br /> all content of this site is under Creative Commons License <br />
 此网站所有内容采用 知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。(digitalfingerprint: e71076c267f520b120f4bb81270fe189)</small>]]></description>
		<wfw:commentRss>http://canremember.com/?feed=rss2&amp;p=17</wfw:commentRss>
		</item>
		<item>
		<title>技术主义者的网游观点</title>
		<link>http://canremember.com/?p=16</link>
		<comments>http://canremember.com/?p=16#comments</comments>
		<pubDate>Sun, 23 Mar 2008 15:33:14 +0000</pubDate>
		<dc:creator>zhiyong</dc:creator>
		
		<category><![CDATA[开发杂谈]]></category>

		<category><![CDATA[ACU]]></category>

		<category><![CDATA[Cluster]]></category>

		<category><![CDATA[design]]></category>

		<category><![CDATA[game]]></category>

		<category><![CDATA[mmo]]></category>

		<category><![CDATA[MMOG]]></category>

		<category><![CDATA[Scalability]]></category>

		<category><![CDATA[Server]]></category>

		<category><![CDATA[TCO]]></category>

		<category><![CDATA[同质化]]></category>

		<category><![CDATA[工作]]></category>

		<category><![CDATA[开发]]></category>

		<category><![CDATA[技术]]></category>

		<category><![CDATA[技术主义]]></category>

		<category><![CDATA[技术主义者]]></category>

		<category><![CDATA[服务器]]></category>

		<category><![CDATA[服务器组]]></category>

		<category><![CDATA[架构]]></category>

		<category><![CDATA[比较优势]]></category>

		<category><![CDATA[游戏]]></category>

		<category><![CDATA[竞争力]]></category>

		<category><![CDATA[网游]]></category>

		<category><![CDATA[设计]]></category>

		<guid isPermaLink="false">http://canremember.com/?p=16</guid>
		<description><![CDATA[如果想成为第一，就不能老是跟着别人的屁股后面走，尤其是在网游这种新兴高科技行业里面，竞争力和比较优势在很大程度上就是直接来自于技术。我是有理想的人，所以我确实想成为第一，能不能做到那就再说了，至少意愿是有的。技术主义者很傻很天真，但是纵观历史，推动发展的动力很大程度上都是来自于他们，说到底——为发展带来积极因素有什么不好的？技术主义者至少会是个实践者，实践了即使失败也有收获。]]></description>
		<wfw:commentRss>http://canremember.com/?feed=rss2&amp;p=16</wfw:commentRss>
		</item>
		<item>
		<title>Trap of C++</title>
		<link>http://canremember.com/?p=15</link>
		<comments>http://canremember.com/?p=15#comments</comments>
		<pubDate>Mon, 18 Feb 2008 06:55:42 +0000</pubDate>
		<dc:creator>zhiyong</dc:creator>
		
		<category><![CDATA[网游技术]]></category>

		<category><![CDATA[c++]]></category>

		<category><![CDATA[design]]></category>

		<category><![CDATA[implicit]]></category>

		<category><![CDATA[trap]]></category>

		<category><![CDATA[工作]]></category>

		<category><![CDATA[陷阱]]></category>

		<category><![CDATA[隐式转换]]></category>

		<guid isPermaLink="false">http://canremember.com/?p=15</guid>
		<description><![CDATA[<p>Trap of c++</p>
<p>前段时间春节假期，好好休息了一下，并且趁机复习了几本C++的书，包括 More Exceptional C++、Imperfect C++、Morden C++ Design 等等，这次看得比较快，大概3、5个晚上的时间就看完了，尽管外头的鞭炮声不时打扰，不过还是经常会有“想拍大腿的感觉”。正如 Herb Sutter 说的[sutter2001]那样：“第一遍看掌握基本知识，然后再看以学习细节，这样才能成为某一领域的专家”（含义，非原文）。<br />
是否成为了专家自己还不能定论，但是我一直认为——c++越学越复杂。知道c++越多，就会越认为它复杂，所以其实我很怀疑绝大多数我收到的简历上面——“精通c++”这句话的水分 ;)  精通谈何容易啊。拿下面这个例子来说吧，从感情上说，我们几乎可以认为c++就是在这里面设置了一个陷阱。<br />
</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: #ffa500;">// 可以通过编译</span></li>
<li><span class="hl-types">void</span><span style="color: Gray;"> </span><span style="color: Blue;">a</span><span style="color: Olive;">()</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span class="hl-types">int</span><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">a</span><span style="color: Gray;"> = </span><span style="color: Maroon;">100</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span class="hl-types">const</span><span style="color: Gray;">&nbsp;</span><span class="hl-types">short</span><span style="color: Gray;"> &amp;</span><span style="color: Blue;">b</span><span style="color: Gray;"> = </span><span style="color: Blue;">a</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">a</span><span style="color: Gray;"> = </span><span style="color: Maroon;">0</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">std</span><span style="color: Gray;">::</span><span style="color: Blue;">cout</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">a:</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: Blue;">a</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">,b:</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: Blue;">b</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: Blue;">std</span><span style="color: Gray;">::</span><span style="color: Blue;">endl</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span></li></ol></div>
<p>这段程序的输出结果很违反我们的直觉——a:0,b:100，问题的原因在于 const short &#038;b 实际上指向的是一个临时对象，并非是 a 。我用的编译器（msvc8）在缺省警告级别（W3）下对此毫无怨言，它默默的为我生成了一个临时对象并且做好其他的‘伪装’工作，警告级别设置为 W4 的时候它才提示这个转换可能会导致‘丢失数据’。<br />
“编译器怎么能这么干呢！？”我也有过这样的疑问。但是想想也对，既然声明了 b 是个 const refrence，就相当于我告诉了编译器我不打算改动 b 的内容，那么即使编译器给了我一个临时对象而非原始对象 a ，也没问题呀！站在编译器的角度来看，这确实没问题。而且我用的编译器确实会用‘错误’阻止我写下面这样的东西：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: #ffa500;">// 这是无法通过编译的</span></li>
<li><span class="hl-types">void</span><span style="color: Gray;"> </span><span style="color: Blue;">a</span><span style="color: Olive;">()</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span class="hl-types">int</span><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">a</span><span style="color: Gray;"> = </span><span style="color: Maroon;">100</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span class="hl-types">short</span><span style="color: Gray;"> &amp;</span><span style="color: Blue;">b</span><span style="color: Gray;"> = </span><span style="color: Blue;">a</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">a</span><span style="color: Gray;"> = </span><span style="color: Maroon;">0</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">std</span><span style="color: Gray;">::</span><span style="color: Blue;">cout</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">a:</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: Blue;">a</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">,b:</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: Blue;">b</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: Blue;">std</span><span style="color: Gray;">::</span><span style="color: Blue;">endl</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span></li></ol></div>
<p>也就是说编译器会阻止我对非 const refrence 做这种不合理的转型，它不会在这种情况下给我生成个临时对象。即使用下面这样的 static_cast 也不行。</p>
<div class="hl-surround"><div class="hl-main"><span style="color: #ffa500;">// 这是无法通过编译的</span><span style="color: Gray;"><br />&nbsp;&nbsp; &nbsp;</span><span class="hl-types">short</span><span style="color: Gray;"> &amp;</span><span style="color: Blue;">b</span><span style="color: Gray;"> = </span><span style="color: Green;">static_cast</span><span style="color: Gray;">&lt;</span><span class="hl-types">short</span><span style="color: Gray;">&amp;&gt;</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: Blue;">a</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></div></div>
<p>那些讨厌 c++ “奇技淫巧”的 c 程序员，会提供下面这样的方案：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: #ffa500;">// 可以通过编译</span></li>
<li><span class="hl-types">void</span><span style="color: Gray;"> </span><span style="color: Blue;">a</span><span style="color: Olive;">()</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span class="hl-types">int</span><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">a</span><span style="color: Gray;"> = </span><span style="color: Maroon;">100</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span class="hl-types">short</span><span style="color: Gray;"> &amp;</span><span style="color: Blue;">b</span><span style="color: Gray;"> = *</span><span style="color: Olive;">((</span><span style="color: Gray;">&nbsp;</span><span class="hl-types">short</span><span style="color: Gray;">* </span><span style="color: Olive;">)(</span><span style="color: Gray;"> &amp;</span><span style="color: Blue;">a</span><span style="color: Gray;"> </span><span style="color: Olive;">))</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">a</span><span style="color: Gray;"> = </span><span style="color: Maroon;">11</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">std</span><span style="color: Gray;">::</span><span style="color: Blue;">cout</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">a:</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: Blue;">a</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">,b:</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: Blue;">b</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: Blue;">std</span><span style="color: Gray;">::</span><span style="color: Blue;">endl</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span></li></ol></div>
<p>这次编译器不会抱怨了，而且它输出了 c 程序员想要的结果—— a:11,b:11 ，结果看上去非常好！但是代码只要稍微改动一下，事情就变得离谱了：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: #ffa500;">// 可以通过编译，但是结果有问题</span></li>
<li><span class="hl-types">void</span><span style="color: Gray;"> </span><span style="color: Blue;">a</span><span style="color: Olive;">()</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span class="hl-types">int</span><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">a</span><span style="color: Gray;"> = </span><span style="color: Maroon;">100</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span class="hl-types">short</span><span style="color: Gray;"> &amp;</span><span style="color: Blue;">b</span><span style="color: Gray;"> = *</span><span style="color: Olive;">((</span><span style="color: Gray;">&nbsp;</span><span class="hl-types">short</span><span style="color: Gray;">* </span><span style="color: Olive;">)(</span><span style="color: Gray;"> &amp;</span><span style="color: Blue;">a</span><span style="color: Gray;"> </span><span style="color: Olive;">))</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">a</span><span style="color: Gray;"> = </span><span style="color: Maroon;">32768</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">std</span><span style="color: Gray;">::</span><span style="color: Blue;">cout</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">a:</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: Blue;">a</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">,b:</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: Blue;">b</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: Blue;">std</span><span style="color: Gray;">::</span><span style="color: Blue;">endl</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span></li></ol></div>
<p>这段代码会输出——a:32768,b:-32768 ，这差得很远，对吧？再改，a = 65537 的时候会输出——a:65537,b:1 。至此，我似乎可以得出结论：这种 c 转型方案很坏、很危险。可能这种方法只适合那些“知道他们自己在做些什么的 hacker ”，c 程序员。但是问题还没有结束，即使用纯 c++ 方法，问题也还存在。</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: #ffa500;">// 可以通过编译，使用纯 c++ 的方法</span></li>
<li><span class="hl-types">void</span><span style="color: Gray;"> </span><span style="color: Blue;">a</span><span style="color: Olive;">()</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span class="hl-types">int</span><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">a</span><span style="color: Gray;"> = </span><span style="color: Maroon;">100</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span class="hl-types">const</span><span style="color: Gray;">&nbsp;</span><span class="hl-types">short</span><span style="color: Gray;"> &amp;</span><span style="color: Blue;">b</span><span style="color: Gray;"> = </span><span style="color: Blue;">a</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: #ffa500;">// c++ 提供了 const_cast</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span class="hl-types">short</span><span style="color: Gray;"> &amp;</span><span style="color: Blue;">c</span><span style="color: Gray;"> = </span><span style="color: Green;">const_cast</span><span style="color: Gray;">&lt;</span><span class="hl-types">short</span><span style="color: Gray;">&amp;&gt;</span><span style="color: Olive;">(</span><span style="color: Blue;">b</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">c</span><span style="color: Gray;"> = </span><span style="color: Maroon;">1</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">std</span><span style="color: Gray;">::</span><span style="color: Blue;">cout</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">a:</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: Blue;">a</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">,b:</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: Blue;">b</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">,c:</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> &lt;&lt; </span><span style="color: Blue;">c</span><span style="color: Gray;"> &lt;&lt;</span><span style="color: Blue;">std</span><span style="color: Gray;">::</span><span style="color: Blue;">endl</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span></li></ol></div>
<p>在这个例子里面，b 是 a 的 refrence，c 和 b 是同一个东西，这段代码的输出结果很容易就被期望为：a:1,b:1,c:1，当然这不可能，实际上是：a:100,b:1,c:1 。根据这个输出结果，我们还能得出关于这种临时对象的另外一个结论——这种临时对象，也可以通过 refrence 而改变它的值，这个临时对象一定处于可写的内存区域。</p>
<p>就这样一个隐式（implicit）转换问题，就可以带来如此多的麻烦，我们很难做出“c++ 不复杂”这样的判断。c++ 里面违反直觉的例子数不胜数，例如 new int[0] 合法，但是 int array[0] 就非法，我们很容易就会认为编译器是在找茬打架。不过，强大的东西怎么可能不复杂？否则它早就消灭一切其他的编程语言了。</p>
<hr /><h2>Related posts,相关文章</h2><ul><li><a href="http://canremember.com/?p=15" rel="bookmark" title="Permanent Link: Trap of C++">Trap of C++</a></li></ul><hr /><h2>Related posts,相关文章</h2><ul>
<!-- Generated by Simple Tags 1.3.8 - http://wordpress.org/extend/plugins/simple-tags -->
	<h4>Related posts</h4>
	<ul class='st-related-posts'>
	<li><a href="http://canremember.com/?p=8" title="无缝世界网游服务器架构的设计思路 (2008.02月.12)">无缝世界网游服务器架构的设计思路</a> (4)</li>
	<li><a href="http://canremember.com/?p=16" title="技术主义者的网游观点 (2008.03月.23)">技术主义者的网游观点</a> (11)</li>
	<li><a href="http://canremember.com/?page_id=2" title="关于我 (2008.02月.3)">关于我</a> (0)</li>
	<li><a href="http://canremember.com/?p=5" title="任务“耦合” (2008.02月.5)">任务“耦合”</a> (1)</li>
</ul>

</ul><hr /><small>Copyright &copy 2008 Wang Zhiyong, Some Rights Reserved ;)<br /> all content of this site is under Creative Commons License <br />
 此网站所有内容采用 知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。(digitalfingerprint: e71076c267f520b120f4bb81270fe189)</small>]]></description>
		<wfw:commentRss>http://canremember.com/?feed=rss2&amp;p=15</wfw:commentRss>
		</item>
		<item>
		<title>无缝世界网游服务器架构的设计思路（续）</title>
		<link>http://canremember.com/?p=10</link>
		<comments>http://canremember.com/?p=10#comments</comments>
		<pubDate>Fri, 15 Feb 2008 08:54:44 +0000</pubDate>
		<dc:creator>zhiyong</dc:creator>
		
		<category><![CDATA[网游技术]]></category>

		<category><![CDATA[AoI]]></category>

		<category><![CDATA[Architecture]]></category>

		<category><![CDATA[Area of Interest]]></category>

		<category><![CDATA[cell]]></category>

		<category><![CDATA[cells-based]]></category>

		<category><![CDATA[Coupling]]></category>

		<category><![CDATA[MMORPG]]></category>

		<category><![CDATA[seamless world]]></category>

		<category><![CDATA[Server]]></category>

		<category><![CDATA[services-based]]></category>

		<category><![CDATA[stateless service]]></category>

		<category><![CDATA[无缝世界]]></category>

		<category><![CDATA[服务器]]></category>

		<category><![CDATA[服务器端]]></category>

		<category><![CDATA[架构]]></category>

		<category><![CDATA[网游]]></category>

		<category><![CDATA[耦合]]></category>

		<guid isPermaLink="false">http://canremember.com/?p=10</guid>
		<description><![CDATA[<p class="MsoNormal"><span style="font-family: 宋体">上次写了《无缝世界网游服务器架构的设计思路》，这次是续篇，主要内容是两种架构的优缺点分析。</span></p>
<p class="MsoNormal"><span style="font-family: 宋体">从一组服务器的角度来看，一般来说，我们的服务器组（</span><span lang="EN-US">Cluster</span><span style="font-family: 宋体">）内都会有登陆验证服务器（</span><span lang="EN-US">Login Server</span><span style="font-family: 宋体">）、持久性数据服务器（</span><span lang="EN-US">DB</span><span style="font-family: 宋体">及</span><span lang="EN-US">DB Proxy</span><span style="font-family: 宋体">）、连接代理服务器（</span><span lang="EN-US">Gate Server</span><span style="font-family: 宋体">、</span><span lang="EN-US">FEP Server</span><span style="font-family: 宋体">、</span><span lang="EN-US">Client Proxy</span><span style="font-family: 宋体">等）以及</span><span lang="EN-US">Auto Patch Server</span><span style="font-family: 宋体">、还有用于集中管理及控制组的服务器等等，由于这些服务器基本上什么样的架构设计都会用到，所以——现在不考虑以上这些服务器，只考虑具体处理游戏逻辑、游戏规则的各个服务器。以此为前提来分析一下</span><span lang="EN-US"> Services-based Architecture </span><span style="font-family: 宋体">和</span><span lang="EN-US"> Cells-based Architecture </span><span style="font-family: 宋体">的优缺点。</span></p>
<p></p>
<h2><span style="font-family: 黑体; color: #993366">对</span><span style="color: #993366" lang="EN-US">Services-based Architecture </span><span style="font-family: 黑体; color: #993366">的分析</span><span style="color: #993366" lang="EN-US"><o:p></o:p></span></h2>
<p class="MsoNormal">&nbsp;</p>
<p class="MsoNormal"><span style="font-family: 宋体">基于服务的架构，顾名思义这种架构的实现（程序）会是和服务的具体内容（策划）相关的，这是因为——各种【服务】内容的确定是建立于项目的【需求分析】基础上的，【需求分析】的前提是基本确定了【策划设计】，至少是项目的概要设计。</span></p>
<p class="MsoNormal"><span style="font-family: 宋体">我想多数做过游戏项目的人都应该对需求变更有很深的感触，每个人都说“开始想做的那个和最后实际做出来的那个不一样”。特别是在项目的早期阶段，团队的不同成员对项目做完之后的样子有相当不同的看法（很可能大家互相都不知道对方怎么看的），这很容易理解，谁也不可能从几页纸几张图就确切地知道这个游戏做完了什么样子，即使不考虑需求变更。涉及到项目开发方法方面的东西这里就不多说了，总之我的看法就是——<strong>尽管我们不大可能设计出一个架构能够适应任何的游戏设计，但是不同开发任务间的耦合度显然还是越低越好，基于服务的架构适应需求变更的能力较差</strong>。</span></p>
<h3><strong><span style="font-family: 宋体">关于服务耦合</span></strong></h3>
<p class="MsoNormal"><span style="font-family: 宋体">不管如何划分</span><span lang="EN-US">service</span><span style="font-family: 宋体">，不同</span><span lang="EN-US"> service</span><span style="font-family: 宋体">之间都一定存在不同程度的耦合（</span><span lang="EN-US">coupling</span><span style="font-family: 宋体">）关系，不同的</span><span lang="EN-US"> service </span><span style="font-family: 宋体">之间会有相互依赖关系。而你们的策划设计可能会让这种关系复杂到程序在运行时的状态很难以琢磨的程度。</span></p>
<blockquote><p><strong>假设：</strong><br />
<em> 服务器组内的战斗处理和物品处理分别由两个不同的服务（器）提供</em><br />
<strong> 游戏规则：</strong><br />
<em> 人物被攻击后自己携带的物品可能掉落到地上<br />
某些物品掉落后会爆炸<br />
物品在地上爆炸可能伤及周围（半径10米内）人物<br />
人物之间的‘仇恨度’影响战斗数值计算<br />
被攻击时掉落的物品爆炸后伤及的人物，会增加对‘被攻击人’的‘仇恨度’</em></p></blockquote>
<p class="MsoNormal"><span style="font-family: 宋体">我想我还能想出很多很多“看上去不算过分”的规则来让这个事情变得复杂无比，很可能你们的策划也在无意中，已经拥有我这种能力</span> <span style="font-family: Wingdings" lang="EN-US"><span>:)</span></span><span lang="EN-US"> </span><span style="font-family: 宋体">而且他们在写文档时候的表达还多半不如我上面写的清楚，另外，他们还会把这些规则分到很多不同的文档里面去写。好吧，你肯定会想“把这两个服务合二为一好了”，实际上不管你想把哪两个（或多个）服务合并为一个服务的时候，都应该先考虑一下当时是为什么把他们独立为不同服务的？</span></p>
<p class="MsoNormal"><span style="font-family: 宋体">实际上很多这样“看上去不算过分”的规则都会导致</span><span lang="EN-US">service</span><span style="font-family: 宋体">间的频繁交互，所以<strong>每个</strong></span><strong><span lang="EN-US">service</span></strong><strong><span style="font-family: 宋体">最好都是</span><span lang="EN-US">stateless service</span></strong><strong><span style="font-family: 宋体">，这样的话情况会好很多，但是对于游戏来说这很难做到</span></strong><span style="font-family: 宋体">。</span></p>
<h3><strong><span style="font-family: 宋体">请求处理的时序问题</span></strong></h3>
<p class="MsoNormal"><span style="font-family: 宋体">服务耦合的问题在不考虑开发复杂度比较高的情况下，还是可以被搞定的，只要脑袋够清醒，愿意花够多的时间，那么还有更难以搞定的么？我看确实还有，如果你对将要面对的问题，了解得足够多的话</span><span style="font-family: Wingdings" lang="EN-US"><span>:)</span></span></p>
<p class="MsoNormal">&nbsp;</p>
<p class="MsoNormal">&nbsp;</p>
<p class="MsoNormal"> <a href="http://canremember.com/wp-content/uploads/2008/02/problem_of_services-based_arch.gif" title="some problem about services-based"><img src="http://canremember.com/wp-content/uploads/2008/02/problem_of_services-based_arch.gif" alt="problem_of_services-based_arch.gif" /> </a></p>
<p class="MsoNormal"><span style="font-family: 宋体">上面两个序列图描述的是某个玩家做了连续做了两次同样的操作但是很可能得到了不同的结果，当然这些请求都是异步地被处理。问题的关键在于——尽管两次玩家执行的命令一样、顺序一样，甚至时间间隔都一样，但是结果却很不同——因为图（</span><span lang="EN-US">1</span><span style="font-family: 宋体">）里面</span><span lang="EN-US">C2CS::Request_to_attack</span><span style="font-family: 宋体">请求被处理的时候，</span><span lang="EN-US">C2IS::Request_equip_item </span><span style="font-family: 宋体">这个请求还没有被处理完，但是图（</span><span lang="EN-US">2</span><span style="font-family: 宋体">）显示的情况就不一样了。因为</span><span lang="EN-US">C2IS::Request_equip_item</span><span style="font-family: 宋体">这个操作很可能会改变游戏人物的属性，这个属性又很可能影响</span><span lang="EN-US">attack</span><span style="font-family: 宋体">的结果。这两幅图实际上省略了</span><span lang="EN-US"> Combat Server </span><span style="font-family: 宋体">与</span><span lang="EN-US"> Item Server </span><span style="font-family: 宋体">之间的交互过程。但是已经足以说明问题了，<strong>每个</strong></span><strong><span lang="EN-US">Service</span></strong><strong><span style="font-family: 宋体">处理每个</span><span lang="EN-US">Request</span></strong><strong><span style="font-family: 宋体">时具体会消耗的时间，是无法在设计时确定的</span><span lang="EN-US">!<o:p></o:p></span></strong></p>
<p class="MsoNormal"><span style="font-family: 宋体">谁喜欢这类结果上的<strong>不确定性</strong>？举个例子：玩家很可能已经装备上了“只能使用</span><span lang="EN-US">1</span><span style="font-family: 宋体">次的魔兽必杀刀”然后攻击了一下魔兽，但是它却没死！这会导致什么样的结果？请自行想象。另外，这种不确定性还会表现为“在项目开发期和运营期的行为差异”，或者“出现某些偶然的奇怪现象”。</span></p>
<p class="MsoNormal"><span style="font-family: 宋体">那还有解决方案么？有的，其实只要序列化玩家请求的处理，使处理有序进行就可以了。但是又一次的，这会带来新的复杂度——在某个范围（整个服务器组？一个行会？一个队伍？）内，以每个玩家为单位，序列化他（们）的（可能是所有）操作，但是也显而易见，这在某种程度上降低了请求处理的并发性，尽管它对并发性的影响可能只局限于不大（最少是一个玩家）的范围。</span></p>
<p></p>
<p class="MsoNormal">&nbsp;</p>
<p> <a href="http://canremember.com/wp-content/uploads/2008/02/problem_of_services-based_arch.gif" title="some problem about services-based">  </a></p>
<h3></h3>
<h2><span style="font-family: 黑体; color: #993366">对</span><span style="color: #993366" lang="EN-US">Cells-based Architecture </span><span style="font-family: 黑体; color: #993366">的分析</span><span style="color: #993366" lang="EN-US"><o:p></o:p></span></h2>
<p class="MsoNormal">&nbsp;</p>
<p class="MsoNormal"><span style="font-family: 宋体">基于</span><span lang="EN-US">Cell</span><span style="font-family: 宋体">的架构有个明显的优势就是</span><span lang="EN-US">Cell</span><span style="font-family: 宋体">如何划分和你的策划没有关系</span><span style="font-family: Wingdings" lang="EN-US"><span>J</span></span><span style="font-family: 宋体">这是真的。而且</span><span lang="EN-US">Cell</span><span style="font-family: 宋体">间如何交互可以被放到系统的底层，具体有多底层、多隐蔽（实际上可以隐蔽到对开发上层游戏逻辑的程序员都不可见的程度）要看你的实现如何了。<strong>如果做到了某个系统的程序设计与游戏设计完全无关的话，显然，这个系统受到游戏设计变更（需求变更）的影响就会很小很小，甚至会到完全不受影响的程度</strong>，当然这是理想情况。</span></p>
<h3><strong><span style="font-family: 宋体">关于跨边界对象交互</span></strong></h3>
<p class="MsoNormal"><span style="font-family: 宋体">在基于</span><span lang="EN-US">Cell</span><span style="font-family: 宋体">的服务器架构里面，实现无缝世界（</span><span lang="EN-US">Seamless World</span><span style="font-family: 宋体">）的主要难点在于实现跨边界对象的交互时会出现的一些问题，因为这些对象在不同的</span><span lang="EN-US">Cell</span><span style="font-family: 宋体">进程里面，这些</span><span lang="EN-US">Cell</span><span style="font-family: 宋体">一般来说是在不同的物理服务器上运行。</span></p>
<p class="MsoNormal"><span style="font-family: 宋体">无缝世界的特点自然就是无缝，并且因为无缝给玩家带来更好的游戏体验，所以显然我们希望“跨边界对象交互”问题不把事情搞砸，那么这种交互的表现就必须满足稳定、高效的前提。一般来说，高于</span><span lang="EN-US">300ms</span><span style="font-family: 宋体">的延迟对玩家操作来说就属于“明显可见”的程度了，不能让玩家骑着</span><span lang="EN-US">500</span><span style="font-family: 宋体">块</span><span lang="EN-US">RMB</span><span style="font-family: 宋体">买来的虚拟马在一片大草原上面畅快的奔跑的时候，在某个地方突然就被“看不见的墙”给“挡”了一下，因为这“墙”根本看不见，所以会很影响“上帝”的游戏心情。</span></p>
<p class="MsoNormal"><span style="font-family: 宋体">关于组成整个虚拟世界的</span><span lang="EN-US">Cell</span><span style="font-family: 宋体">之间的关系，下面来分析两种情况：</span></p>
<p><a href="http://canremember.com/wp-content/uploads/2008/02/problem_of_services-based_arch.gif" title="some problem about services-based"> </a></p>
<p class="MsoNormal" style="margin-left: 21.75pt; text-indent: -21.75pt"><!--[if !supportLists]--><strong><span lang="EN-US"><span>一，<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal">             </span></span></span></strong><!--[endif]--><strong><span lang="EN-US">Cell </span></strong><strong><span style="font-family: 宋体">承载的场景不重叠</span></strong></p>
<p class="MsoNormal" style="margin-left: 21.75pt; text-indent: -21.75pt"> <img src="http://canremember.com/wp-content/uploads/2008/02/cell_1.gif" alt="cells-based_1" /></p>
<p class="MsoNormal" style="margin-left: 21.75pt; text-indent: -21.75pt">&nbsp;</p>
<p class="MsoNormal"><span style="font-family: 宋体">如图（</span><span lang="EN-US">1</span><span style="font-family: 宋体">），一个连续的虚拟世界场景被分成左右两块，分别在不同的</span><span lang="EN-US">Cell Server</span><span style="font-family: 宋体">上面运行。</span><span lang="EN-US">A</span><span style="font-family: 宋体">、</span><span lang="EN-US">B</span><span style="font-family: 宋体">、</span><span lang="EN-US">C</span><span style="font-family: 宋体">分别是</span><span lang="EN-US">3</span><span style="font-family: 宋体">个不同的游戏角色。在这种情况下</span><span lang="EN-US">B</span><span style="font-family: 宋体">与</span><span lang="EN-US">C</span><span style="font-family: 宋体">的交互并不存在任何障碍，因为</span><span lang="EN-US">B</span><span style="font-family: 宋体">和</span><span lang="EN-US">C</span><span style="font-family: 宋体">只不过是同一个物理服务器上同一个进程内的两块不同的内存数据而已。但是</span><span lang="EN-US">A</span><span style="font-family: 宋体">与</span><span lang="EN-US">B/C</span><span style="font-family: 宋体">的交互就不那么直接了，尽管他们所在的场景看上去是“连续的、一体的”但是事情不会像表面上那么简单。</span><span lang="EN-US">A</span><span style="font-family: 宋体">与</span><span lang="EN-US">B</span><span style="font-family: 宋体">发生交互时候会发生什么事情？例如</span><span lang="EN-US">A</span><span style="font-family: 宋体">攻击了</span><span lang="EN-US">B</span><span style="font-family: 宋体">、</span><span lang="EN-US">A</span><span style="font-family: 宋体">与</span><span lang="EN-US">B</span><span style="font-family: 宋体">交易物品等等，因为在这种结构下做数据同步会带来很多问题，例如对象状态不确定性、开发复杂度等等、相对来说两个</span><span lang="EN-US">Cell Server</span><span style="font-family: 宋体">之间做网络通讯而带来的延迟可能反而是最小的问题，这些问题不需要很复杂的分析就可以得出结论，在此不再多说了。</span></p>
<p class="MsoNormal" style="margin-left: 21.75pt; text-indent: -21.75pt"><!--[if !supportLists]--><strong><span lang="EN-US"><span>二，<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal"></span></span></span></strong><strong><span lang="EN-US">Cell </span></strong><strong><span style="font-family: 宋体">承载的场景（部分地）重叠</span></strong></p>
<p class="MsoNormal" style="margin-left: 21.75pt; text-indent: -21.75pt"> <img src="http://canremember.com/wp-content/uploads/2008/02/cell_2.gif" alt="cells-based_2" /></p>
<p class="MsoNormal" style="margin-left: 21.75pt; text-indent: -21.75pt">&nbsp;</p>
<p class="MsoNormal"><span style="font-family: 宋体">如图（2</span><span style="font-family: 宋体">），一个连续的虚拟世界场景被分成左右两块，分别在不用的</span><span lang="EN-US">Cell Server</span><span style="font-family: 宋体">上面运行。</span><span lang="EN-US">A</span><span style="font-family: 宋体">、</span><span lang="EN-US">B</span><span style="font-family: 宋体">、</span><span lang="EN-US">C</span><span style="font-family: 宋体">、</span><span lang="EN-US">D</span><span style="font-family: 宋体">分别是</span><span lang="EN-US">4</span><span style="font-family: 宋体">个不同的游戏角色。这个情况下，中间的区域为</span><span lang="EN-US">2</span><span style="font-family: 宋体">个</span><span lang="EN-US">Cell</span><span style="font-family: 宋体">所共同维护，中间区域的对象同属于</span><span lang="EN-US">2</span><span style="font-family: 宋体">个</span><span lang="EN-US">Cell</span><span style="font-family: 宋体">所‘拥有’。这有什么好处？现在，任意两个对象之间，<u>除了</u></span><u><span lang="EN-US">A</span></u><u><span style="font-family: 宋体">与</span><span lang="EN-US">C</span></u><u><span style="font-family: 宋体">之间的交互</span></u><span style="font-family: 宋体">，都变得更‘直接’了。变得直接肯定是一件好事儿，那么</span><span lang="EN-US">A</span><span style="font-family: 宋体">与</span><span lang="EN-US">C</span><span style="font-family: 宋体">之间呢？他们之间其实也没有任何问题</span><span style="font-family: Wingdings" lang="EN-US"><span>J</span></span><span lang="EN-US"> </span><span style="font-family: 宋体">因为双方都已经超出了对方的</span><em><span lang="EN-US">Area of Interest（AoI）</span></em><span style="font-family: 宋体">区域，游戏规则可以限制他们不能直接交互。</span></p>
<p class="MsoNormal"><span style="font-family: 宋体">上面提到的第二种方案算不上什么魔法，但是肯定是比第一种方案更有效。接下来怎么办？假设</span><span lang="EN-US">B</span><span style="font-family: 宋体">是个玩家，他站在中间这块区域上面时，并不会产生“我到底是在哪里”这样的疑问</span><span style="font-family: Wingdings" lang="EN-US"><span>J</span></span><span lang="EN-US"> </span><span style="font-family: 宋体">问题的关键在于对于</span><span lang="EN-US">Cell Server</span><span style="font-family: 宋体">来说，怎么样<strong>同步那些处于重叠区域对象的状态</strong>。游戏世界内的对象可能同时处于</span><span lang="EN-US">1</span><span style="font-family: 宋体">个、</span><span lang="EN-US">2</span><span style="font-family: 宋体">个、</span><span lang="EN-US">3</span><span style="font-family: 宋体">个或者</span><span lang="EN-US">4</span><span style="font-family: 宋体">个不同的</span><span lang="EN-US">Cell Server</span><span style="font-family: 宋体">。如果你的</span><span lang="EN-US">Cell</span><span style="font-family: 宋体">分隔方法不限于水平线和垂直线、或者有人故意捣乱的话，还可能会更多。需要被同步的对象也不只是玩家本身，还包括怪物、</span><span lang="EN-US">NPC</span><span style="font-family: 宋体">、一颗会走的树、某玩家在地上吐的痰等等。</span></p>
<p class="MsoNormal"><span style="font-family: 宋体">由于我们的基于无缝世界的游戏规则不大会直接去限制游戏世界某处玩家的行为，也就是说玩家如果能相互交易物品的话，他们肯定希望在任何地方都能交易，“为什么其他地方都行，但是在某个墙角做交易就会导致物品丢失？”所以比较可靠的方法是建立一套的用于同步的底层机制，来同步这些跨边界对象。</span></p>
<p class="MsoNormal"><span style="font-family: 宋体">怎么实现？这个话题很大，恐怕再写几篇</span><span lang="EN-US">Blog</span><span style="font-family: 宋体">我也讲不完，但是有一些东西可以作为参考，例如：</span><span lang="EN-US">DCOM</span><span style="font-family: 宋体">和</span><span lang="EN-US">CORBA</span><span style="font-family: 宋体">规范，</span><span lang="EN-US">Java</span><span style="font-family: 宋体">的</span><span lang="EN-US">RMI</span><span style="font-family: 宋体">，基于</span><span lang="EN-US">Python</span><span style="font-family: 宋体">的</span><span lang="EN-US"> PYRO</span><span style="font-family: 宋体">，</span><span lang="EN-US">TAO(The ACE ORB)</span><span style="font-family: 宋体">等等。好在分布式处理的问题不止是网络游戏会涉及到，可以借鉴的东西还是很多的。</span></p>
<h2><span style="font-family: 黑体; color: #993366">总结</span><span style="color: #993366" lang="EN-US"><o:p></o:p></span></h2>
<p class="MsoNormal"><span style="font-family: 宋体">很显然，这篇文章在两种架构的评价上面存在某些倾向性，但是倾向性本身只是副产品。另外一个副产品就是关于一些技术分析方法。</span></p>
<p class="MsoNormal"><span style="font-family: 宋体">在考虑采用何种技术的时候，我们往往很容易地就会忽略对程序之外那些事情的影响。上面我提到的关于</span><span lang="EN-US">Services-based</span><span style="font-family: 宋体">架构实现的时候，提到划分</span><span lang="EN-US">service</span><span style="font-family: 宋体">及数据设计对程序设计能力的挑战、对策划设计的制约，对适应需求变更能力的影响，都不会只是空谈。这些问题也不是只在实现这种架构的时候才出现。</span></p>
<p class="MsoNormal" style="margin-left: 21.75pt; text-indent: -21.75pt"><span style="font-family: 宋体">不要高估自己的智商，</span><span lang="EN-US">Keep It Simple and Stupid </span><span style="font-family: Wingdings" lang="EN-US"><span>:) </span></span><span lang="EN-US"></span><span style="font-family: 宋体">应该可以让我们离成功更近一点儿。</span></p>
<hr /><h2>comments,文章评论</h2><ul><li><a href="http://canremember.com/?p=10#comment-5">2008.02月.16</a>, 青风无影 comment: 受益匪浅，我也是比较偏向Cells-based Architecture，Services-based Architecture比较突出的缺点就是：对开发人员要求比较高，适应需求变更的能力较差，服务如果分得太细那就开发复杂度高，为了保证数据的有效性而付出的代价将会抵消本身的优点～</li><li><a href="http://canremember.com/?p=10#comment-26">2009.03月.9</a>, James comment: 分析非常好，单纯谈技术不是万能，需要根据不同的问题具体分析，采用合适的解决方案</li><li><a href="http://canremember.com/?p=10#comment-27">2009.03月.13</a>, <a href='http://www.benegg.com' rel='external nofollow'>benegg</a> comment: 边界重叠是一种较好的思想. 基于边界重叠思想, 可以发展出动态边界, 动态改变Cell所控制的范围, 将玩家多的区域用更多的Cell服务器来处理, 从而达到性能上的负载均衡.

Service-based 较适合网站, 如果用于网游, 和分区没有什么两样.</li><li><a href="http://canremember.com/?p=10#comment-32">2010.03月.1</a>, inkcomic comment: 受教了。</li></ul><hr /><h2>Related posts,相关文章</h2><ul>
<!-- Generated by Simple Tags 1.3.8 - http://wordpress.org/extend/plugins/simple-tags -->
	<h4>Related posts</h4>
	<ul class='st-related-posts'>
	<li><a href="http://canremember.com/?p=8" title="无缝世界网游服务器架构的设计思路 (2008.02月.12)">无缝世界网游服务器架构的设计思路</a> (4)</li>
	<li><a href="http://canremember.com/?p=4" title="服务器组架构设计需要考虑的一些关键因素 (2008.02月.5)">服务器组架构设计需要考虑的一些关键因素</a> (6)</li>
	<li><a href="http://canremember.com/?p=16" title="技术主义者的网游观点 (2008.03月.23)">技术主义者的网游观点</a> (11)</li>
	<li><a href="http://canremember.com/?p=22" title="随便聊聊网游和数据挖掘 (2009.04月.4)">随便聊聊网游和数据挖掘</a> (5)</li>
	<li><a href="http://canremember.com/?page_id=2" title="关于我 (2008.02月.3)">关于我</a> (0)</li>
</ul>

</ul><hr /><small>Copyright &copy 2008 Wang Zhiyong, Some Rights Reserved ;)<br /> all content of this site is under Creative Commons License <br />
 此网站所有内容采用 知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。(digitalfingerprint: e71076c267f520b120f4bb81270fe189)</small>]]></description>
		<wfw:commentRss>http://canremember.com/?feed=rss2&amp;p=10</wfw:commentRss>
		</item>
		<item>
		<title>无缝世界网游服务器架构的设计思路</title>
		<link>http://canremember.com/?p=8</link>
		<comments>http://canremember.com/?p=8#comments</comments>
		<pubDate>Tue, 12 Feb 2008 13:53:18 +0000</pubDate>
		<dc:creator>zhiyong</dc:creator>
		
		<category><![CDATA[网游技术]]></category>

		<category><![CDATA[Architecture]]></category>

		<category><![CDATA[Archtecture]]></category>

		<category><![CDATA[cell]]></category>

		<category><![CDATA[cells-based]]></category>

		<category><![CDATA[Cluster]]></category>

		<category><![CDATA[design]]></category>

		<category><![CDATA[game]]></category>

		<category><![CDATA[implicit]]></category>

		<category><![CDATA[mmo]]></category>

		<category><![CDATA[seamless world]]></category>

		<category><![CDATA[Server]]></category>

		<category><![CDATA[services-based]]></category>

		<category><![CDATA[Simplicity]]></category>

		<category><![CDATA[任务]]></category>

		<category><![CDATA[工作]]></category>

		<category><![CDATA[无缝世界]]></category>

		<category><![CDATA[服务器]]></category>

		<category><![CDATA[服务器组]]></category>

		<category><![CDATA[架构]]></category>

		<category><![CDATA[架构设计]]></category>

		<category><![CDATA[网游]]></category>

		<category><![CDATA[设计]]></category>

		<guid isPermaLink="false">http://canremember.com/?p=8</guid>
		<description><![CDATA[<p>过去一年中，花了很多时间在考虑服务器架构设计方面的问题。看了大量文章、也研究了不少开源项目，眼界倒是开阔了不少，不过回过头来看，对网游架构设计方面的帮助却是不多。老外还是玩儿console  game的多，MMO Games方面涉及的还是不如国内广泛。看看 <a href="http://www.charlesriver.com/Books/BookDetail.aspx?productID=62407" title="http://www.charlesriver.com/Books/BookDetail.aspx?productID=62407" target="_blank">Massively Multiplayer Games Development</a> 1 &amp;  2  这两本书吧，质量说实话很一般，帮助自然也很有限。当然这也是好事，对国内的研发公司/团队来说，在网游服务器技术方面当然就存在超越老外的可能性，而且在这方面技术超越的机会更大，当然前提是要有积累、要舍得投入，研发人员更要耐得住寂寞、经得起诱惑，在平均每天收到超过3个猎头电话的时候——依然不动心。</p>
<p>上面有点儿扯远了，下面聊聊无缝世界架构（Seamless world server architecture）设计方面的一点儿看法。</p>
<p>先说架构设计的目标——我的看法，服务器组架构设计的目标就是确定各服务器拓补关系和主要的业务逻辑处理方法。主要要解决的问题就是在满足游戏内容设计需要的前提下，如何提高带负载能力的问题。<br />
<br />
最简单的架构就是基本的C/S架构，一台Server直接构成一个Cluster，所有Client直接连接这个Server，这个Server完成所有逻辑和数据处理。这架构其实很好，最大的好处就是它架构上的  Simplicity ，Cluster内部的跨进程交互完全被排除，复杂度立刻就降下来了，而且——完全可以实现一个无缝（Seamless  world）的游戏世界。但是即使我不说，大家也知道这种单Server架构会有什么问题。不过我们不妨以另外一个角度来看这个Server——一个黑盒子。从系统外部的角度来看，什么样的系统都可以看成一个整体、一个黑盒，而不管系统内部的拓补关系和实现复杂度方面的问题。在不考虑这个系统的实现的前提下，理论上Cluster的处理能力就是由硬件的数量和能力决定的，也就是说一个Server  Cluster内包含越多的服务器、服务器越‘快’，那么这个Cluster的处理能力越好、带负载能力越好。那么我们要面对的带负载能力的问题，就是如何高效的利用这些Server的问题，基本上也可以理解为<strong>如何提高玩家请求的并发处理能力</strong>的问题。</p>
<p>CPU厂商在很久以前就在考虑这方面的问题了，CPU其实也可以看成个黑盒。看看他们用过的技术——<a href="https://canremember.com/redirect/go.php?q=http%3A%2F%2Fen.wikipedia.org%2Fwiki%2FPipeline_%28computer%29&#038;hl=c1"  target = "_blank" title="http://en.wikipedia.org/wiki/Pipeline_(computer)">流水线（pipeline）</a>技术、<a href="https://canremember.com/redirect/go.php?q=http%3A%2F%2Fen.wikipedia.org%2Fwiki%2FMulti-core_%28computing%29&#038;hl=c1" target = "_blank" title="http://en.wikipedia.org/wiki/Multi-core_(computing)">多CPU/多核（multicore）</a>技术，以及这些技术的衍生技术。我想了很久让 Server  Cluster 内部处理并行的方法、并且有了比较清晰的思路之后，才发现其实早就可以参照CPU厂商的方法。流水线的方法就是把一个指令处理拆分成很多个步骤，这样指令的处理被分解之后就可以部分重叠（相当于变成并发的了）执行。我们的Server  Cluster一样可以用这种方法来拆分，我想了个名字——</p>
<p><strong>Services-based  Architecture</strong>——基于服务的架构。在这种架构内部，我们根据处理数据、逻辑的相关性来划分组内各个服务器的工作任务。例如：位置服务提供物体可见性信息、物品服务处理所有物品相关的逻辑、社会关系服务提供行会家族等等方面的逻辑、战斗服务器只处理战斗相关的逻辑，等等。这样划分的话、逻辑处理的并发就有了可能性。举例来说：A砍B一刀这件事情与C从奸商手里买到一件武器这个事情是完全不相干的，而且这2个请求本来就在不同的服务器上被处理，他们是被不同的Service  Server并发处理的。这就是 Services-based Architecture 的并发方法。</p>
<p>基本上，把游戏逻辑的处理拆分成一个个的service，就和设计cpu的时候把机器指令的具体处理拆分，然后设计出一个个流水线单元是一个道理。</p>
<p><strong>Cells-based  Architecture</strong>——基于cell的架构。每个cell都在不同的物理server上面运行着完全一样的应用程序服务器，但是他们负责承载不同的游戏场景区域的游戏逻辑。和  services-based arch.  明显不同的就是，每个cell都是个‘在逻辑上完整的’服务器。它得处理物品操作、人物移动、战斗计算等等几乎所有的游戏逻辑。尽管这么做会带来一些（可能是很复杂）的问题，但是它完全是可行的。举例来说：在吴国A砍B一刀显然地和千里之外在越国的C砍D一刀不搭界，他们完全可以被不同的Cell并发地处理。</p>
<p>基本上，这就相当于一个主板上面插多个CPU或者一个CPU但是有多个内核，每个CPU能做的事情都是一样的，而且能一起做。</p>
<p>关于这两种 seamless world 架构的基本分析和需要解决的一些主要问题，下次再写。</p>
<hr /><h2>comments,文章评论</h2><ul><li><a href="http://canremember.com/?p=8#comment-4">2008.02月.13</a>, 青风无影 comment: 期待 关于seamless world 架构后续更详细的大作。。。</li><li><a href="http://canremember.com/?p=8#comment-7">2008.04月.15</a>, uvbs comment: Services-based 和 Cells-based在分类上我觉得Services-based更具有逻辑意义一些，Cells-based总觉得只是在物理上进行分类。。。这样分出Cell这个类型我觉得比较牵强</li><li><a href="http://canremember.com/?p=8#comment-35">2010.08月.1</a>, benjiam comment: 今年的 chinadogame 是你做的演讲么？

呵呵。  这个还是理论化太强，离真的实践未必好。 特别是切换的问题。我感觉带来的问题很多</li><li><a href="http://canremember.com/?p=8#comment-36">2010.08月.3</a>, zhiyong comment: to benjiam:

  按这个思路的实现，已经做到了。
  实现这两种架构，确实都有些门槛，问题之一就是解决‘所有权切换’。</li></ul><hr /><h2>Related posts,相关文章</h2><ul>
<!-- Generated by Simple Tags 1.3.8 - http://wordpress.org/extend/plugins/simple-tags -->
	<h4>Related posts</h4>
	<ul class='st-related-posts'>
	<li><a href="http://canremember.com/?p=16" title="技术主义者的网游观点 (2008.03月.23)">技术主义者的网游观点</a> (11)</li>
	<li><a href="http://canremember.com/?p=10" title="无缝世界网游服务器架构的设计思路（续） (2008.02月.15)">无缝世界网游服务器架构的设计思路（续）</a> (4)</li>
	<li><a href="http://canremember.com/?p=4" title="服务器组架构设计需要考虑的一些关键因素 (2008.02月.5)">服务器组架构设计需要考虑的一些关键因素</a> (6)</li>
	<li><a href="http://canremember.com/?page_id=2" title="关于我 (2008.02月.3)">关于我</a> (0)</li>
	<li><a href="http://canremember.com/?p=15" title="Trap of C++ (2008.02月.18)">Trap of C++</a> (0)</li>
</ul>

</ul><hr /><small>Copyright &copy 2008 Wang Zhiyong, Some Rights Reserved ;)<br /> all content of this site is under Creative Commons License <br />
 此网站所有内容采用 知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。(digitalfingerprint: e71076c267f520b120f4bb81270fe189)</small>]]></description>
		<wfw:commentRss>http://canremember.com/?feed=rss2&amp;p=8</wfw:commentRss>
		</item>
		<item>
		<title>任务“耦合”</title>
		<link>http://canremember.com/?p=5</link>
		<comments>http://canremember.com/?p=5#comments</comments>
		<pubDate>Tue, 05 Feb 2008 06:23:18 +0000</pubDate>
		<dc:creator>zhiyong</dc:creator>
		
		<category><![CDATA[开发杂谈]]></category>

		<category><![CDATA[Coupling]]></category>

		<category><![CDATA[任务]]></category>

		<category><![CDATA[工作]]></category>

		<category><![CDATA[工作流]]></category>

		<category><![CDATA[开发]]></category>

		<category><![CDATA[效率]]></category>

		<category><![CDATA[游戏开发]]></category>

		<category><![CDATA[耦合]]></category>

		<guid isPermaLink="false">http://canremember.com/?p=5</guid>
		<description><![CDATA[<p class="MsoNormal"><span lang="EN-US"><span>       </span></span><span style="font-family: 宋体">    对于游戏开发过程中的任务“耦合”，最近感触颇多，多说几句。这里描述一个场景：</span></p>
<p class="MsoNormal" style="text-indent: 21pt"><span style="font-family: 宋体">明天要发布某个游戏版本，现在有个功能模块中发现了一个</span><span lang="EN-US">Bug</span><span style="font-family: 宋体">，会导致女性角色能穿上男性角色的服装。当然大家都不希望老板因此而不爽，所以</span><span lang="EN-US">Team Leader A</span><span style="font-family: 宋体">去告诉负责</span><span lang="EN-US">Avatar</span><span style="font-family: 宋体">系统渲染的</span><span lang="EN-US">Programmer B</span><span style="font-family: 宋体">去检查问题（为什么找</span><span lang="EN-US">B</span><span style="font-family: 宋体">而不是其他人，请自行想象），</span><span lang="EN-US">B</span><span style="font-family: 宋体">检查</span><span lang="EN-US">20</span><span style="font-family: 宋体">分钟之后发现这是数据错误，也就是说服务器方面发过来的数据就是错误的。</span><span lang="EN-US">B</span><span style="font-family: 宋体">接着通知</span><span lang="EN-US">A</span><span style="font-family: 宋体">他的测试结果和发现的原因，然后又去改另外一个</span><span lang="EN-US">Bug</span><span style="font-family: 宋体">。</span><span lang="EN-US">A</span><span style="font-family: 宋体">接下来去找负责服务器上角色逻辑处理的</span><span lang="EN-US">Programmer C</span><span style="font-family: 宋体">，</span><span lang="EN-US">C</span><span style="font-family: 宋体">检查了</span><span lang="EN-US">2</span><span style="font-family: 宋体">个小时之后发现这不是代码里头的</span><span lang="EN-US">Bug</span><span style="font-family: 宋体">导致的而是个数据问题，也就是说数据库内保存的某个物品数据的类型数值和外观并不匹配。</span><span lang="EN-US">C</span><span style="font-family: 宋体">通知了</span><span lang="EN-US">A</span><span style="font-family: 宋体">，</span><span lang="EN-US">A</span><span style="font-family: 宋体">又去找负责维护游戏设定数据的</span><span lang="EN-US">Designer D</span><span style="font-family: 宋体">，</span><span lang="EN-US">D</span><span style="font-family: 宋体">打开自己的</span><span lang="EN-US">Excel</span><span style="font-family: 宋体">之后检查了一个小时，才找到一个数据填写错误——只是该填写为</span><span lang="EN-US">2</span><span style="font-family: 宋体">的一个单元格填成了</span><span lang="EN-US">1</span><span style="font-family: 宋体">而已——问题终于找到了。</span></p>
<p></p>
<p class="MsoNormal" style="text-indent: 21pt"><span lang="EN-US">D</span><span style="font-family: 宋体">改好这个有问题的</span><span lang="EN-US">Excel</span><span style="font-family: 宋体">表格之后提交到</span><span lang="EN-US">svn</span><span style="font-family: 宋体">，再通知</span><span lang="EN-US">A</span><span style="font-family: 宋体">和</span><span lang="EN-US">Programmer E</span><span style="font-family: 宋体">，</span><span lang="EN-US">E</span><span style="font-family: 宋体">更新了</span><span lang="EN-US">Repo. </span><span style="font-family: 宋体">内的数据之后再把表格导入到数据库，然后再删掉已经有了这种‘非法的道具’的所有角色数据库内的记录，然后再通知</span><span lang="EN-US">C</span><span style="font-family: 宋体">重新启动服务器组——问题就快被解决了，只要再做测试去验证一下。</span></p>
<p class="MsoNormal" style="text-indent: 21pt"><span style="font-family: 宋体">这个情景想必大家都比较熟悉。谁都不会因为添错一个单元格这点儿小事儿对肇事的策划发一顿脾气，我猜你们那儿就不会，对吧？尽管整个团队可能就因为这点儿小事儿白白浪费掉几个小时。但是多数时候都没人去计算类似事情的成本，更不去考虑如何改进。</span></p>
<p class="MsoNormal" style="text-indent: 21pt"><span style="font-family: 宋体">我们试试看如何改进：</span></p>
<ul>
<li><span style="font-family: 宋体"></span> <span style="font-family: 宋体">策划的数据表</span><span lang="EN-US">Excel</span><span style="font-family: 宋体">是可以添加数据‘有效性’限制的，同时可以做绝大多数运算，所以也能利用这个功能检测出绝大多数错误；</span></li>
<li><span style="font-family: 宋体"></span> <span style="font-family: Wingdings" lang="EN-US"><span><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal"></span></span></span><span style="font-family: 宋体">程序在加载数据的时候，应该附带必要的合法性检查，何况在系统启动时做检查的开销并不算昂贵；</span></li>
<li><span style="font-family: 宋体"></span> <span style="font-family: Wingdings" lang="EN-US"><span><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal"></span></span></span><span style="font-family: 宋体">是否可以让策划自己修改</span><span lang="EN-US">Excel</span><span style="font-family: 宋体">、修改</span><span lang="EN-US">DB</span><span lang="EN-US">表、重启测试服务器、并且接着验证自己的修改结果？对于专业从事游戏开发的人来说，学会这些想必不难；</span></li>
</ul>
<p class="MsoNormal" style="text-indent: 21pt"><span style="font-family: 宋体">这个问题的关键还是任务存在大量的任务耦合，我们确实需要任务分配、团队合作，但是不能过度，否则沟通成本会上升到过分的程度、而且带来不良气氛、降低工作效率。我们的工作中存在大量不被察觉的可怕的效率低下，如何改进，非常值得思考。发现、设计、改进工作流应该是主要问题之一。</span></p>
<hr /><h2>comments,文章评论</h2><ul><li><a href="http://canremember.com/?p=5#comment-34">2010.06月.24</a>, Lex Zhou comment: 顶你。现实中的确经常遇到这类问题</li></ul><hr /><h2>Related posts,相关文章</h2><ul>
<!-- Generated by Simple Tags 1.3.8 - http://wordpress.org/extend/plugins/simple-tags -->
	<h4>Related posts</h4>
	<ul class='st-related-posts'>
	<li><a href="http://canremember.com/?p=10" title="无缝世界网游服务器架构的设计思路（续） (2008.02月.15)">无缝世界网游服务器架构的设计思路（续）</a> (4)</li>
	<li><a href="http://canremember.com/?p=8" title="无缝世界网游服务器架构的设计思路 (2008.02月.12)">无缝世界网游服务器架构的设计思路</a> (4)</li>
	<li><a href="http://canremember.com/?p=16" title="技术主义者的网游观点 (2008.03月.23)">技术主义者的网游观点</a> (11)</li>
	<li><a href="http://canremember.com/?page_id=2" title="关于我 (2008.02月.3)">关于我</a> (0)</li>
	<li><a href="http://canremember.com/?p=15" title="Trap of C++ (2008.02月.18)">Trap of C++</a> (0)</li>
</ul>

</ul><hr /><small>Copyright &copy 2008 Wang Zhiyong, Some Rights Reserved ;)<br /> all content of this site is under Creative Commons License <br />
 此网站所有内容采用 知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。(digitalfingerprint: e71076c267f520b120f4bb81270fe189)</small>]]></description>
		<wfw:commentRss>http://canremember.com/?feed=rss2&amp;p=5</wfw:commentRss>
		</item>
		<item>
		<title>服务器组架构设计需要考虑的一些关键因素</title>
		<link>http://canremember.com/?p=4</link>
		<comments>http://canremember.com/?p=4#comments</comments>
		<pubDate>Tue, 05 Feb 2008 06:00:58 +0000</pubDate>
		<dc:creator>zhiyong</dc:creator>
		
		<category><![CDATA[网游技术]]></category>

		<category><![CDATA[Architecture]]></category>

		<category><![CDATA[Cluster]]></category>

		<category><![CDATA[Efficiency]]></category>

		<category><![CDATA[MMORPG]]></category>

		<category><![CDATA[Productivity]]></category>

		<category><![CDATA[Scalability]]></category>

		<category><![CDATA[Server]]></category>

		<category><![CDATA[Simplicity]]></category>

		<category><![CDATA[Stability]]></category>

		<category><![CDATA[TCO]]></category>

		<category><![CDATA[服务器组]]></category>

		<category><![CDATA[架构]]></category>

		<category><![CDATA[设计]]></category>

		<guid isPermaLink="false">http://canremember.com/?p=4</guid>
		<description><![CDATA[<p><span style="font-family: 宋体">——</span><span lang="EN-US">Some key problems we should consider when design MMORPG Server Architecture</span></p>
<p class="MsoNormal"><span lang="EN-US"><span>       </span></span><span style="font-family: 宋体">网络游戏出现至今，角色扮演游戏（</span><span lang="EN-US">MMORPG</span><span style="font-family: 宋体">）一直是个主流游戏类型。主要原因还是因为拥有丰富的交互体验，特别是玩家之间的互动、角色扮演的特性在</span><span lang="EN-US">MMORPG</span><span style="font-family: 宋体">这种游戏类型中最能得到丰富的表现。相对于</span><span lang="EN-US">Casual Game</span><span style="font-family: 宋体">网游来说，</span><span lang="EN-US">MMORPG</span><span style="font-family: 宋体">本身的游戏设计方面的特性就决定了</span><span lang="EN-US">MMORPG </span><span style="font-family: 宋体">服务器的设计和实现的难度会更大、对服务器系统的要求更高。这个难度又主要体现在服务器架构设计方面。</span></p>
<p class="MsoNormal"><span lang="EN-US"><span>       </span></span><span style="font-family: 宋体">那么如何设计架构、如何评价架构设计、以什么为标准来决定设计，就是一个问题，接下来说说我对评价标准的看法。</span></p>
<p></p>
<p class="MsoNormal" style="text-indent: 21pt"><span style="font-family: 宋体">服务器组架构（</span><span lang="EN-US">Server Cluster Architecture</span><span style="font-family: 宋体">）的主要评价标准包括：</span></p>
<ul>
<li><span style="font-family: Wingdings" lang="EN-US"><span><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal">         </span></span></span><span lang="EN-US">Stability</span><span style="font-family: 宋体">，稳定性</span></li>
</ul>
<p class="MsoNormal" style="margin-left: 42pt"><span style="font-family: 宋体">稳定提供游戏服务，是服务器系统确保用户体验的最基本要求。稳定性主要与应用服务器的软件质量相关。稳定性处于第一位的原因是稳定性是用户体验的基石，稳定性不过关的话，其他一切都无从谈起。</span></p>
<ul>
<li><span style="font-family: Wingdings" lang="EN-US"><span><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal">         </span></span></span><span lang="EN-US">Efficiency</span><span style="font-family: 宋体">，效率</span></li>
</ul>
<p class="MsoNormal" style="margin-left: 42pt"><span style="font-family: 宋体">服务器组的运行时效率主要体现在服务器系统的承载能力上。对于同类型的游戏来说，同样一组服务器硬件运行</span><span lang="EN-US">A</span><span style="font-family: 宋体">游戏可以承载</span><span lang="EN-US">5000</span><span style="font-family: 宋体">人，但是运行</span><span lang="EN-US">B</span><span style="font-family: 宋体">游戏只能运行</span><span lang="EN-US">2000</span><span style="font-family: 宋体">人，这就是效率差异。</span></p>
<ul>
<li><span style="font-family: Wingdings" lang="EN-US"><span><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal">         </span></span></span><span lang="EN-US">Scalability</span><span style="font-family: 宋体">，可缩放性</span></li>
</ul>
<p class="MsoNormal" style="margin-left: 42pt"><span style="font-family: 宋体">可缩放性在一定程度上可以理解为：增加服务器硬件是否可以相应的提高系统的负载能力或者是否能提高用户体验。承载能力和用户体验都是系统表现的一部分。但是不管对于什么样的系统，系统硬件数量</span><span lang="EN-US">/</span><span style="font-family: 宋体">能力和系统实际运行表现基本上都不可能是线型关系。就是说</span><span lang="EN-US">Scalability</span><span style="font-family: 宋体">总是只能在一定范围内做评价，例如：某系统可以在</span><span lang="EN-US">0</span><span style="font-family: 宋体">－</span><span lang="EN-US">100k</span><span style="font-family: 宋体">在线玩家的情况下提供流畅的游戏。</span></p>
<p class="MsoNormal" style="margin-left: 21pt"><span style="font-family: 宋体">从游戏开发及运营的角度来考虑，主要评价标准还要包括：</span></p>
<ul>
<li><span style="font-family: Wingdings" lang="EN-US"><span><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal">         </span></span></span><span lang="EN-US">Productivity</span><span style="font-family: 宋体">，生产力、开发效率</span></li>
</ul>
<p class="MsoNormal" style="margin-left: 42pt"><span style="font-family: 宋体">服务器的架构设计不止要考虑系统运行时的效率，开发时的工作效率也要考虑。例如：不同的系统服务（</span><span lang="EN-US">Service</span><span style="font-family: 宋体">）或应用服务器（</span><span lang="EN-US">Application Server</span><span style="font-family: 宋体">）之间是否会过度耦合（</span><span lang="EN-US">Over Coupling</span><span style="font-family: 宋体">）？如果这种情况出现，也常常会导致开发人员工作的耦合，在日常的开发中，工作效率就难以保证。想象一下要</span><span lang="EN-US">Debug</span><span style="font-family: 宋体">某个模块时候需要手动的在不同的远程服务器上更新开启</span><span lang="EN-US">3</span><span style="font-family: 宋体">、</span><span lang="EN-US">5</span><span style="font-family: 宋体">个不同的服务器程序。这种小任务重复做一年、二年累积起来就是很大的资源浪费，包括人力和硬件，甚至团队士气。</span></p>
<ul>
<li><span style="font-family: Wingdings" lang="EN-US"><span><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal">         </span></span></span><span lang="EN-US">TCO</span><span style="font-family: 宋体">，总体拥有成本</span></li>
</ul>
<p class="MsoNormal" style="margin-left: 42pt"><span style="font-family: 宋体">尽量使用最便宜、最少量的硬件、最小的带宽、最少的维护人员，尽量达到最好的运行时表现；这直接影响游戏的运营收入、利润率，间接影响游戏的成败、公司的成败；</span></p>
<ul>
<li><span style="font-family: Wingdings" lang="EN-US"><span><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal">         </span></span></span><span lang="EN-US">Simplicity</span><span style="font-family: 宋体">，简单</span></li>
</ul>
<p class="MsoNormal" style="margin-left: 42pt"><span style="font-family: 宋体">简单性要体现在服务器组（</span><span lang="EN-US">Server Cluster</span><span style="font-family: 宋体">）的部署、和维护方面。如果一个游戏服务器组有</span><span lang="EN-US">20</span><span style="font-family: 宋体">台硬件，那么备份数据、更新、重启这种简单的事情都会不再简单。一般游戏服务商每周都只做两小时停机维护，</span><span lang="EN-US">20</span><span style="font-family: 宋体">组服务器的话，一次需要多少人做这个维护工作？</span><span lang="EN-US">40</span><span style="font-family: 宋体">组呢？</span></p>
<ul>
<li><span style="font-family: Wingdings" lang="EN-US"><span><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal">         </span></span></span><span lang="EN-US">Extendibility/</span><span style="font-family: 宋体">可扩展性</span></li>
</ul>
<p class="MsoNormal" style="margin-left: 42pt"><span lang="EN-US">  </span><span style="font-family: 宋体">实际上考虑到网络游戏服务的持续性，可扩展性也很重要，再丰富的游戏内容也无法持续吸引玩家几年，一般的做法就是周期性的持续提供游戏更新。在网游服务器架构设计上考虑内容上的可扩充性，也是有必要的，通过技术细节的改进总可以得到或多或少的改进，但是在架构设计阶段就考虑到可扩展性才是聪明的做法。</span></p>
<hr /><h2>comments,文章评论</h2><ul><li><a href="http://canremember.com/?p=4#comment-10">2008.04月.15</a>, uvbs comment: 网易的邮箱你2个MAIL都不能用，不知道为什么~

想问你个问题。

各服务器之间当然样保持稳定连接。参考了下一些代码~~~都是在几秒之内进行重新连接，这样的做法不太可取，请问你有什么可以替代的方法么？</li><li><a href="http://canremember.com/?p=4#comment-11">2008.04月.15</a>, <a href='http://canremember.com' rel='external nofollow'>zhiyong</a> comment: 说实话，没看懂你说的意思 :D
你发我的mail该不是中间用的  " at " 吧</li><li><a href="http://canremember.com/?p=4#comment-12">2008.04月.15</a>, uvbs comment: 我用的
JerryWang.cn@gmail.cn
JerryWang_cn@msn.com

不知道为什么用不来，我问题的意思是这样：

比如有
LoginGate -  LoginSever之间，（服务器组的内部交互）有时连接会出现不稳定状态，这时需要重新连接，而如果不想让这种情况出现，一些办法是隔段时间进行重连。。。呵呵，我是参考很老的东西啦~~难道你没碰到过这种情况？</li><li><a href="http://canremember.com/?p=4#comment-13">2008.04月.16</a>, <a href='http://canremember.com' rel='external nofollow'>zhiyong</a> comment: 关于服务器组内的连接，除了因为某个server crash掉或者server进程内的“网络模块”出现问题，实在想象不出还有什么其他原因会导致链接“不稳定”了，我是说基本上不要去怀疑hardware、os、compiler甚至msvcrt.dll这些东西。
过去做过的所有项目确实都没碰到网络连接会不稳定的情况。发现过的几乎全部服务失效都是由于人为失误——bug导致，这就算是个统计结果吧。

jerrywang.cn@gmail.com</li><li><a href="http://canremember.com/?p=4#comment-14">2008.04月.17</a>, uvbs comment: 我的本意是想使用SESSION之类的东西，不过现在看起来好象是多余了</li><li><a href="http://canremember.com/?p=4#comment-16">2008.04月.24</a>, 自由电子乙 comment: 曾经的程序员飘过</li></ul><hr /><h2>Related posts,相关文章</h2><ul>
<!-- Generated by Simple Tags 1.3.8 - http://wordpress.org/extend/plugins/simple-tags -->
	<h4>Related posts</h4>
	<ul class='st-related-posts'>
	<li><a href="http://canremember.com/?p=8" title="无缝世界网游服务器架构的设计思路 (2008.02月.12)">无缝世界网游服务器架构的设计思路</a> (4)</li>
	<li><a href="http://canremember.com/?p=16" title="技术主义者的网游观点 (2008.03月.23)">技术主义者的网游观点</a> (11)</li>
	<li><a href="http://canremember.com/?p=10" title="无缝世界网游服务器架构的设计思路（续） (2008.02月.15)">无缝世界网游服务器架构的设计思路（续）</a> (4)</li>
	<li><a href="http://canremember.com/?page_id=2" title="关于我 (2008.02月.3)">关于我</a> (0)</li>
	<li><a href="http://canremember.com/?p=22" title="随便聊聊网游和数据挖掘 (2009.04月.4)">随便聊聊网游和数据挖掘</a> (5)</li>
</ul>

</ul><hr /><small>Copyright &copy 2008 Wang Zhiyong, Some Rights Reserved ;)<br /> all content of this site is under Creative Commons License <br />
 此网站所有内容采用 知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。(digitalfingerprint: e71076c267f520b120f4bb81270fe189)</small>]]></description>
		<wfw:commentRss>http://canremember.com/?feed=rss2&amp;p=4</wfw:commentRss>
		</item>
	</channel>
</rss>
