<?xml version="1.0" encoding="UTF-8"?>
<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/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>中文 &#187; smarttony</title>
	<atom:link href="http://software.intel.com/zh-cn/blogs/author/smarttony/feed/" rel="self" type="application/rss+xml" />
	<link>http://software.intel.com/zh-cn/blogs</link>
	<description></description>
	<lastBuildDate>Sat, 26 May 2012 06:34:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>游戏服务器的架构设计</title>
		<link>http://software.intel.com/zh-cn/blogs/2011/12/16/400009430/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2011/12/16/400009430/#comments</comments>
		<pubDate>Fri, 16 Dec 2011 02:39:29 +0000</pubDate>
		<dc:creator>smarttony</dc:creator>
				<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[服务器]]></category>
		<category><![CDATA[游戏]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2011/12/16/400009430/</guid>
		<description><![CDATA[  游戏服务器的设计是一项颇有挑战性的工作，游戏服务器的发展也由以前的单服结构转变为多服机构，甚至出现了bigworld引擎的分布式解决方案，最近了解到Unreal的服务器解决方案atlas也是基于集群的方式。 负载均衡是一个很复杂的课题，这里暂不谈bigworld和atlas的这类服务器的设计，更多的是基于功能和场景划分服务器结构。 首先说一下思路，服务器划分基于以下原则： 1：分离游戏中占用系统资源（cpu，内存，IO等）较多的功能，独立成服务器 2：在同一服务器架构下的不同游戏，应尽可能的复用某些服务器（进程级别的复用） 3：以多线程并发的编程方式适应多核处理器。 4：宁可在服务器之间多复制数据，也要保持清晰的数据流向 5：主要按照场景划分进程，若需按功能划分，必须保持整个逻辑足够的简单，并满足以上1，2点 服务器结构图： 各个服务器的简要说明： Gateway：应用网关，主要用于保持和client的连接，该服务器需要2种IO，对client采用高并发连接，低吞吐量的网络模型，如IOCP等，对服务器采用高吞吐量连接，如阻塞或异步IO。 网关主要有以下用途： 1：分担了网络IO资源 2：同时，也分担了网络消息包的加解密，压缩解压等cpu密集的操作。 3：隔离了client和内部服务器组，对client来说，它只需要知道网关的相关信息即可（ip和port）。 4：client由于一直和网关保持常连接，所以切换场景服务器等操作对client来说是透明的。 5：维护玩家登录状态 World Server 是一个控制中心，它负责把各种计算资源分布到各个服务器 它具有以下职责： 1：管理和维护多个Scene Server 2：管理和维护多个功能服务器，主要是同步数据到功能服务器 3：复杂转发其他服务器和Gateway之间的数据 4：实现其他需要跨场景的功能，如组队，聊天，帮派等 Phys Server 主要用于玩家移动，碰撞等检测 所有玩家的移动类操作都在该服务器上做检查，所以该服务器本身具备所有地图的地形等相关信息。具体检查过程是这样的：首先，Worldserver收到一个移动信息，WorldServer收到后向Phys Server请求检查，Phys Server检查成功后再返回给world Server，然后world server传递给相应的Scene Server. Scene Server 场景服务器，按场景划分，每个服务器负责的场景应该是可以配置的。理想情况下是可以动态调节的。 ItemMgr Server 物品管理服务器，负责所有物品的生产过程。在该服务器上存储一个物品掉落数据库，服务器初始化的时候载入到内存。任何需要产生物品的服务器均与该服务器直接通信 AIServer 又一个功能服务器，负责管理所有NPC的AI。AI服务器通常有2个输入，一个是Scene Server发送过来的玩家相关操作信息，另一个时钟Timer驱动，在这个设计中，对其他服务器来说，AIServer就是一个拥有很多个NPC的客户端。AIserver需要同步所有与AI相关的数据，包括很多玩家数据。由于AIServer的Timer驱动特性，可在很大程度上使用TBB程序库来发挥多核的性能。]]></description>
			<content:encoded><![CDATA[<p> </p>
<p>游戏服务器的设计是一项颇有挑战性的工作，游戏服务器的发展也由以前的单服结构转变为多服机构，甚至出现了bigworld引擎的分布式解决方案，最近了解到Unreal的服务器解决方案atlas也是基于集群的方式。</p>
<p>负载均衡是一个很复杂的课题，这里暂不谈bigworld和atlas的这类服务器的设计，更多的是基于功能和场景划分服务器结构。</p>
<p>首先说一下思路，服务器划分基于以下原则：<br />
1：分离游戏中占用系统资源（cpu，内存，IO等）较多的功能，独立成服务器<br />
2：在同一服务器架构下的不同游戏，应尽可能的复用某些服务器（进程级别的复用）<br />
3：以多线程并发的编程方式适应多核处理器。<br />
4：宁可在服务器之间多复制数据，也要保持清晰的数据流向<br />
5：主要按照场景划分进程，若需按功能划分，必须保持整个逻辑足够的简单，并满足以上1，2点</p>
<p>服务器结构图：</p>
<p><img src="http://images.csdn.net/20111215/1.jpg" alt="null" /><br />
各个服务器的简要说明：</p>
<p>Gateway：应用网关，主要用于保持和client的连接，该服务器需要2种IO，对client采用高并发连接，低吞吐量的网络模型，如IOCP等，对服务器采用高吞吐量连接，如阻塞或异步IO。</p>
<p>网关主要有以下用途：<br />
1：分担了网络IO资源<br />
2：同时，也分担了网络消息包的加解密，压缩解压等cpu密集的操作。<br />
3：隔离了client和内部服务器组，对client来说，它只需要知道网关的相关信息即可（ip和port）。<br />
4：client由于一直和网关保持常连接，所以切换场景服务器等操作对client来说是透明的。<br />
5：维护玩家登录状态</p>
<p>World Server 是一个控制中心，它负责把各种计算资源分布到各个服务器<br />
它具有以下职责：<br />
1：管理和维护多个Scene Server<br />
2：管理和维护多个功能服务器，主要是同步数据到功能服务器<br />
3：复杂转发其他服务器和Gateway之间的数据<br />
4：实现其他需要跨场景的功能，如组队，聊天，帮派等</p>
<p>Phys Server 主要用于玩家移动，碰撞等检测<br />
所有玩家的移动类操作都在该服务器上做检查，所以该服务器本身具备所有地图的地形等相关信息。具体检查过程是这样的：首先，Worldserver收到一个移动信息，WorldServer收到后向Phys Server请求检查，Phys Server检查成功后再返回给world Server，然后world server传递给相应的Scene Server.</p>
<p>Scene Server 场景服务器，按场景划分，每个服务器负责的场景应该是可以配置的。理想情况下是可以动态调节的。</p>
<p>ItemMgr Server 物品管理服务器，负责所有物品的生产过程。在该服务器上存储一个物品掉落数据库，服务器初始化的时候载入到内存。任何需要产生物品的服务器均与该服务器直接通信</p>
<p>AIServer 又一个功能服务器，负责管理所有NPC的AI。AI服务器通常有2个输入，一个是Scene Server发送过来的玩家相关操作信息，另一个时钟Timer驱动，在这个设计中，对其他服务器来说，AIServer就是一个拥有很多个NPC的客户端。AIserver需要同步所有与AI相关的数据，包括很多玩家数据。由于AIServer的Timer驱动特性，可在很大程度上使用TBB程序库来发挥多核的性能。</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2011/12/16/400009430/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>架构设计之性能设计经验</title>
		<link>http://software.intel.com/zh-cn/blogs/2010/09/15/400005818/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2010/09/15/400005818/#comments</comments>
		<pubDate>Wed, 15 Sep 2010 07:42:18 +0000</pubDate>
		<dc:creator>smarttony</dc:creator>
				<category><![CDATA[其他]]></category>
		<category><![CDATA[博客征文专栏]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2010/09/15/400005818/</guid>
		<description><![CDATA[性能(performance)设计非常重要，对于服务器端实时交易系统来说系统性能的重要性不言而喻，对客户端软件来说性能好的软件也会获得良好的用户体验，从而给用户留下高质量软件的良好印象。因此在进行架构设计中性能设计非常重要。 但架构设计实际是一个平衡设计，在可用性、可扩展性、可维护性、可靠性、高性能等之间做个妥协选择。这些非功能性的需求再加上复杂的功能性需求，同时还要考虑到项目管理上tight schedule, low cost, perfect effect的三角难题约束，有时需求还不是很明确，vision不是很清楚，这种情况下系统架构设计真是一门艺术。 单就性能设计来说，在架构设计初期就一定要把系统性能考虑在内，否则等开发完成以后测试发现性能不好就比较难办，通常要花费较长的时间来诊断性能瓶颈，找到提升的办法，甚至要改变架构，伤筋动骨，往往造成项目延期。所以性能设计首先要有明确的性能目标，根据用户和软件本身的性能要求来设计，合适的就是最好的。其次，要有适当的度量标准和量化的性能指标。最后，要有相应的设计策略，具体的测试方法。 根据我的经验，影响系统性能主要瓶颈在I/O，包括数据库，socket，网络通信，文件等，例如频繁查询数据库并返回大量结果集，频繁操作大文件等，这些昂贵的操作会占用大量的CPU时间。拿系统响应和服务一个事务来说，有几个Round trip，要通过哪几层I/O，如何合理的分配这些I/O的调用，降低不必要的I/O，都是进行系统性能设计要考虑的。而有些性能问题在初期并不会表现出来，但当拿到实际上线环境下，存在多用户并发、大数据量的情况下就会暴露出严重的问题。所以性能设计时一定要考虑到I/O，同步，并发，资源争用，以及大数据量等因素。通常，I/O操作、网络响应、差的算法、数据库、以及其他的低效的资源使用都会导致低劣的性能。 具体可用的设计策略有： - 缓存以及缓存层(caching layer) 在数据层和应用层之间增加数据缓存层，提供全局数据服务。可以大大减少数据库往返次数。与读取数据库和读取大文件（如XML文件）比，读取内存的速度无疑要快的多。所以对经常要访问的数据进行缓存是非常好的实践方法。因为现在系统往往内存很大，可以充分利用大内存，而共享内存更能实现数据并发访问。 - 多线程(multi-threading) 现在基本上大部分软件实现多线程或多进程，多线程对单CPU系统还只是顺序利用CPU时间和改善用户体验，多CPU系统才是真正的并行。要注意的是多线程不要争抢访问同一资源而导致部分串行操作，要做到真正的并行操作多线程并不容易。另外，在多线程间同步一个庞大的资源，过多创建线程又没有实现线程池也会导致系统性能下降。 - 负载平衡(load balancing) 物理上增加地位对等的集群服务器（Cluster），通过负载分配算法分配相应服务器来相应客户端请求。很多系统支持负载均衡，Windows server2003 IIS就支持负载均衡服务，其他如WebLogic, WebSphere也有集群版本支持负载均衡。当然你也可以自己实现负载分配算法。 - 数据库优化（database optimization） 如果应用程序使用了数据库，可以采取许多步骤来消除访问和写入数据时的瓶颈： - 标识潜在的索引，但不要创建过多的索引。 - 如果使用 SQL Server，则使用 SQL Server 的事件探查器和索引优化向导。 - 监视处理器的使用；理想范围是：75-80% 处理器时间。 - 使用查询分析器分析查询计划以优化查询。 - 使用存储过程优化性能。 - 标准化写入的大量数据 —写入较少的数据。 - 取消标准化读取的大量数据 —读取较少的数据。 文件系统优化 有时候系统性能不好，但当你关闭写log的功能，性能一下子提高很多。因为频繁的打开关闭大log文件时I/O开销非常大，同样记录log到数据库也一样。所以，release版尽量减少写log，或干脆移到裸设备上。 频繁打开关闭文件对系统性能下降程度是惊人的，可以通过一些变通办法来减少文件的频繁操作。 例如，原来的缓存持久化实现是保存在XML文件，每次要获得一个配置项，都打开XML文件，通过XPath拿到这个配置项的值，这样效率不高，而且容易把这个XML文件lock住；改进的方法是：通过比较XML文件的修改时间(System.IO.File.GetLastWriteTime)判断是否要再次打开文件，大大提高了效率；另一个可以改进的方法是：启动时读取所有配置到一个静态的HashTable，每次要获得一个配置项都从内存HashTable获取，在最后或适当的时候持久化到XML。 [...]]]></description>
			<content:encoded><![CDATA[<p>性能(performance)设计非常重要，对于服务器端实时交易系统来说系统性能的重要性不言而喻，对客户端软件来说性能好的软件也会获得良好的用户体验，从而给用户留下高质量软件的良好印象。因此在进行架构设计中性能设计非常重要。<br />
但架构设计实际是一个平衡设计，在可用性、可扩展性、可维护性、可靠性、高性能等之间做个妥协选择。这些非功能性的需求再加上复杂的功能性需求，同时还要考虑到项目管理上tight schedule, low cost, perfect effect的三角难题约束，有时需求还不是很明确，vision不是很清楚，这种情况下系统架构设计真是一门艺术。<br />
单就性能设计来说，在架构设计初期就一定要把系统性能考虑在内，否则等开发完成以后测试发现性能不好就比较难办，通常要花费较长的时间来诊断性能瓶颈，找到提升的办法，甚至要改变架构，伤筋动骨，往往造成项目延期。所以性能设计首先要有明确的性能目标，根据用户和软件本身的性能要求来设计，合适的就是最好的。其次，要有适当的度量标准和量化的性能指标。最后，要有相应的设计策略，具体的测试方法。<br />
根据我的经验，影响系统性能主要瓶颈在I/O，包括数据库，socket，网络通信，文件等，例如频繁查询数据库并返回大量结果集，频繁操作大文件等，这些昂贵的操作会占用大量的CPU时间。拿系统响应和服务一个事务来说，有几个Round trip，要通过哪几层I/O，如何合理的分配这些I/O的调用，降低不必要的I/O，都是进行系统性能设计要考虑的。而有些性能问题在初期并不会表现出来，但当拿到实际上线环境下，存在多用户并发、大数据量的情况下就会暴露出严重的问题。所以性能设计时一定要考虑到I/O，同步，并发，资源争用，以及大数据量等因素。通常，I/O操作、网络响应、差的算法、数据库、以及其他的低效的资源使用都会导致低劣的性能。<br />
具体可用的设计策略有：<br />
- 缓存以及缓存层(caching layer)<br />
在数据层和应用层之间增加数据缓存层，提供全局数据服务。可以大大减少数据库往返次数。与读取数据库和读取大文件（如XML文件）比，读取内存的速度无疑要快的多。所以对经常要访问的数据进行缓存是非常好的实践方法。因为现在系统往往内存很大，可以充分利用大内存，而共享内存更能实现数据并发访问。<br />
- 多线程(multi-threading)<br />
现在基本上大部分软件实现多线程或多进程，多线程对单CPU系统还只是顺序利用CPU时间和改善用户体验，多CPU系统才是真正的并行。要注意的是多线程不要争抢访问同一资源而导致部分串行操作，要做到真正的并行操作多线程并不容易。另外，在多线程间同步一个庞大的资源，过多创建线程又没有实现线程池也会导致系统性能下降。<br />
- 负载平衡(load balancing)<br />
物理上增加地位对等的集群服务器（Cluster），通过负载分配算法分配相应服务器来相应客户端请求。很多系统支持负载均衡，Windows server2003 IIS就支持负载均衡服务，其他如WebLogic, WebSphere也有集群版本支持负载均衡。当然你也可以自己实现负载分配算法。<br />
- 数据库优化（database optimization）<br />
如果应用程序使用了数据库，可以采取许多步骤来消除访问和写入数据时的瓶颈：<br />
- 标识潜在的索引，但不要创建过多的索引。<br />
- 如果使用 SQL Server，则使用 SQL Server 的事件探查器和索引优化向导。<br />
- 监视处理器的使用；理想范围是：75-80% 处理器时间。<br />
- 使用查询分析器分析查询计划以优化查询。<br />
- 使用存储过程优化性能。<br />
- 标准化写入的大量数据 —写入较少的数据。<br />
- 取消标准化读取的大量数据 —读取较少的数据。<br />
文件系统优化<br />
有时候系统性能不好，但当你关闭写log的功能，性能一下子提高很多。因为频繁的打开关闭大log文件时I/O开销非常大，同样记录log到数据库也一样。所以，release版尽量减少写log，或干脆移到裸设备上。<br />
频繁打开关闭文件对系统性能下降程度是惊人的，可以通过一些变通办法来减少文件的频繁操作。<br />
例如，原来的缓存持久化实现是保存在XML文件，每次要获得一个配置项，都打开XML文件，通过XPath拿到这个配置项的值，这样效率不高，而且容易把这个XML文件lock住；改进的方法是：通过比较XML文件的修改时间(System.IO.File.GetLastWriteTime)判断是否要再次打开文件，大大提高了效率；另一个可以改进的方法是：启动时读取所有配置到一个静态的HashTable，每次要获得一个配置项都从内存HashTable获取，在最后或适当的时候持久化到XML。<br />
代码性能设计<br />
在编程实现上，代码性能设计也很重要，一些昂贵的操作会占用大量的资源和CPU时间。例如，字符串相加没用StringBuilder, 频繁创建对象，差劲的排序或递归算法，过多的装箱拆箱，过多的使用反射（Reflection），频繁new HashTable或大的数组，用异常（Catch Exception）用做正常的逻辑，使用复杂的正则表达式，等等。具体可以参考《Effective C++》《Effective C#》等书籍。<br />
语言的选择<br />
另外，语言选择也很重要。比如相对于Java, C#, C++, 大多数OLTP系统用C语言效率高的多，因为在所有的高级程序设计语言中，C程序设计语言的运行效率是公认的。再比如我们熟悉的一些框架，框架本身是C#或是Java的，但其核心独立模块是C++封装的，这样可以达到最佳的性能。所以对于一些特定的业务需求目标和数据的具体情况，对于核心的模块或算法，可以用特定的语言来实现以获得更好的效率。<br />
应用层<br />
比如应用层和数据库的API，在.Net中就有就有DataReader、DataSet和IList等的选择以及转换等，这个根据具体情况而定；还有就是大家常采用的数据的格式化和压缩，以及采用分页，减少传输的数据量；是否可以把一部分处理逻辑放在客户端呢，减少服务端的工作量。界面端也是有很多针对性能优化的考虑，例如绘图，控件重绘都是非常耗资源的，各控件的数据加载和数据绑定性能也各不相同，尽量采用惰性加载，异步加载；初始化和启动速度等都是需要考虑和优化的。</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2010/09/15/400005818/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

