本帖最后由 中關(guān)村村草 于 2011-01-06 11:15 編輯
轉(zhuǎn):skandhas
WEBrick在局域網(wǎng)內(nèi)響應(yīng)慢的解決方案
前言
WEBrick是Ruby標(biāo)準(zhǔn)庫(kù)帶的一個(gè)HTTP服務(wù)器程序庫(kù)。WEBrick用來(lái)支撐小型的網(wǎng)絡(luò)應(yīng)用還是能勝任的。最近遇到了WEBrick在局域網(wǎng)內(nèi)響應(yīng)慢的問(wèn)題,經(jīng)過(guò)調(diào)查并解決了此問(wèn)題。下面是詳細(xì)過(guò)程。
運(yùn)行環(huán)境
Ruby1.9.2-p0,WinXP(SP3)
現(xiàn)象
公司的同事最近用Rails開(kāi)發(fā)了一個(gè)日?qǐng)?bào)系統(tǒng),由于使用人數(shù)不多且并發(fā)量并不大,打算直接用WEBRick就可以了。結(jié)果發(fā)現(xiàn)一個(gè)現(xiàn)象:WEBrick響應(yīng)特別慢,一個(gè)請(qǐng)求從開(kāi)始處理到結(jié)束,需要差不多30秒的時(shí)間,我無(wú)語(yǔ)!@#$%^& 。為了將問(wèn)題簡(jiǎn)單化,我寫(xiě)了個(gè)相當(dāng)簡(jiǎn)單的腳本來(lái)測(cè)試WEBrick:
Ruby代碼- require 'webrick'
-
- server = WEBrick::HTTPServer.new(
- {:Port => 3000, :DocumentRoot => 'C:/webroot'}
- )
- server.start
復(fù)制代碼 運(yùn)行腳本,然后用局域網(wǎng)的其他機(jī)器訪問(wèn)這個(gè)服務(wù)器,癥狀和上面是一樣的。
分析
在分析過(guò)程中有2個(gè)現(xiàn)象:
1.Ruby進(jìn)程的CPU占用率并不高,說(shuō)明并不是Ruby在進(jìn)行大量的運(yùn)算。
2.客戶端的請(qǐng)求到達(dá)WEBRick服務(wù)器是很快的。
經(jīng)過(guò)跟蹤和分析源碼,發(fā)現(xiàn)在“某些局域網(wǎng)環(huán)境” 中,套接字的peeraddr 方法會(huì)相當(dāng)耗時(shí), 如同阻塞一樣,大約15秒左右。WEBRick代碼中調(diào)用 peeraddr 的有兩處,這樣看來(lái),30秒的時(shí)間基本就花在這兩次調(diào)用上了。再進(jìn)一步分析發(fā)現(xiàn):peeraddr 真正慢的地方是在內(nèi)部獲取客戶端名稱(chēng) 的時(shí)候。
WEBRick調(diào)用peeraddr方法的兩處地方:
第一處:
文件 :server.rb 文件
方法 :GenericServer#start_thread
代碼 :addr = sock.peeraddr
第二處:
文件 :httprequest.rb
方法 :HTTPRequest#parse
代碼 : @ peeraddr = socket.respond_to?(:peeraddr) ? socket.peeraddr : []
解決方案
知道了原因,修改方法就簡(jiǎn)單了。其實(shí),peeraddr是可以帶參數(shù)的,如果傳入:numeric ,則peeraddr 方法就不會(huì)去獲取客戶端名稱(chēng),而是直接用客戶端IP字符串來(lái)代替客戶端名稱(chēng) 。在實(shí)際應(yīng)用中,對(duì)服務(wù)器來(lái)說(shuō),客戶端名稱(chēng)并不是十分重要,客戶端IP才是重要的。具體修改如下:
第一處修改 :
文件: server.rb 文件
方法: GenericServer#start_thread
修改:
addr = sock.peeraddr
改為:
addr = sock.peeraddr(:numeric )
第二處修改 :
文件: httprequest.rb
方法: HTTPRequest#parse
修改:
@peeraddr = socket.respond_to?(:peeraddr) ? socket.peeraddr : []
改為:
@peeraddr = socket.respond_to?(:peeraddr) ? socket.peeraddr(:numeric ) : []
結(jié)果
修改完之后,WEBrick在局域網(wǎng)內(nèi)的響應(yīng)速度立刻就提升上去了。 |