2012-05-30 30 views
3

我有我的服務器,它看起來像這樣上運行的守護進程的Ruby腳本:如何判斷我的Ruby服務器腳本是否被重載?

@server = TCPServer.open(61101)       
loop do             
    @thr = Thread.new(@server.accept) do |sock| 
    Thread.current[:myArrayOfHashes] = [] # hashes containing attributes of myObject 
    SystemTimer.timeout_after(5) do 
     Thread.current[:string] = sock.gets 
     sock.close 

     # parse the string and load the data into myArrayOfHashes 

     Myobject.transaction do   # Update the myObjects Table 
     Thread.current[:myArrayOfHashes].each do |h| 
      Thread.current[:newMyObject] = Myobject.new 
      # load up the new object with data 
      Thread.current[:newMyObject].save 
     end 
     end 

    end 
    end 
    @thr.join 
end 

該服務器接收併爲我的Rails應用程序是在Mac OS 10.6所有正在運行的管理數據。客戶端調用服務器上的15,每15分鐘,而我現在只有16級左右的客戶端,呼籲15每15分鐘,我想了解一下以下內容:

  1. 如果兩個客戶端在足夠接近調用同時,一個客戶端的連接嘗試失敗?
  2. 我怎麼知道我的服務器可以同時容納多少個客戶端連接?
  3. 如何監控我的服務器使用多少內存?

另外,有沒有一篇文章可以指向我討論實現這種服務器的最佳方式?我的意思是我可以有多個服務器實例在同一個端口上監聽嗎?這甚至會有幫助嗎?

我正在使用Bluepill來監視我的服務器守護進程。

+1

好奇:爲什麼要使用'Thread.new'如果你只是'join'它之後?這相當於'sock = @ server.accept',然後刪除所有對線程的引用。 – Ashe

+1

我想這個問題的真正答案是我可能不知道我在做什麼。我所知道的是,@ thr.join使所有事情都能夠可靠地開始工作。我會用足夠的中間代碼更新我的文章,以便能夠了解我在理解上存在的差距。 – pitachip

+0

如果你使用'Thread.new'而不是'join',那麼是的,如果你的代碼不是線程安全的,那可能會很奇怪。儘管如此,您更安全,但只是刪除所有'Thread'引用。像這樣:[http://pastebin.com/8m6CnbU4](http://pastebin.com/8m6CnbU4)。 – Ashe

回答

2

1和2
答案是否定的,連靠近對方不會使連接失敗兩個客戶端(連接可能會失敗,但是多個客戶端,見下文)。

原因是操作系統有一個默認所謂的監聽隊列內置於所有服務器插座。因此,即使您的程序中沒有足夠快地呼叫accept,操作系統仍會繼續爲您緩衝傳入連接。只要監聽隊列沒有被填滿,它將緩衝這些連接。

現在這個隊列的大小是多少?

在大多數情況下,通常使用的默認大小爲5.大小在創建套接字後設置,並在此套接字上調用listen(請參閱man page for listen here)。

紅寶石TCPSocket自動爲您調用listen,如果你看看在TCPSocket的C源代碼,你會發現,它確實將大小設置爲5:

https://github.com/ruby/ruby/blob/trunk/ext/socket/ipsocket.c#L108

SOMAXCONN被定義爲5瀏覽:

https://github.com/ruby/ruby/blob/trunk/ext/socket/mkconstants.rb#L693

現在,如果你不叫接受速度不夠快會發生什麼以及隊列中獲得並祝d? 答案是在的listen手冊頁找到:

積壓參數定義到掛起連接爲的sockfd隊列可能生長的最大長度。如果連接請求在隊列已滿時到達,客戶端可能會收到錯誤並顯示ECONNREFUSED,或者如果底層協議支持重新傳輸,則可能會忽略此請求,以便稍後重新嘗試連接時成功。

在你的代碼但是有一個問題,它可以使隊列填滿,如果超過5個客戶試圖同時連接:你在循環結束通話@thr.join

當你這樣做時有效的發生是你的服務器不會接受任何新的傳入連接,直到你的accept-thread中的所有東西完成執行。

因此,如果數據庫內容和其他內容在accept-thread中執行需要很長時間,那麼監聽隊列可能會在此期間填滿。這取決於您的處理需要多長時間,以及有多少客戶可能在同一時間連接。


你沒有說你正在運行在哪個平臺上,但在Linux/OSX的最簡單的方法是隻在您的控制檯上運行top。對於更高級的內存監控選項,你可能要檢查這些了:

ruby/ruby on rails memory leak detection
track application memory usage on heroku

+0

Hi Casper。所以當你問一個問題時,我會驚慌失措,然後意識到你不僅僅需要你的問題的答案,而且也不知道你在做什麼。好的#1我現在需要能夠同時容納大約80個連接。作爲一個臨時修復,所以我的服務器不會拒絕任何連接嘗試,而我找出一個更好的解決方案,對於我來說,將SOMAXCONN變量設置爲100是否可以? – pitachip

+0

@pitachip不,改變SOMAXCONN不是這裏的解決方案。我懷疑操作系統會讓你把它設置得如此之高。看起來你需要抽出時間閱讀一些線程。當你不明白你在做什麼時,你不能創建適當的程序。一種解決方案是讓你有一個線程,它所做的就是接受新的連接。然後,此線程觸發「子線程」來處理傳入的客戶端請求。你在添加'@ thr.join'之前所做的一切。但是,您需要首先正確理解線程安全性和共享變量。學習時間到! – Casper

+0

我可能誇大了我缺乏理解,因爲我傾向於:)。我已經閱讀了很多關於線程和線程安全性以及關於爲什麼線程在這個系統上不好的文章。我還沒有找到的解釋是建議一種實現「正確」的簡單多客戶端TCP服務器的方法。我上面提到的是很多人推薦的,目前正在工作,但顯然是非常不正確的。我是一個偉大的研究,並希望閱讀關於這個問題的權威材料。你能指出我在這方面的確切來源嗎?因爲谷歌在這種情況下似乎沒有幫助。 – pitachip

相關問題