2011-04-22 59 views
11

目前與我建立一個HTTP服務器上的實驗支持保持活動插座。服務器由一個監聽線程使用select(...)和四個由線程池管理的工作線程進行多線程處理。目前,我正在Core I3 330M上管理大約每秒14k-16k的請求,文檔長度爲70字節,響應時間爲6-10ms。但是這沒有保持活力,並且在工作完成時我立即關閉了所有的套接字。問題一個土生土長的HTTP服務器

編輯:工作線程處理'作業',當檢測到套接字上的活動時調度,服務請求。 「工作」完成後,如果沒有更多的「工作」,我們會睡覺,直到更多的「工作」被派出,或者如果已經有一些工作可用,我們開始處理其中的一個。當我開始嘗試實施保活的支持

我的問題開始。隨着保持活動激活,我只能用100個開放式套接字管理每秒1.5k-2.2k的請求。這個數字通過1000個開放式插座增長到12k左右。在這兩種情況下,響應時間都在60-90毫秒左右。我覺得這很奇怪,因爲我目前的假設認爲請求應該升高而不是降低,並且響應時間應該有望下降,但絕對不會升高。

我試過幾種不同的策略以固定低性能:

    1.呼叫選擇(...)/ PSELECT(...)有超時值,以便我們能夠重建我們FD_SET結構和聽到我們阻止後到達的任何其他套接字,併爲檢測到的套接字活動提供服務。 (除了性能低,這裏還有插座的問題被關閉,而我們封鎖,導致選擇(...)/ PSELECT(...)報告壞的文件描述符。)
    2.有一個監聽線程只接受新的連接和一個保持活動狀態的線程,通過管道通知我們阻塞之後到達的任何新套接字以及任何新的套接字活動,並重建FD_SET。 (與'1'相同的附加問題)。
    3.選擇(...)/ PSELECT(...)以超時,當新的工作是必須要做的,分離爲具有活性的插座的鏈接列表條目,並將其添加回的請求時已經提供服務。重建FD_SET希望會更快。這樣我們也避免試圖聽任何不好的文件描述符。
    4.合併(2.)和(3.)。

    - 。可能還有幾個,但他們逃脫我。

保活套接字存儲在一個簡單的鏈接列表中,其添加/刪除方法被pthread_mutex鎖包圍,負責重建FD_SET的功能也具有此鎖。

我懷疑它是在這裏的主要元兇互斥的不斷鎖定/解鎖,我試着來分析這個問題,但沒有gprof的還是谷歌perftools一直非常合作,無論是引入極端不穩定或純拒不收集所有數據(這可能是我不知道如何正確使用這些工具)。但是移除鎖可能會使鏈表處於非正常狀態並可能崩潰或將程序置於無限循環中。 我也懷疑選擇(...)/ pselect(...)超時,但我很確信這不是問題,因爲即使沒有它,低性能也會保持。

我在我應該如何處理保持活動插座一個損失,我爲此想,如果你人在那裏有關於如何解決低性能或有任何建議,任何其他方法我可以使用任何建議去支持保持活着的插座。

  • 如果您需要更多的信息,以便能夠正確回答我的問題,不要猶豫,問它,我將盡我所能,爲你提供必要的信息,並與這個新的信息更新的問題。
+0

爲了分析,你可以使用'oprofile',它應該比'gprof'少一些侵入性。 – ninjalj 2011-04-26 20:15:26

+0

你可以發佈執行鎖定的代碼嗎?你保護什麼樣的數據結構(鏈接列表?)以及該數據結構上的哪些操作受到鎖保護(添加/刪除?)或什麼? – johnnycrash 2011-04-27 01:49:36

+0

我使用C開發的Web服務器「GoAhead」,並根據需要進行修改。你可以使用它作爲參考。 – AjayR 2011-04-27 05:10:40

回答

0

當客戶端使用您的套接字多於一個請求時,時間增加將更明顯。如果你只是打開和關閉,但仍然告訴客戶保持活力,那麼你的情況與沒有保持活動時一樣。但是現在你有插座的開銷。

如果無論您是從同一客戶端多次使用套接字多次請求,那麼您將失去TCP連接開銷並以此方式獲得性能。

確保您的客戶端正確使用keepalive。並且可能是更好的方式來獲取套接字狀態和數據的通知。也許是輪詢設備或排隊請求。

http://www.techrepublic.com/article/using-the-select-and-poll-methods/1044098

這個頁面有針對Linux,以處理調查設備的修補程序。也許一些理解它的工作原理,你可以在你的應用程序中使用相同的技術,而不是依賴可能未安裝的設備。

6

試着完全擺脫選擇。您可以在每個流行的平臺上找到某種事件通知:freebsd()上的kqueue/kevent,Linux上的epoll等。這樣您就不需要重新生成FD_SET,並且可以隨時添加/刪除觀看的fds。

+2

+1。選擇是可怕的。另外,請看'libevent'和/或Boost.ASIO - 這些庫正在使用平臺特定的機制。你可以依靠它們或者至少將它們用作參考。 – 2011-05-03 13:50:45

0

有很多選擇:

  • 使用過程中,而不是線程,並通過Unix套接字傳遞文件描述符。
  • 維護套接字的每個線程列表。您甚至可以直接在工作線程上使用accept()
  • 等...
0

是你的測試客戶端重用插座?他們正確處理保持活着? 我可以看到這種情況,只要傳遞keep alive頭文件,就可以在基準代碼中儘可能做最小的改變,但不會更改代碼,以便在收到付費數據包後客戶端的套接字就會關閉。 這將承擔保持活力的所有成本,沒有任何好處。