我有一個用C寫的守護進程,它需要同時處理20-150K的TCP連接。他們是長期運行的連接,並且很少拆卸下來。它們在任何給定的時間都有非常少量的數據(很少超過MTU,這是一種刺激/響應協議),但對它們的響應時間至關重要。我想知道當前的UNIX社區正在使用什麼來獲取大量套接字,並儘量減少響應時間。我已經看到設計圍繞多路複用連接到fork工作池,線程(每個連接),靜態大小的線程池。有什麼建議麼?如何在現代多核/多插口機器上擴展TCP偵聽器
回答
最簡單的建議是使用libevent,它可以很容易地編寫一個簡單的非阻塞單線程服務器,以符合您的要求。如果每個響應的處理需要一些時間,或者如果它使用某些阻塞API(如幾乎任何來自數據庫的任何內容),那麼您將需要一些線程。
一個答案是工作者線程,你在哪裏產生一組線程,每個線程都監聽一些隊列工作。如果你喜歡,它可以是單獨的進程,而不是線程。主要區別在於溝通機制告訴工作人員該做什麼。
一個不同的方法是使用多個線程,併爲它們中的每一個提供這些150K連接的一部分。每個人都將擁有自己的進程循環,並且主要像單線程服務器一樣工作,除了偵聽端口,它將由單個線程處理。這有助於在覈心之間傳播負載,但是如果使用阻塞資源,它將阻塞由該特定線程處理的所有連接。
libevent讓你使用第二種方式,如果你小心;但也有一個替代方案:libev。它不像libevent那樣廣爲人知,但它特別支持多環路方案。
您應該考慮工作線程模型和工作進程模型。事實上,如果你想要這樣做,你應該真的爲線程和進程編寫代碼,然後計時。在現代Linux內核進程中,切換開銷類似於線程切換,但應用程序不必執行任何鎖定信號量。 – 2009-10-22 20:25:45
如果系統配置訪問不要過度做並設置一些iptables的/ PF的/ etc 爲這個負載均衡連接到N個守護實例(進程)將工作開箱。取決於阻止守護進程n的性質應該來自系統上的核心數量還是幾倍更高。這種方法看起來很粗糙,但它可以處理破損的守護進程,並在必要時重啓它們。同樣遷移將會平滑,因爲您可以開始將新連接轉移到另一組進程(例如,新版本或遷移到新框)而不是服務中斷。最重要的是,你會得到幾個功能,如源親和力,這可以顯着幫助緩存和爭用有問題的會話。
如果您沒有訪問系統(OPS或不能打擾),你可以使用負載平衡器守護(有大量的開源者的),而不是iptables的/ PF /等,並利用N服務守護進程,如上所述。
而且,這種方法有助於分離特權端口。如果外部服務需要服務於低端口(< 1024),則只需要運行特權/或管理員/根或內核的負載平衡器。)
我已經寫過幾個IP負載均衡器在生產中可能非常容易出錯。你不想支持和調試。此外,操作和管理會比外部代碼更容易猜測您的代碼。
相反,它聽起來..它不是一個Web服務器。 :)它是很多客戶端的服務器..客戶端保持TCP連接,並有他們期望的輸入設置響應。 – Obi 2009-10-22 19:45:08
你**閱讀**很多瘋狂雜誌是一個**孩子**,是不是? – caf 2009-10-22 20:35:00
@Obi iptables/pf是IP/TCP/UDP,而不是HTTP。您可以使用庫(libevent?),線程或直OpenMP。最後可以在源代碼的特定關鍵點進行相當多的內核間平衡。此外,英特爾最近的nehalem/i7還有超線程技術,但不知道ICC或GCC是否已經支持OpenMP(他們幾年前在2000年初期爲前一個超線程時代所做的) IMHE線程給出了O(n^2)由於同步和caché混音而導致的性能下降。另外它通常伴隨着很多分支預測錯誤。因人而異。 @caf **什麼**? – alecco 2009-10-22 21:25:40
如果性能至關重要,那麼您真的想要尋求一個多線程事件循環解決方案 - 即工作線程池來處理您的連接。不幸的是,沒有抽象庫要做到這一點,在大多數Unix平臺上工作(注意,libevent的僅僅是單線程的最這些事件循環庫),所以你必須自己做骯髒的工作。在Linux上,這意味着使用邊緣觸發epoll與工作線程池(Windows將有I/O完成端口,這也可以在多線程環境中正常工作 - 我不確定其他Unix)。我已經做了一些嘗試在Linux和Windows I/O完成端口上抽象邊緣觸發epoll的工作(它正在進行中,但可能提供一些想法)。
我認爲哈維爾的回答是很有道理的。如果你想測試理論,那麼請查看node JavaScript項目。
節點基於Google的v8引擎,它將javascript編譯爲機器代碼,並且對於某些任務而言與c一樣快。也正是基於對libev和設計是完全無阻塞的,這意味着你不必擔心線程的上下文切換(一切在一個單一的事件循環運行)。在這方面它與erlang非常相似。
在JavaScript編寫高性能服務器現在是真的,真的與節點容易。你也可以通過一點點努力在c中編寫自定義代碼,併爲節點創建綁定以便進行實際處理(查看節點源代碼以瞭解如何執行此操作 - 文檔有點粗略此時此刻)。作爲一個更醜陋的選擇,您可以將您的自定義c代碼構建爲應用程序,並使用stdin/stdout與它進行通信。
我已經用自己的測試節點向上150k連接,絕對沒有問題(當然,如果所有這些連接都要一次通信,你將需要一些嚴重的硬件)。 node.js中的TCP連接平均只使用2-3k的內存,因此您理論上可以處理每1GB內存350-500k的連接。
注 - Node.js的目前不支持Windows版本,但它只是處於發展的初期階段,我會想象它會在某個階段被移植。
注2 - 你必須確保你調用到從節點不會阻止
只需要注意...節點現在可以通過它的底層庫libuv完全支持(類似於libevent)。因爲它成功地封裝了Windows的非阻塞IOCP API,所以libuv在Windows上實際上會比libevent更快。如果您想編寫跨平臺的非阻塞應用程序,libuv和libevent現在都是非常可以接受的選項,但是正如我所提到的,libuv在windows上可能比libevent更好(直到libevent包裝IOCP)。 – andrew 2012-09-26 20:11:13
- 1. 偵聽多個TCP端口
- 2. TCP端口偵聽器不工作
- 3. 服務器偵聽多個端口[Java]
- 4. 服務器偵聽多個端口c
- 5. TCP/IP服務器如何偵聽多個客戶端?
- 6. 打開多個窗口時重複的事件偵聽器(Firefox擴展)
- 7. 如何用多臺機器擴展MySQL?
- 8. Socket.io在多個端口上偵聽?
- 9. gevent多個StreamServer偵聽器
- 10. 我如何偵聽內核空間中的tcp端口(freebsd)?
- 11. 在按鈕上實現多個點擊偵聽器
- 12. Laravel在同一隊列上的多臺機器上排隊偵聽器
- 13. .NET VB如何讓服務器偵聽多個端口?
- 14. 如何編寫python HTTP服務器以偵聽多個端口?
- 15. 在多個JVM上配置ActiveMq偵聽器的多個實例
- 16. 如何更新chrome擴展中的onBeforeRequest事件偵聽器?
- 17. Firefox擴展按鈕偵聽
- 18. c上的網絡端口偵聽器#
- 19. MPI多核機器
- 20. 如何在動作監聽器上控制焦點偵聽器?
- 21. Android:如何實現pushnotification偵聽器?
- 22. tcp/ip數據包偵聽器
- 23. Firefox擴展端口監聽器
- 24. 畫在多核機器
- 25. 兩個瀏覽器如何同時在端口80上偵聽?
- 26. 如何在窗口上暫時阻止鼠標偵聽器?
- 27. Python-Firebase偵聽器實現
- 28. 如何將偵聽器添加到現有的偵聽器對象?
- 29. 如何在本地機器上嗅探/偵聽HTTP?
- 30. 確保在擴展活動後調用事件偵聽器
請重新格式化你的問題的代碼。單個水平滾動線不是很有幫助。 – ndim 2009-10-22 18:01:37
爲什麼選擇C?你不能用別的東西......說Erlang? – jldupont 2009-10-22 18:02:14
@jldupont,語言對此是否重要?這似乎是一個系統問題,而不是某種語言限制。 – mrduclaw 2009-10-22 18:11:14