友爱部停止服务原因分析——FastCGI模式下PHP可能因长进程中断服务

今天晚上发现无法打开友爱部的中文圈主页,就连桄欣结的博客站点也无法打开。翻墙之后重试,结果发现依然打开不能,看来不是因为GFW发力。于是用SSH远程登录服务器,检查系统资源使用状况,发现内存使用533MB,CPU占用12%,均属正常范围。又检查网络套接字状况,发现有20个到64.71.130.98的连接处于CLOSE_WAIT的状态,其他连接均在两个以下。看来也不是网络Socket连接数用尽的原因造成停止服务。重启lighttpd之后,发现服务恢复工作,但是大约过了五分钟,就无法刷新界面,一切和之前一模一样,浏览器提示正在连接,然后一直等到超时。进一步检查了Unix Socket状况,找到了根本原因:今晚twitter.com出现中断服务状况,部署在友爱部的twip软件耗尽了fastcgi的所有守护进程,所以PHP页面均无法打开。

这得从lighttpd和PHP的工作模式解释。PHP并没有为lighttpd这种服务器设计的独立模块,而是通过FastCGI接口实现的一种CGI方式的协作。lighttpd启动的时候会调用PHP的CGI模块,然后启动一个FastCGI进程,这个进程会根据配置文件中的描述,启动20个PHP解释器进程。然后lighttpd把所有以.php为后缀的请求都转发给FastCGI进程,后者则会自动选择一个空闲的PHP解释器进程来执行PHP程序。这种工作方式有点像Worker模式的服务器。本来PHP脚本的执行时间很短,这种多路复用的方式可以保证在最小进程创建、销毁开销之下执行PHP脚本,以提高响应速度。但是这种模式有一个漏洞,如果某个PHP脚本的执行时间不可控,在较高并发访问状况下,可能会出现所有PHP解释器进程均处于忙碌状态而无法使用的状况。这种状况一旦发生,会导致其他正常PHP脚本也无法执行,因为FastCGI不能分配任务,只好等待。而客户端的症状就是网站假死,客户端一直提示“正在连接”或者“正在等待响应”。

今晚的情况就是如此。友爱部的Twip是一个用CURL库转发Twitter请求的程序,它的执行时间受Twitter服务器工作状况影响,今晚赶上Twitter停止工作,于是大量CURL请求无法满足,处于等待Twitter响应状况。Twip的程序脚本耗尽了所有空闲的PHP解释器进程之后,网站上的其他PHP页面也就无法打开了。

目前我还没有想到解决这个问题的有效办法,毕竟所有PHP程序之间是共享FastCGI的,切换成Apache这样的服务器目前也不可能。降低配置文件中CURL请求超时时间是一个办法,但是不能从根本上解决问题。

Continue Reading

這個春節比較冷

春節期間一直沒有發文章,一來是因為天氣冷,不願意打字,二來是這個春節過得實在單調,沒什麽特別值得記錄的東西,再就是一些個人的瑣事已經寫進日記本,也沒有必要拿出來曬。

剛回家的時候很冷,下了飛機沒有脫去外套,全然沒有以往春節回家時渾身冒汗的感覺。這樣的天氣對於沒有暖氣的南方,自然還是躲在被窩裡寫寫畫畫,或者用手機上上QQ逛逛校內比較好。也有時候跑到外邊去跟朋友們聚聚,人多總算暖和一些,如果自己一個人在家,我實在不願意坐在電腦前面,頂著動的全無思想的大腦寫文章。

後來過年的那幾天終於還是暖和起來了,可以穿少少出門打球,也可以逛逛商場,或者同平日裡散在五湖四海的同學們喝茶看電影。走親戚串門本來也少不了,奈何跟我年齡相仿的小弟跑去當兵,回不來家。其他親戚全是長輩,也沒有什麽共同話題,每次見面問的最多的就是有對象沒有,面對這種問題總是頭大得很。每每同學出來碰頭,說起家長,大家都煩這個問題。更有推友分享:剛上大二的時候,鄰居家女同學結婚生娃了,媽媽教育道“千萬別學她,要以學業為重,不要談戀愛”;到了畢業工作,媽媽總是抱怨“妳看鄰居XXX,孩子都會打醬油了,妳還不快點,想當‘剩女’啊”。唉……成長的煩惱!

從回家那天起,老爸總不停旁敲側擊地試探,想給我介紹對象。開始我還裝傻,不做正面回答以免麻煩上身。終於有一天頂不過老爸的絮叨,乾脆挑明了直問,他才抖出消息,有個XX校長介紹的XX局長的女兒(聽到這複雜關係我已經暈掉)也在北京,中央財經大學畢業的(千萬別讓我找文科生啦,很難溝通的)……還說什麽就算不處對象,找個回家的伴也好。末了老爸丟下一句:你有無興趣給個準話,我好答覆人家。頓時我感到形同大赦,斬釘截鐵做出否定答覆,這下世界清靜了。不料自那天開始,老爸就不停旁敲側擊地試探,想瞭解我是否已經有女朋友。

婆婆媽媽這個詞語在我家行不通。喜歡逛商場買衣服的是我爸,喜歡在菜場討價還價的是我爸,家裡做飯的是我爸,喜歡嘮嘮叨叨說個不停的也是我爸。倒反我媽比較爽快,做事情條理清晰,雷厲風行。看來婆婆媽媽的性格是誰做飯誰養成,可以理解為柴米油鹽的燻陶。

放假前考慮要做一個團隊內部使用的任務管理系統,把軟件項目、結構、人員、工作任務整合起來。設想比較宏大,考慮了許多特性。用一句話概括基本上就是以時間線為消息交互平臺,以結構、團隊、計劃、缺陷為項目組織方式,以工作表為個人工作安排輔助工具的一個系統。在家期間只畫了一些支離破碎的介面草圖,設想了一些典型的Use Case。不過看圖就覺得這個東西很複雜,尤其是瀏覽器端的邏輯比較多,不可能用以前的開發方式實現。

飛到北京之後突然想明白了。CRUD式的開發已經不能使用,而應該讓服務器端服務化,瀏覽器端單元化。把服務器端設計成一堆Ajax的API,服務器腳本也不需要複雜的面向對象,只要檢查數據合法性并組合成SQL就好。瀏覽器端則把不同的功能分散在不同的單元中,然後用DIV構建介面框架,用JS分別實現具體功能。這樣作為入口的PHP腳本只負責寫一堆configuration,綁定到入口PHP的template負責介面框架的DIV構成,和加載必要單元的JS就好。單元化的JS腳本被加載之後,自動完成自己的初始化,用Ajax聯絡服務器腳本API實現具體功能。

考慮明白這一層,基本上整個構想都可以實現,用純Web技術實現RIA倒也不是癡人說夢。

Continue Reading