July 24th, 2008 by 张磊
最近我的blog频繁地遇到500错误,同在这服务器的几个导航站也遇到这问题。服务器上跑php用的是apache+fastcgi,到错误日志里看了看,发现是这样的:
FastCGI: comm with server “D:/AppServ/php5/php-cgi.exe” aborted: idle timeout (30 sec)
FastCGI: incomplete headers (0 bytes) received from server “D:/AppServ/php5/php-cgi.exe”
比较重要的是这里的“idle timeout”,等待已超时。这里的意思是fastcgi进程等待了30秒,依然没能从php解释器那里获得内容,所以反映在外面就是个500错误。
出现这个的原因往往是由于程序中有不少耗时的操作(比如不小心写了个死循环)——联想到我刚刚启用了一个WP插件@Feed,就去服务器上把这个插件的文件夹改了个名字,马上blog就恢复了。我使用自动升级的功能升级了一下@Feed插件,再次启用,就可以正常工作了。看来可能是以前的插件不能用于这个新版本的WP。
有人说,我在程序里使用“set_time_limit(0)”,可以让该脚本永远不超时,为啥还是出500呢?其实这里是两个概念。Fastcgi为啥叫fastcgi,它不能容忍进程长期不响应的处理。理想的fastcgi应该是一秒可以处理数十个操作(虽然是挨个处理,但看起来就像是并发的)。set_time_limit(0)只能告诉php解释器这段脚本可以永不超时地执行,但在fastcgi还是有30秒的限制,所以还会报错。
如果真的要进行大量耗时的操作,还是考虑一下使用命令行的PHP吧。
May 13th, 2008 by 张磊
昨天说了在Windows上面安装APC,我用Apache的ab.exe测试了一下之前和之后服务器生成页面的速度,提升确实很明显。但是很快遇到了问题:服务器经常出现500错误,网站怎么也打不开。
在日志里的错误信息是这样的:
[client 208.36.144.6] (OS 121)信号灯超时时间已到 : FastCGI: failed to connect to server “D:/AppServ/php5/php-cgi.exe”: CreateFile()/WaitNamedPipe() timed out
[Tue May 13 09:53:10 2008] [error] [client 208.36.144.6] FastCGI: incomplete headers (0 bytes) received from server “D:/AppServ/php5/php-cgi.exe”
搜了一下,没搜到解决办法。又是一个不眠之夜,今天早上只好把APC关掉,访问就正常了。想了一下,failed to connect to server的错误,可能是fastcgi进程因为APC需要不停地查询缓存、更新缓存、整理碎片而被拖慢了。这该如何解决呢?
May 12th, 2008 by 张磊
心血来潮去翻Fenng以前整理出来的大型网站们批露的架构方面的信息,看到的都是很典型的,基于ROR的财帮子(不晓得现在JavaEye流量大还是财帮子大),基于.net的“PlentyOfFish”,深藏不露的豆瓣以及非常平民化的facebook(用的是PHP+MySQL)。有点纳闷,这些网站怎么没一个用java的,虽然说是“Architecture Scale”,但看起来java确实不受待见阿。
翻到Facebook的时候注意到它用了Memcached和APC。Memcached我已经用在服务器上了,APC以前在Dreamhost时使用过,不过效果一般。这里谈到Facebook用APC使得“一个页面显示的时间从4000多毫秒降到了100多毫秒”,肯定不是所有用了APC的地方都能有这么大的提升,但是使用APC确实能为PHP加速。
由于PHP是个解释型语言,执行的时候先得把程序读进来,(进行基本的差错,)然后“解释”成机器可以跑的程序。解释就会生成Opcode,如果可以把这个Opcode缓存起来,下次就能避免重新解释了。想想一下很多大型的系统,一个页面会包含很多文件,所以把这些文件的opcode存储起来,效果有点像“片段缓存”。我所知道的可以做PHP中opcode缓存的除了APC还有XCache,今天就安装了APC在自己的服务器上。
借用下面这张图,应该能弄清楚APC的作用了。
网上有很多在linux服务器上安装APC的指导,其实作为PHP的扩展,在windows的安装大同小异。先去perl4win.php.net,搜索APC,就能找到可以下载的DLL文件。这时需要选择一个和服务器PHP版本相匹配的。我服务器上的PHP是5.2.3,就下载了最后一个DLL。
下载回来后放到PHP插件文件夹,一般是php目录下的”ext”文件夹。之后编辑php.ini,在末尾加入:
[apc]
extension=”php_apc.dll”
apc.enabled=1
apc.shm_segments=1
apc.shm_size=48
apc.ttl=7200
apc.user_ttl=7200
apc.num_files_hint=1024
apc.mmap_file_mask=d:/tmp/apc.XXXXXX
apc.enable_cli=1
其中apc.shm_size就是给APC开的缓存大小,单位是M。我之前开了16M,有点小,就改成了48M。保存php.ini之后重启apache,如果你有一个显示phpinfo()的网页,刷新就能看到安装完成的apc了。
如果想得到apc运行的更多信息,可以去下载一个APC源代码包,里面有一个apc.php,放在web目录下就可以看到APC运行的详细情况。见下面的图:
April 24th, 2008 by 张磊
在Windows上有个烦恼就是装类似于memcached、lighttpd这些好东西都得一番好找,最后像是做贼一样,终于在互联网的某个角落里找到了。
其实memcached Server我早就找到了,可是配套的PHP的memcached Client一直没找着。windows里不能像在linux那样config/make/make install就搞定,只能满世界地找dll。
坦白说现在做这些都是尝试。niupu的微薄流量对比起强悍的双核服务器,哪怕不用缓存也没啥问题,现在用文件系统缓存自然也可以。想把memcached拿来尝尝鲜,终于被我找到php_memcached.dll 。
把php_memcached.dll放在php的扩展文件夹,然后在C:\windows下打开php.ini,加入一行对php_memcached.dll的引用。重启apache,看看phpinfo()中有没有memcache,如果有,那就安装成功了。
我用Zend Framework中的Zend_Cache,使用默认配置,就可以连接memcached Server了。试试看,速度也没提升多少嘛。
December 6th, 2007 by 张磊
让人心痛的回忆,我浪费了将近1个小时,才明白自己程序里错在哪了。想起当年用Emeditor写程序的时候,折腾了一下午,发现少写个小括号。很久没有这么废了。
开发Camel的过程中,我把错误报告的级别设为了”E_ALL”。看到好多大牛都是这么做的,这样所有notice级别的错误都能暴露出来,更能一目了然。用了E_ALL,果然每个页面加载时都会跳几个“Notice”的错误出来,看多了也不当回事了。
然后今天尝试登录Camel后台,登录这一块是很久以前做的了。之前已经做过许多次登录,所以Camel登录这一块就没有做UnitTest。一看发现没法登录,我就慌了。仔细地检查了一下各个模块之间的逻辑关系,没找到毛病,只好一点一点地修改、调试,可一直都不对。Cookie没法成功发送,自然也去不了后台。到后来甚至让我对我自己装的PHP产生了怀疑,可我的PHP是直接更新自apt源的。我好好规划的模块化程度这么高的Camel,在被我七手八脚调试的过程中,弄得七零八落了。
万念俱灰的时候,突然注意到在我不当回事的“Notice”中,有一个“Warning”。内容是:
Cannot modify header information – headers already sent by (output started at /var/www/camel/v/admin/Utlities.php:9)
一拍脑袋,我怎么没早发现呢?之所以服务器不能发送Cookie,是因为服务器为了输出那些“Notice”们,就打开了输出流,于是就没法发送header信息。而Cookie是包含在header中的。学着那些牛人们整了个E_ALL,结果把自己给害了。如果你做事和我一样没心没肺,还是别用E_ALL了,极端一点的话用一句error_report(0),关掉所有的错误报告,世界更干净。
November 7th, 2007 by 张磊
终于开始做事了。睡午觉时在考虑Camel的用户后台,想到里面零碎地有很多种数据,有点头大。于是打算用一个框架抽象一下,就像ROR那样,可以自动把表转化成对象。
PHP下面这样的框架很多,Cake/Flea等都可以做到。可是在项目里再引入这些框架实在显得太臃肿,还可能被他们绑住手脚。我一下就大胆起来,要不自己写一个吧。说做就做,起床花几个小时写了一个粗糙的框架,我先把它叫做CF(Camel Framework)。主体就是一个抽象类,可以自动侦测表结构,然后提供一些常用操作的函数。不支持ROR里那些复杂的东西。
程序只有70行(写得太快就没写注释),进行了些简单的测试还比较满意,因为太粗糙了就不放出来了。将来的Camel里数据操作必然会用到这个精巧的CF,面对再多样的数据也不会发愁了——也许还能在未来的其他项目中用到CF呢。
不过据说CF写好,某人会有奖励哎 。
August 30th, 2007 by 张磊
今天在做Camel的时候,对ZF中的Cache的一些初始化选项觉得有些疑惑,于是找来了官方的文档看了看。不看不知道,一看之下才发觉自己之前对ZendCache的使用简直太浅薄了。现在的ZendCache可以对页面某一部分做Cache,也可以对整个页面进行Cache,Cache的保存方式也多种多样,真的很强大。之前我自己对Cache的思考,和他们所做的工作比起来,可以说是微不足道了。
所以牛扑还需要更大的改动。今天我一度动摇,想用Python来重写牛扑,但很快就打消了这个念头。牛扑的架构需要进行更改,我打算大量地使用ZF框架中的组件。这个假期还有些遗憾就是,没有把足够的时间花在看Lucene上。智勇说牛扑啥都搜不出来,这是因为没用全文检索阿。记得那时Tiny还说要送我一个他们在这方面的产品,可那我也得会用阿。
不过,现在做Web开发会觉得顺手很多,因为网络上流行的框架有一大堆,总能找到适合你的一款。若不,说明你已经高超到该自己去写框架了。牛扑几乎所有的方面都需要改进,用户界面、全文检索、缓存算法、数据库结构……回头看自己之前的项目总会觉得千疮百孔。不过,一个一个来吧,我打算把这个拿来做我的毕业设计。
晚上还花了十来分钟,给机器人在互联网的某个角落,安了一个小小的开关。以后机器人掉线,就不需要爬上服务器去改了。只要对那个开关说一个暗语,机器人就会被重新打开。想着你说机器人不见了时可爱的表情,我忍不住就把这个秘密泄漏给了你。
August 30th, 2007 by 张磊
最近在忙着做一个叫Camel的项目,用上GTD之后,我也把项目的进程放到了里面,这样可以被监督着。Camel是用来做一个提供建站服务的东西,可以让用户轻易地搭建一个功能齐全的网站。同时我也想对现有的一些同类的程序做些改进,看看他们的数据库和页面,做的实在不让人满意。
从技术上,我觉得我可以从中学到很多。开始在web程序中试用面向对象,是从牛扑开始的(Project ZLLP)。但独立地大规模地使用对象,是在期末软件实习里面做的在线购物车(Project OLBK),老师看完我做的东西之后,说可以拿来当毕业设计了,顺理成章地拿了优──实际上我只做了7、8天的样子。而现在我正在做的Camel 里面,一切都是对象。
当接到一个HTTP请求,服务器上会用.htaccess文件将所有的都请求重定向(不是301或302,而是Rewrite)到一个叫做page.php的文件,当然,带着不同的GET参数。page.php中会初始化一个Site对象,这个对象里除了一些必要的内部变量,还包含了缓存对象、数据库对象、smarttemplate对象,以及我自己写的字典对象、语言包对象、分页对象、校验对象等等。所有的任务都在Site内部完成,然后通过smarttemplate显示出来。现在,这样的一个骨架已经完成了。
后台管理我也打算采用类似的方式,不过还没有进行设计,相对来说可能要花更多的精力。
很久以前读了Babel的程序,感叹Livid的才华。用完全的面向对象写一个社区程序,之前的人们也许想都没有想过。最大的那个文件有几百K──想像一下,全部手写的程序,几百K实在是庞然大物了。而Babel的设计思想至少影响了我的3个项目,虽然,和babel的差距还很远。
2005年我刚上大学时17岁,85年出生的Livid20岁。明年即将满20的我,不知道能学到Livid的几分。而Livid更打动我的是那种轻松闲适的生活态度,同样是85年,有的人让我顶礼膜拜,有的人在我心里还是小女孩。
June 7th, 2007 by 张磊
最近在研究PHP中的缓存,在牛扑上一个简单的图书信息页面(比如这个)都要进行至少9次数据库查询,而其中大部分东西都是在相当长一段时间不会变的,所以把这些内容缓存出来是很必要的。其实现在的牛扑一部分内容是有缓存的,当然效果很好,但缓存没有大规模使用,会限制整站的速度。于是我开始找一种通用的缓存机制,果然被我找到了,那就是ZF中的Zend_Cache。
其实缓存的概念在很多地方都有,CPU中有一级缓存二级缓存,缓存的存在大大提高了信息交换的速度(当然,和命中率有关),其实是一种空间换时间的办法。空间换时间的思路在编程中也有,特别是在做ACM时,对解法要求的效率很高,这些时候“空间换时间”的思想往往会对解题有很大帮助。
Zend_Cache是包含在ZendFramework中的,我查看了一下官方文档,发现介绍的比较简单。后来找到了Babel的程序,才看到了实例。V2EXCore.php中有这样一段:
if ($o = $this->cs->get(‘babel_top_wealth’) && $cached) {
echo $o;
} else {
ob_start();
/*output sth.*/
$o = ob_get_contents();
ob_end_clean();
$this->cs->save($o, ‘babel_top_wealth’);
echo $o;
}
其中$this->cs是一个初始化好的缓存类。在这里,思路是这样,如果缓存”babel_top_wealth”命中,就输出,如果没有命中,就通过ob_start()/ob_get_contents()获得输出的内容,然后保存到缓存。坦白说,这个比我以前自己写的缓存类好使多了。
现在唯一的问题是,缓存很多的话查找也是一个问题。牛扑上的50W本书假如有10W本进入缓存,估计需要的空间在1G左右。这个时候,到底是数据库的速度快呢,还是利用程序的逻辑从磁盘上读的速度快呢?
May 20th, 2007 by 张磊
洗了一个澡清醒一点,赶紧写篇blog吧,要不关心我的朋友们还以为我出车祸挂了呢。
谈一下这几天的生活。这里的四天,说的是这周星期三一直到星期六这段时间。周二晚上加班,一直到了周三3点半才上去睡。很快,7点半起床去上课,躺在床上的时间一共只有4个小时。
周四要到上海比赛了,所以周三晚上和SIFE的弟兄们排练到十来点回来等到十二点左右就睡了,但是这也没睡多久,早上6点整就起来开始收拾,准备赶去上海的火车。火车上也没歇着,在那边排练话剧一样的练我们的Presantation。
这个时候虽然连续两天都睡得很少,但也没觉得有多累。真正累的是11点多到了上海之后,我穿着硬底的皮鞋,正好左脚在周二踢球时磨破了。实在痛苦,而且到了KPMG的OFFICE里面根本没有坐下的机会。匆匆忙忙底准备、紧紧张张比赛,然后是颁奖──这些完了之后就19点了,估摸着回不去杭州了。
其实我挺不想回去杭州的,因为如果我们九个人不回去的话,会有一个上海师范大学的漂亮MM和我们一起吃饭(后来吃完才知道,这个MM不光是上海师大的学生,也是上海市委党校的学生,牛啊……)。我的小小阴谋得逞,我们吃饭到9点。之后的三个小时,我们奔波在上海的街头,一边高声唱歌,一边在找落脚的地方。3 hours walking,还穿着双硬底皮鞋,可以想想多恐怖。后来终于找到宾馆了,9个人开了一间房,有男有女,过了一个有意思的晚上。
我是在第二天凌晨两点多快三点的时候睡的。我最后一个洗澡,出来之后大家已经都睡着了。我慢吞吞地烧了开水,喝了两大杯之后这才去睡。不过很快就天亮了,6点钟好几个手机的闹钟都开始响,冤枉的是我的手机没上闹钟,我却成了唯一被闹钟叫醒的人。中间估计只睡了三个钟头多一点。
睡三个钟头,脚已经不痛了,歇过来了。然后我们从旅馆朝上海南站走。我突然意识到我第一次来上海的时候到过这里,蜗牛MM还请我吃过一顿很好吃的饭。那是去年10月的事了。去年10月之前我虽然已经是大二的学生,但不用说上海了,连杭州市区也只去过3、4次。 但自从10月在浙大见到了Jennifer,我开始接触了一大批顶尖的同学,也开始习惯于经常往上海或是浙大跑的生活。真快啊,这半年之中我出去过多少次呢?
我们到了南站,买到了9点36的火车,车上我和SIFE里面负责财物的MM聊了一路,爽啊。可惜的是拿这一个半小时来睡一下我肯定会更开心。到了杭州已经是11点40。我下午还和Jennifer约好参加GC的party呢。 于是我马上坐525回到下沙,这时快1点了。我换掉了烦人的西装和硌脚的皮鞋,带着Alone很快出发了,不过还是迟到了。
GC的Party应该从来都不缺乏笑声,里面技术的高手们总给我可爱的感觉。游戏玩了很久,后来huony介绍了一下MrTech的新产品(我保个密先,回头详细介绍)。很快我又得知晚上有ASES的案例分析的活动,我和Alone心动了,反正也不急着回去,就先和Jennifer到了他们公司,骗了一顿饭,然后一起到了遥远的ZJG──这是我第二次来紫金港。
ASES的活动也是很有意思,细节不方便透露。我和Alone以及浙大一个06级的MM在我的鼓动下组了一支队伍,也来参加。本来我是很阳痿地爬在那里,累的够呛了,因为早上只有3个小时的睡眠。后来也想干脆做观众。不过既然大家都来参加这活动,就也组一个队认真对待吧。我马上就来了精神──这点Alone可以作证。我们要做的是给以个产品置顶营销的策略,同时为它定价。我们队三个学的都是计算机方面东西,相比起来我知道的这方面东西可能多一点。我在自己的角度上队这个产品的营销做了陈述,虽然后面没有幸运地拿奖,我对自己的表现还是满意的。活动结束后,一些ZJU的学长主动来要我的名片,颇有成就感啊。
但是,我们忘记了时间。结束之后已经十点多了,怎么从紫金港回到下沙呢?这是一个问题。Alone拨了114,总算找到个办法。我们回到寝室的时候,已经快0点了。我这一天在外面奔波,连电脑都没开过,于是开了电脑处理邮件。这一弄就到了一点多。感谢Fenng大哥,帮我要来一张阿里巴巴网络工程师侠客行大会的门票,大会是在周六上午开始。我一点多睡觉,然后早上六点起来,准备去做公交到市里(虽然很辛苦,但从来也没抱怨过怎么到下沙了)。下了公交车又走了20多分钟,终于到了传说中的人民大会堂了。
上午的两场专题演讲都是英文的,PHP之父Rasmus以及另一位Yahoo资深的工程师。我周围的朋友都在用同声翻译的装置,但我发现自己居然可以直接听懂,不禁对我的英文水平有了全新的认识。下午比较累,头疼(我很少头疼的)。但还是坚持听完了,花了半个小时走到公交站,站着回来下沙,现在是星期天的凌晨了,前一天的晚饭还没吃。
这4天里我加起来睡的不超过20小时,但是大部分时间还是能保持清醒的头脑和充沛的精力。我在火车上感觉会睡着的时候,就很努力地和旁边的人说话,因为我感觉万一睡着,想再变得清醒就不容易了。
这是我生命里最稠密的四天时间。想好好休息、放松下了。周日的侠客行大会就不过去了。今天大部分链接也没有加,见谅。