以字符串为key访问key为整数的数组

June 29th, 2009 by sulong No comments »

题目比较拗口,不多说了,看了程序就明白了:

<?php
$b = array(0=>'bbb');
echo $b['0'];
 
$v = array(0=>'bbb', '0'=>'ccc');
echo $v['0'];
?>

程序输出bbbccc。当数组里没有字符串的’0′,有0时,php自动把作为key的’0′转变成了0。

  • Share/Bookmark

浅谈TOMCAT集群

June 27th, 2009 by wuwei 5 comments »

老实说,一开始我也认为没这个必要,因为加大JVM内存就就可以了嘛,干啥要集群很多TOMCAT呢?其实不是这样的。

首先TOMCAT集群需要APACHE和TOCMAT组合在一起。APACHE作为服务端的访问入口,自动地根据TOMCAT的并发数量分配到不同的TOMCAT里。二者缺一不可。并且配置是比较麻烦的。

很多人没用到集群是因为并发数还没达到一定的程度。一般企业应用最多也就50个并发,架一个TOCMAT,内存开大点就够了。但游戏就不一样了,动不动就几百甚至1000多的并发量,一个TOMCAT吃得消吗?吃不消!通过我们的实践证明,一个TOMCAT最多支撑起150个并发数,有次我们将其开发200个,结果到了170左右TOMCAT立马崩溃。所以后来为了支撑起1000都个并发量,我们架了9个TOMCAT集群。150*9=1350,基本能满足最大的用户访问量了。

有人说还不够,加大TOMCAT的内存嘛!这么并发量不就更大了?非也!我们通过实践证明,一个TOMCAT内存到了1G以上,就起不了多大的效果了,也就是说,1G内存的TOMCAT和2G内存的TOMCAT,基本性能是一样的!哈哈

还有一点,TOMCAT是免费的哦!不花钱还能架起这么大的一个应用,够省了吧?呵呵

  • Share/Bookmark

个人对开发WEB游戏的总结

June 24th, 2009 by wuwei 5 comments »

很多人以为WEB游戏的样子就类似开心网,很简单,主要是大家互动.但其实不是这样的.

开心网的WEB游戏比如种菜,大家觉得画面很精美,其实主要是前段采用了FLASH作为页面的展示,而FLASH有优势也有劣势.画面精良,与服务端数据通讯少(只需要提供必要的数据就可以了)是他的强项.当然他也有很大的缺陷,那就是第一次加载SWF文件很慢.不过因为开心网的这个SWF游戏本身比较小,所以并不能体现出他的劣势,这可能只有开心网这个平台才可以这么做,而很多网页游戏(FALSH版本)光下载SWF(第一次)就需要几M的容量,加上后续还需要下载地图…这不得不感叹有客户端游戏的极大优势啊…

我们的游戏没有采用FALSH方式,当然也有团队对FLASH的SOCKET通讯方式不熟悉,也有FALSH下载量太大导致服务器流量与并发量吃紧有关.我们采用的是javascript.用了很多扩展包,比如propotype,dwr(ajax),以及JS的特效包.页面采用的是WEB2.0(CSS+DIV)方式.其实效果也是很好的.这里不得不说一下DWR了.速度快,只刷新局部页面是他的最大优势.普通的WEB请求需要请求图片,js,html等等,花费的请求时间与数据下载量巨大.一个JS小的到50毫秒,大的到500毫秒不等.而不起眼的小图片,竟然也会吞噬你20毫秒的时间,而这些请求一累计,请求时间花费无数…这个时候DWR就发挥出他的威力了,他只有一个请求(只有一个!)在这个游戏里最大的数据库消耗功能(排名统计)也仅仅用了800毫秒,而这个功能竟然包括了数据库的一张表(几万数据量)的 1select,2count,3where 等3次查询,性能之高可想而知.

这里大家可以看出来,WEB游戏除了画面之外,重要的是什么?性能.基本上我们游戏5万个会员,在线人数保持在500人左右(并发量).这可不同于普通网站的在线人数哦.因为普通网站一般访问一下要过好久然后再次请求,没有狂刷页面的.而游戏是实时互动的.一个用户可能一秒就要来一个请求,服务器的压力之大可想而知…有人说,加大服务器配置嘛,这句有点偏颇.其实是,要先从软件的角度优化性能.比如不必要的数据库查询(大约占性能的30%),比需要的网络请求下载(30%),数据的缓存(20%)以及其他的一些优化.需要综合…这样的结果就是,我们用3台服务器(1个MYSQL,2台应用)撑起了整个游戏环境(应用服务器还是TOMCAT集群的哦!)

开服只1个月,数据库量大到什么程度?一张表竟然有100万条记录了…这时候怎么办呢?目前比较好的想法是用年月的方式作为表的名称,但这个就与hibernate的动态映射有关了,网上搜了一下有这个技术,但目前还没用.只能用定时删除历史的方式来实现了..呵呵

做游戏,重要的是你要时刻考虑:性能,游戏的效率,游戏的可玩性.如果你觉得这个功能好玩,就要吧他做到最好,既好玩,又速度快,又要让玩家有刺激感…很复杂啊..

第一部分先写到这里吧,能写的太多了,这里只是一小部分.呵呵

  • Share/Bookmark

ActiveMQ使用经验

June 18th, 2009 by sulong No comments »

ActiveMQ是apache的一个开源JMS服务器,不仅具备标准JMS的功能,还有很多额外的功能。公司里引入ActiveMQ后,ActiveMQ成里我们公司业务系统中最重要的一个环节。所有应用都通过jms集成,如果ActiveMQ出了故障,整个系统就瘫痪了。因此,头对ActiveMQ的性能,可靠性,以及如何正确使用,是非常的关心的,而我就被指派来做关于ActiveMQ的调研,本文对此做了些总结。

1 使用jms需要注意的问题

一下所述的问题,不仅是对ActiveMQ,对于其他的JMS也一样有效。

1.1 不要频繁的建立和关闭连接

JMS使用长连接方式,一个程序,只要和JMS服务器保持一个连接就可以了,不要频繁的建立和关闭连接。频繁的建立和关闭连接,对程序的性能影响还是很大的。这一点和jdbc还是不太一样的。

1.2 Connection的start()和stop()方法代价很高

JMS的Connection的start()和stop()方法代价很高,不能经常调用。我们试用的时候,写了个jms的connection pool,每次将connection取出pool时调用start()方法,归还时调用stop()方法,然而后来用jprofiler发现,一般的cpu时间都耗在了这两个方法上。

1.3 start()后才能收消息

Connection的start()方法调用后,才能收到jms消息。如果不调用这个方法,能发出消息,但是一直收不到消息。不知道其它的jms服务器也是这样。

1.4 显示关闭Session

如果忘记了最后关闭Connection或Session对象,都会导致内存泄漏。这个在我测试的时候也发现了。本来以为关闭了Connection,由这个Connection生成的Session也会被自动关闭,结果并非如此,Session并没有关闭,导致内存泄漏。所以一定要显示的关闭Connection和Session。

1.5 对Session做对象池

对Session做对象池,而不是Connection。Session也是昂贵的对象,每次使用都新建和关闭,代价也非常高。而且后来我们发现,原来Connection是线程安全的,而Session不是,所以后来改成了对Session做对象池,而只保留一个Connection。

2 集群

ActiveMQ有强大而灵活的集群功能,但是使用起来还是会有很多陷阱。

2.1 broker cluster和 master-slave

ActiveMQ可以做broker的集群,也可以做master-slave方式的集群。前者能在多个broker之前fail-over和load-balance,但是在某个节点出故障时,可能导致消息丢失;而后者能实时备份消息,和fail-over,但是不能load-balance。broker cluser的方式,在一个broker上发送的消息可以在其它的broker上收到。当一个broker失效时,客户端可以自动的转到别的broker上运行,多个broker可以同时提供服务,但是消息只存储在一个broker上,如果那个broker失效了,那么客户端直到它重新启动后才能收到该broker上的消息,假如很不幸,那个broker的存储介质坏了,那么消息就丢失掉了。
Master-slave方式中,只有master提供服务,slave只是实时的备份master的数据,所以消息不会丢失。当master失效时,slave会自动升为master,客户端会自动转到slave上工作,所以能fail-over。由于只有master提供服务,所以不能将负载分到多个broker上。
其实单个broker的性能已经是相当的惊人了,在我们公司的机器上能达到每秒收发4000个消息,没个消息4K字节这样的速度,足够公司目前的需要了,而公司并不希望丢失任何数据,所以我们选择使用master-slave模式。

2.2 多种master-slave模式

master-slave也有多种实现方式。它们的不同只是在共享数据和锁机制上。

2.2.1 Pure master-slave

Pure master-slave,显示的在配置文件中指定一个broker做为另一个broker的slave。运行时,slave同过网络自动从master出复制数据,同时在和master失去连接时自动升级为master。当master失效,slave成为master后,如果要让原先的master重新投入运行,需要停掉运行中的slave(现在升级为master了),手动复制slave中的数据到master中。再重新启动master和slave。这种方式最简单,效率也不错,但是只能有两台做集群,只能fail-over一次,而且需要停机回复master-slave结构。

2.2.2 JDBC master-slave

这种方式不需要特殊的配置,只要让所有的节点都把数据存储到同一个数据库中。先拿到数据库表的锁的节点成为master,一旦它失效了,其它的节点获得锁,就可以成为master。因为数据通过数据库共享,放在一个地方,不需要停机恢复master-slave。这种方式,需要额外的数据库服务器,如果数据库失效了,那么就全失效了,而且速度不是很快。我们在用mysql测试时,并没有成功,master失效后,其他的节点始终没有升级成slave,可能是数据库配置的问题。

2.2.3 Share file master-slave

这种方式类似于前者,也不需要特别的配置,只是通过共享文件系统来共享数据,靠文件锁实现只有一台成为master。共享文件系统的方式有很多,我们测试了nfs v4 (v3有bug,不行), 最终在稳定性,效率等方面不是很满意,可能是通过网络太慢了。

测试过众多master-slave模式后发现,pure方式管理起来麻烦,jdbc方式成本高,效率低,share file方式需要高性能的共享文件,都有缺点。鉴于单台activeMQ很可靠,而我们的基础平台组愿意用硬件备份,最终还是决定不用master-slave了,也不用broker cluster,就用单台,通过硬件冗余保证数据不会丢失,并找另外一台刀片机做冷备,在主服务器失效时顶替。

  • Share/Bookmark