巴别塔上的雇工


建军八十周年
7月 31, 2007, 2:46 下午
Filed under: 山河好大
今年是建军八十周年,这个“建军”是缩写,全称是什么呢?你要说是“中国人民解放军建立”,不准确,因为八十年前还没有“解放军”这概念呢;你要说是“红军”,那也犯了错误,南昌起义之后的部队旗号还是“国民革命军”,是为了用这么名号争取大众的支持。

还有几个有趣的地方,毛主席领导的秋收起义的部队,打出的旗号是“工农革命军第四军”,第一、二、三军还没有怎么就出来四呢?这是因为在第一次国共合作的北伐时期,叶挺独立团所在的第四军特别生猛,所以,“四”字头比较吓人,就用了,当然还有一个作用就是对没听说过北伐第四军的敌人,有个第四军会让他们以为还有一二三军,也有吓敌的效果,之后井冈山会师后成立“中国工农红军第四军”,第二次国共合作成立“新四军”,再后来又有“四野”,都是这也道理。



TIME_WAIT状态
7月 30, 2007, 12:50 下午
Filed under: 技术体会

根据TCP协议,主动发起关闭的一方,会进入TIME_WAIT状态,持续2*MSL(Max Segment Lifetime),缺省为240秒,在这个post中简洁的介绍了为什么需要这个状态。

值得一说的是,对于基于TCP的HTTP协议,关闭TCP连接的是Server端,这样,Server端会进入TIME_WAIT状态,可想而知,对于访问量大的Web Server,会存在大量的TIME_WAIT状态,假如server一秒钟接收1000个请求,那么就会积压240*1000=240,000个TIME_WAIT的记录,维护这些状态给Server带来负担。当然现代操作系统都会用快速的查找算法来管理这些TIME_WAIT,所以对于新的TCP连接请求,判断是否hit中一个TIME_WAIT不会太费时间,但是有这么多状态要维护总是不好。

HTTP协议1.1版规定default行为是Keep-Alive,也就是会重用TCP连接传输多个request/response,一个主要原因就是发现了这个问题。还有一个方法减缓TIME_WAIT压力就是把系统的2*MSL时间减少,因为240秒的时间实在是忒长了点,对于Windows,修改注册表,在HKEY_LOCAL_MACHINE SYSTEMCurrentControlSetServices TcpipParameters上添加一个DWORD类型的值TcpTimedWaitDelay,一般认为不要少于60,不然可能会有麻烦。

对于大型的服务,一台server搞不定,需要一个LB(Load Balancer)把流量分配到若干后端服务器上,如果这个LB是以NAT方式工作的话,可能会带来问题。假如所有从LB到后端Server的IP包的source address都是一样的(LB的对内地址),那么LB到后端Server的TCP连接会受限制,因为频繁的TCP连接建立和关闭,会在server上留下TIME_WAIT状态,而且这些状态对应的remote address都是LB的,LB的source port撑死也就60000多个(2^16=65536,1~1023是保留端口,还有一些其他端口缺省也不会用),每个LB上的端口一旦进入Server的TIME_WAIT黑名单,就有240秒不能再用来建立和Server的连接,这样LB和Server最多也就能支持300个左右的连接。如果没有LB,不会有这个问题,因为这样server看到的remote address是internet上广阔无垠的集合,对每个address,60000多个port实在是够用了。

一开始我觉得用上LB会很大程度上限制TCP的连接数,但是实验表明没这回事,LB后面的一台Windows Server 2003每秒处理请求数照样达到了600个,难道TIME_WAIT状态没起作用?用Net Monitor和netstat观察后发现,Server和LB的XXXX端口之间的连接进入TIME_WAIT状态后,再来一个LB的XXXX端口的SYN包,Server照样接收处理了,而是想像的那样被drop掉了。翻书,从书堆里面找出覆满尘土的大学时代买的《UNIX Network Programming, Volume 1, Second Edition: Networking APIs: Sockets and XTI》,中间提到一句,对于BSD-derived实现,只要SYN的sequence number比上一次关闭时的最大sequence number还要大,那么TIME_WAIT状态一样接受这个SYN,难不成Windows也算BSD-derived?有了这点线索和关键字(BSD),找到这个post,在NT4.0的时候,还是和BSD-derived不一样的,不过Windows Server 2003已经是NT5.2了,也许有点差别了。

做个试验,用Socket API编一个Client端,每次都Bind到本地一个端口比如2345,重复的建立TCP连接往一个Server发送Keep-Alive=false的HTTP请求,Windows的实现让sequence number不断的增长,所以虽然Server对于Client的2345端口连接保持TIME_WAIT状态,但是总是能够接受新的请求,不会拒绝。那如果SYN的Sequence Number变小会怎么样呢?同样用Socket API,不过这次用Raw IP,发送一个小sequence number的SYN包过去,Net Monitor里面看到,这个SYN被Server接收后如泥牛如海,一点反应没有,被drop掉了。

按照书上的说法,BSD-derived和Windows Server 2003的做法有安全隐患,不过至少这样至少不会出现TIME_WAIT阻止TCP请求的问题,当然,客户端要配合,保证不同TCP连接的sequence number要上涨不要下降。

 

 



伊拉克夺冠:我眼热
7月 30, 2007, 1:24 上午
Filed under: 八卦杂谈

一个有13亿人和谐社会的国家的代表队连小组都出不了线,一个风雨飘摇民不聊生的国家的代表队居然夺冠了,都是爷们,差别怎么就这么大呢?

别管国内环境有多乱,对手有多强大,差旅费有多不足,上了场就不要找借口,和豁出去和对手拼了,这才是纯爷们!

乌代泉下有知,也该瞑目了。



军博
7月 29, 2007, 9:43 上午
Filed under: 山河好大

周六去了趟军博看建军80周年展览,免费,希望以后这样的爱国主义教育都能够免费,看去的人有多少就知道人民群众的热情有多高了。

100_1579

这就是国产的“悍马”了。

100_1582

感觉拿出来展览的军火还是太少,而且不知道为什么没有型号的介绍。

100_1586

室内部分大多数都是照片,第一张是小平同志,不是毛泽东同志。

100_1589

开国十位元帅,没有隐晦把林彪去掉。

100_1590

毛主席用过的“五六”式半自动步枪,我军训的时候也用同样型号的枪放过五颗子弹,全部脱靶:)

100_1596

可惜相机电池用完了,没拍到军队现代化建设部分的照片,有一张西沙永兴岛的照片,上面显示我军建设了机场,此图在网上见过,但有人说是PS的结果,该岛并没有建立机场,在军博也见到这张照片,应该是属实。

yongxing_dao4



ThreadAbortException
7月 24, 2007, 5:16 上午
Filed under: 技术体会

最近要处理一个关于ThreadAbortException的问题,无意中发现.NET CLR在自动re-throw这个Exception的时候和倡导的re-throw方法不一致。

在C#的catch block中,如果需要re-throw抓住的Exception,不要用"throw ex;"(ex是catch(XXXException ex)中定义的变量名),因为这样外面接着catch住这个Exception,StackTrace显示的是"throw ex;"语句的位置,而真正Exception的源头就丢掉了,Bad,Bad,Bad! 但是如果直接用"throw;",不要接"ex",就解决这个问题了,StackTrace没有丢。

再说ThreadAbortException,这是一个asynchronous exception,也就是说可能在任何一个位置上出现,这样很容易乱套,所以理论上,当一个线程运行在finally block或者通过interop运行在native code上的时候,即使被Thread.Abort()了,也不会立即抛出ThreadAbortException,只有等走出finally block或者native code的时候,才会“砰”地抛出这个exception。但是,在.NET 1.1的时候,有点小bug,实际还是有可能在finally block中抛出ThreadAbortException的,2.0版的时候这个bug被fix了。

即使ThreadAbortException被catch住,不写一行code来re-throw,CLR也会在catch block结尾把它throw出去的,为什么呢?因为.Net中一个AppDomain被Unload的时候,其中的Thread都会被Abort,AppDomain通常被用来实现plugin,也就是说可能是第三方的代码,对于写的不怎么样的code,会用一个巨大的try-catch把ThreadAbortException抓住,不作处理,继续运行,这样host AppDomain就不会按时Unload了,当然不能容许这样的事情发生,所以,CLR对于ThreadAbortException,别管你不catch住throw不throw,运行到catch block结尾,都会自动把ThreadAbortException给throw出来。这样又有一个问题,总不能让ThreadAbortException一直往外抛把这个进程能弄死了啊,所以好需要一个Thread.ResetAbort()来打住ThreadAbortException,但是这样malicious code也会用这个Thread.ResetAbort(),所以,这个函数只有一定权限的AppDomain才能调用,不让plugin有这个权限就好了,嘘~,这个问题终于解决了。不过这招只能访君子不能防小人,如果code中就是catch ThreadAbortException,然后就在catch block里面或者finally block里面继续做坏事,比如就是耗时不退出,一样没有办法,对这种情况只好用rude thread abort。

话说回来,ThreadAbortException总是被re-throw,但是re-throw的方法和C#建议的throw方法不一致,如果让CLR自动throw,实际上是丢失StackTrace的,不知道CLR为什么这样做,是疏忽还是by design?不得而知,但是我们在code的时候,如果希望保留Stacktrace,只好显示的re-throw了:

try
{

   ……  
}
catch (ThreadAbortException ex)
{
    ……
    throw;
}



software = 1% inspiration + 99% detective
7月 23, 2007, 2:19 上午
Filed under: 工作心情

周末看一本叫《Hackers & Painters》的书,作者Paul Graham是个大牛,在第一章<Why Nerds Are Unpopular>中,充分说明了为什么喜欢钻研的Nerds在美国secondary school中不会popular,因为要popular也是要付出努力的,虽然popular的小孩自己可能也没有意识到,需要穿好衣服,开好车,出风头,Nerds不是不想popular,而是他们喜欢钻研的东西使得他们没精力去变得popular。我感觉作者说的过于充分,以至于怀疑作者少年的Nerd身份给他留了很深的心理阴影,所以借写这本书发泄一下:) 第一章继续抨击了美国的教育制度,认为学校就和牢房一样,唯一的作用就是把小孩圈起来不要到处乱跑,作者很是神往文艺复兴时代,年轻人十几岁就开始做学徒,真正接触社会和将来要从使得工作,而不是坐在学校里学一些将来注定要忘掉的东西。

这让我有点吃惊,原来美国的中学也是这个样子的啊,我以为中国特色的学校才会是这样:中学学的东西大多数真的后来没什么用,唯一的目的就是考个高分进入大学,家长老师们也知道这种制度有问题,但是没办法,要获得学有用的东西的资格,就得先学没用的,证明给大学看自己学习的能力好歹不差;当进入大学之后,就发现大学教育真的不是中学教育的延续,还有点不适应;大学毕业加入工作之后,发现大学也没学什么能用上的东西,这时候需要用那句“大学不是较你知识,而是较你学习的方法”来对付一下。

不过第一章的道理还是很清楚,很少有天生我才这回事,变得popular或者成为nerd都是需要付出的,而且越出色需要付出的越多。

看完第一章有点累,换本书看,这本叫《Dreaming in Code》,这本书看名字就会知道会揭露软件开发的内在问题,第一章(其实是第零章,这本书的章回从0开始编号)看到一句话:“Their work is one percent inspiration, the rest sweat-drenched detective work; their products are never finished or perfect, just varying degrees of ‘less broken’ ",真是一语道破天机,干这行大部分时间都是在fix自己或者别人创造的bug,当然有的detective工作也很有乐趣。这话让我想起我坐在中学教室里面,墙上挂着各个榜样人物的名言,其中就有爱迪生的“天才是百分之九十九的汗水加百分之一的灵感”,这话被我们写励志作文的时候引用无数次了,不过若干年后我才知道,这句话后面的那句关键的话被人无情而且无耻的删掉了“但有时那百分之一的灵感比那百分之九十九的汗水还要重要”,某些人就是希望小孩子傻傻的被圈着,我可不希望我的孩子会被这样处理。



一支球队窝囊一次不难,难的是一辈子只窝囊,不争气
7月 19, 2007, 1:21 上午
Filed under: 八卦杂谈
没话说了。


刺马
7月 17, 2007, 1:38 上午
Filed under: 电影电视

上周六去看《变形金刚》的时候,放映之前看了几个预告篇,有翻拍当年张彻《刺马》的《投名状》,还有一个《天堂口》我第一次听说,英文名叫Blood Brothers,从预告片可以看得出来,多多少少还是沿用了《刺马》的情节。不得不感慨,经典的故事就是经典,刺马的情节被翻拍N多次。

清同治九年(1870年)7月26日,两江总督马新贻被一个名为张汶祥的刺客所杀,此案案情错综复杂,成为清末四大奇案之一。基本情节:A(马新贻),B,C(张汶祥)是异姓兄弟,贫苦时能共患难,但是一个机会,A因为银子或者女人害死了B,而且飞黄腾达过的很滋润,C大怒,刺杀了A。情节骨干就这么简单,但是血肉可有得发挥了。

吴宇森自己开的电影公司只拍过一部电影,《喋血街头》,情节上糅合了《刺马》和《猎鹿人》;把抄袭当创作的王晶,监制的古装艳情片《满清十大酷刑之赤裸凌迟》也几乎就是刺马的翻版;不过最经典的,还是张彻的《刺马》。

周末弄了老版的《刺马》看了看,要论场面,当时的制作水平和今天当然不可同日而语,但是还是值得一看,主角狄龙(还记得《英雄本色》里面的豪哥吗?)饰演的马新贻,的确很到位,但是似乎电影没留下多少空间渲染三兄弟当年如何同生共死肝胆相照,从《投名状》预告片中三人杀人为盟,在乱军之中困兽犹斗的场面看,估计《投》这一点会比老版《刺》做的好。2007年12月才上映,还有得等待。



变形金刚,我觉得很烂
7月 14, 2007, 10:16 上午
Filed under: 电影电视
上午去看了《变形金刚》,说说感觉:很烂!

要说缺点,什么机器人形象较原版动画改变过大、剧情弱智、打斗过于恍眼睛等等,在BBS上都被说烂了,我就不多说,只说讲故事的能力。导演4迈克尔.贝是拍MTV起家,据说他四五岁的时候就用玩具排演外星人入侵,结果差点把自家房子给烧了,后来拍动作片也颇有成绩(票房成绩),比如《珍珠港》,但是个人觉得此人处理细节和大场面还有点功夫,能够把场面拍出来,但是讲故事的能力实在一般,协调各方面拍摄制作一个大场面是一个技术问题,把这个大场面融入到电影之中就是艺术问题,迈克尔.贝能做好前者,后者就看不到什么作为。不管某个场景有多酷,如果不能为整个电影服务,就显得多余,大决战部分,每个独立的战斗镜头拿来当MTV片断都没有问题,但是组合在一起就显得相当混乱。



“是这样子的”
7月 11, 2007, 9:16 上午
Filed under: 八卦杂谈

发现一个现象,你问服务业的人员一个问题,他/她们喜欢先说一句:“是这样子的”,然后才是回答。今天打电话给银行客服,每问一个问题,接线小姐地回答都是遵循这样的模式:“是这样子的,XXXXXX”。

这句开场白有一个好处,就是先稳定听者的情绪,然后再娓娓道来,如果上来就给一个斩钉截铁的回答,显得很突兀生硬。

体会一下:

“请问我的信用卡自动还款为什么没有生效?”

“是这样子的,自动还款只有付款的账户里面有足够的资金才会发生。”

“我的付款账户里肯定有足够的钱。”

“请稍等……是这样子的,您上个月没有信用卡消费,所以没有没有自动还款。”

把这句去掉,就感觉和开War Meeting一样:)

“请问我的信用卡自动还款为什么没有生效?”

“自动还款只有付款的账户里面有足够的资金才会发生。”

“我的付款账户里肯定有足够的钱。”

“请稍等……您上个月没有信用卡消费,所以没有没有自动还款。”