2012-09-10 63 views
1

我們有一個使用select()設計的web服務器,直到上週才真正看到很多負載,並且始終用於爲我們的500-1000 conn/s負載正常工作。然而,我們最近開始看到更高的負載(和尖峯),並在看到套接字句柄> FD_SETSIZE後遇到了select()發瘋的問題。如果在FD_SET中有任何> FD_SETSIZE,那麼在重複超時後,select會進入一個不可破壞的循環,從而凍結服務器。切換到poll(或epoll)的選項現在不存在,我們必須堅持select。我現在修復它的方式是增加監聽隊列,並在我看到新的accept()返回爲> = FD_SETSIZE並返回到偵聽套接字的select()時停止接受新連接。這是可行的,因爲操作系統回收文件句柄,並總是嘗試提供最小的可用文件句柄。但缺點是,如果套接字句柄> = FD_SETSIZE,則在調用accept()時最終將RST發送到某些連接。現在仍然可以接受,因爲它使服務器保持運行並且連接數降低了〜5%。有沒有辦法可以做到這一點,而不會丟棄這些連接。我不想保留所有使用的手柄和使它太複雜的事情。創建一個假套接字,檢查它的句柄並在調用accept之前關閉它將會非常準確地估計下一個句柄os會給我什麼。在選擇時處理FD_SETSIZE

while(max_conn_to_accept--){ 
SOCKET a_s = accept(..); 
if(a_s >= FD_SETSIZE){ 
    close(a_s); 
    return; 
} 
+1

什麼平臺?您可能只能引發'FD_SETSIZE'。 –

+0

其centos 5.7,我尋找越來越FD_SETSIZE vut無法找到任何做它。 – user1444800

回答

1

只需提高FD_SETSIZE。在編譯器命令行中指定-DFD_SETSIZE=16384

我認爲你的版本已經足夠新,沒有其他問題。如果在頭文件中出現錯誤,則可能需要調整一兩行。

例如,如果你看到這樣的事情:

#undef __FD_SETSIZE 
#define __FD_SETSIZE 1024 

它改成這樣:

#undef __FD_SETSIZE 
#ifndef FD_SETSIZE 
#define __FD_SETSIZE 1024 
#else 
#define __FD_SETSIZE FD_SETSIZE 
#endif 

或者,如果您看到:

#define FD_SETSIZE  1024 

將其更改爲:

#ifndef FD_SETSIZE 
#define FD_SETSIZE  1024 
#endif 

但是,我認爲你不需要改變任何東西。

+0

這看起來像一個不錯的選擇,會試試看,謝謝大衛! – user1444800

+0

不幸的是,這隻適用於兼容BSD或SYSV的UNIX系統。尤其是它不能在不修改系統頭文件的情況下在Linux上運行...... –

+0

幸運的是,修改頭文件只需要幾秒鐘。 (雖然你確實需要root權限才能做到。) –