幸与不幸

昨天发现log中有一段异常的日志.如果那样的话 会出大问题… 结果查了一下代码, 我竟然还有一个判断. 保证了一次的处理.
不会被重复的请求影响… 真是神来之笔…  这阵子神经是越发的紧张… 而愁人的是我快成十万个为什么了,什么都来问我…
地球离了我 就不转了么? 下个月想休息休息了. 咱也歇歇年假?

#程序这行还是需要保持一贯的严谨性. 保证条件分支的高覆盖. 于人于己百利无一害.

Read More

时间即使再紧迫也不能压缩的时间就是充分测试.

RT: 稳定压倒一切. 第一个目标就是要保证游戏的可持续性. 数值调整以及很多工作都可以在这个基础上做。要知道没有这个根基,一切都是零. 就算时间再紧,不能压缩的就是充分测试, bot测试,QA测试,真人测试. 都pass之后,才可以给玩家!!
同样的错误不能再犯.
最近也发现,其实一些问题应该是可以提前发现的 只要测试充分.我指的是QA无法发现的问题, 现在BOT基本能发现大量行为之后的bug. 剩余的就是代码的 数据的错误了.   代码不具备复用性,还被到处使用..  直到有一天有人发现原来这个代码有bug….
但从来没有人在此之前测试过…  如果能结合驱动测试就好了.需要的只是编写一个测试用例, 是不是更高级了, 不再去点来点去的测试UI了. 而且测试的效果更加明显, 更科学.
Test Driven Development.  是有意义的. 
延展阅读: http://onlamp.com/pub/a/python/2004/12/02/tdd_pyunit.html

Read More

11.22 相约神骑世界,我们不为漂亮而死

今天依旧是个繁忙的周六. 依旧到公司加班.回家时,依然是母亲忙碌的身影,和熟睡的孩子。
不经意错过了,足协杯泰达的生死战. 结局竟然如此让我震撼,说实话,我看到这个消息的时候,我的眼泪都快出来了.
我相信这是一种启示, 天道酬勤.
继续努力奋斗中.11/22 12/9 重大的时刻即将来临.
希望能对得起兄弟们的血汗付出,能给大家的生活添一份美好回忆.

11.22 欢迎你来.

Read More

使用asyncore的总结

因为引擎的原因,逼得我用aysncore这个module 写了一个 proxyserver.  用于中转与billing服务器的数据收发. 话说一不小心,断断续续 大大小小 竟然改了大半年. 闲下来的时候,我觉得还是有必要梳理一下,免得日久遗忘了.
对比第一版和目前的版本, 我想有几个点是很重要的.

0.尽早测试,边界测试也很必要.没有环境的话,可以写测试函数,模拟调用. 不能等,等真的上了实际运行环境,你会发现测试起来会更麻烦,更困难.  貌似这是新人经常有的心理, 总以为等到后面就会容易了.

1. 要相信一些既定的现实.  asyncore 这个模块是可以用的. 但是要用对了. 不能在继承了asyncore.dispatcher 之后 不调用 它的函数.那样会遗漏一些处理.导致不确定的问题. 具体些.

myDispatcher(asyncore.dispatcher):
def   close(self):

asyncore.dispatcher.close()  #must call it.

#some code your wirttern
2. 要怀疑一些既定的现实:  也许你想不到asyncore 的模块2.2 时是好用的 但是后来2.5 到2.6 都有一些或多或少的bug.   这一点可以从google查询得知.  所以我们需要做一些修改.  比如:默认 超时时间是30S 实际上需要我们自己调整为一个合理的数值, 我最后用的是 0.1    asyncore.loop(0.1, use_poll, self.socketMap) .  不然会有响应延迟的情况.  还有一些判定socket 状态的部分.  所以我拿了python2.7 的这个asyncore 模块然后 merge了一些有用的修改.

下面列举一些遇到的一些错误和解决的方法.
1. 9  Bad File Descriptor .

这个错误实际上是没有正确关闭socket channel导致的. 而正确关闭的方法就是必须要call  asyncore.dispatcher.close()  .  你可以追踪一下代码,发现这个函数会从 socketMap 里删除当前的socket 的handle.  如果遗漏了close 的调用. 或者不正确调用close 都有可能导致这个错误的抛出.
2. Threaded aysncore loop .

asyncore 的 loop 函数不是线程的. 所以如果要独立使用这个函数, 需要自己开一个线程. 而不是直接调用,否则会阻塞主线程.  第一版我在每个进程里是共用asyncore的sockmap的. 第二版我把这些分开了,各自负责各自的,这样就不会互相影响了. 不然某个socket有问题都会触发异常.. (最后的结果其实还不是这个问题,是close没有处理好 就是没有管理好socketmap)

比如:
asyn_thread = Thread(target=self._async_loop,
args=(),
name=’%s asyncore thread’ % “proxy slave”)
#if disable mode, ignore create thread realy
asyn_thread.start()      这样就ok 了.   async_loop 函数就是用老套的loop

要注意的一点是: 这需要自己管理socketmap,  这样的话开多少个线程都没关系..  不然都用 aysncore.loop  会互相影响..
我的第一个版本就是用一个 asyncore.loop 然后当某个socket关闭的时候 会导致异常, 抛出那个  error  9  bad file descriptor . 而的糟糕是, 第一个版本里, 在proxy 没有建立好连接的时候, 会关掉所有请求的client连接. 结果就是恶性循环, 抛出异常后, 就关闭所有的  asyncore.close_all() ..  实际上需要解决的是保证 close() 被正确调用.. 然后从 asyncore.socketMap 里移除.

3. 谨慎处理一些容易抛出异常的函数.  比如: try connect 异常时要重新设置逻辑连接状态为 False..   不能再等handle_except 处理. 一般不需要自己处理这个.  默认实际上是调用 handle_close的

我在上面提到的线程函数 asyn_loop 有加上重连机制. 以便在连接中断后能处理. 恢复连接.

def _async_loop(self):
print ‘create asynloop for ‘,self
while True:
#step 1. try to ensure wasConnected
obj = self
while not obj._wasConnected:
try:
self.tryconnect()
obj._wasConnected = True
time.sleep(3)
except Exception,e:
self.close()
obj._wasConnected = False
print ‘during reconnect occur’,e
while obj._wasConnected:
use_poll = False
if hasattr(select, ‘poll’):
use_poll = True
try:
#use_poll = False #hard code . for windows select mode has been test 2011-10-21
print self._asyn,’Asyn Monitor loop is running use poll? %s’%use_poll,self.socketMap
asyncore.loop(0.1, use_poll, self.socketMap)#,count=1)
except select.error,args:
#if select.error.
from errno import EINTR
if args[0] == EINTR:
print(‘Shutdown not completely clean…’)
else:
pass
#server mode
if not self.connected:
if self.accepting:
if len(self.socketMap) ==1:
print ‘only server is running no client’,self._wasConnected
self._wasConnected = True
else:
obj._wasConnected = False
else:
obj._wasConnected = False
#ignore.

#to trigger connected = False.. 2.7 seems connected will wait handle_connect function. support logic connect state.
#which close socket should be handled by dispatcher self.
#should asyncore.close_all() ?
#self.close()
self._wasConnected = False
print  self._asyn,’Asyn Monitor Disconnect’,self.socketMap,obj.connected

总的来说,用asyncore 模块就是异步的方式,可以充分利用系统的处理能力,应该说效率还是蛮高的, 在linux上实际上是用epoll 模块. 可以支持很大的吞吐.开销也小. 就像windows上的完成端口..

Read More

CB1.5结束 CB2.0开启

CB1.5版本已经提交, 此次还是出现了一些老问题, 文件丢失数据不对,都是出在后期手动作版本时。同时有个新问题就是没有经过检查就发出去了. :(
11.11 有真人测试,结果很多人可能是没办法进入游戏,因为图像配置默认是高? 但有一个好消息就是,任何不能登陆的帐号,在本地都是可以的, 就是说服务器没有问题.

想想还是因为没有足够的测试造成的. 每一点改动都可能会引起一连串的问题. 最近也一直在反省, 或许我们应该用别的办法来测试一些问题,而不能都等到发现问题. 比如我们需要一个电信的线路来测试.

服务器方面,貌似第八张地图没有算地图,导致传送点不好用. (建branch版本以后 美术才传了一版算过的) .

随着时间的推移,明显的bug消失之后,隐含的bug出现的话,就越来越难查了. 尤其是需要查很多log以后才会发现一些蛛丝马迹.. 如果是明显的error 倒好办些.

#要从海量的log里查到有用的信息,来推断一些事实 和解释一些问题实在是令人疲惫.

期待周一的bot版本测试 能发现一些问题.
或者所有版本最好先跑一遍bot 比真人测试或许更有意义.

Read More

《武侠》说的是什么事?

武侠, 悬乎了整片.

最后大boss是死于天灾,雷击. 金城武给他做了导体。

玄幻了整个电影的武功分析,最后都是狗屁. 不如天的力量.

而另一方面是颂扬了 信仰或者是信念.   金喜是个大好人.  于是就可以做个好人.

人或许就是如此,好多人可能都是如此?或者说导演想说,有这样的人是这样的.

Read More