簡體   English   中英

在創建將同時為200多個客戶端發送/接收任務的服務器時,使用select或多線程(或同時使用)更好嗎?

[英]Is it better to use select or multi-threading (or both) when creating a server that will simultaneously send/receive tasks for 200+ clients

我正在創建一個服務器,該服務器將同時發送和接收來自200多個客戶端的任務(將來可能會有更多的客戶端)。 客戶端上還將有后台引擎,這些后台引擎將執行任務並將響應發送到服務器而無需先詢問。 我希望雙向都有大量的信息傳遞。 我一直在研究多線程並使用select函數,但我想知道給定項目的某些參數,根據流量的多少,哪個選項(或組合)將是最有效的可擴展解決方案。可能會發生。

任何建議將不勝感激。 我很樂意回答任何問題以使內容更加清晰。

兩種方法都行得通; 到目前為止,“更好”將在很大程度上取決於您如何定義“更好”一詞。

  • 單線程方法避免了競爭狀況或死鎖問題的任何可能性,因為這些問題固有地不會在單線程程序中發生。 在多線程程序中,您必須非常小心數據鎖定模式,否則您將發現自己嘗試調試非常神秘的故障,這種故障僅每隔幾天/幾周/幾個月發生一次。

  • 另一方面,單線程方法將您限制為使用單個內核。 它將無法利用現代多核CPU來提高並行處理速度。

  • 第三,如果各種線程/連接經常需要訪問任何共享/可變的數據結構,則多線程方法可能會變得冗長(並失去其加速潛力)。 在這種“共享數據瓶頸”的情況下,線程可能會花費大量時間來等待鎖定互斥鎖,然后無論如何您還是會回到使用單個內核。 如果每個連接獨立於其他連接運行(例如,作為簡單Web服務器的一部分),並且不需要與其他線程進行交互,則不必擔心。

  • 多線程允許您使用阻塞I / O(比非阻塞I / O易於實現),但阻塞I / O限制了您對線程的控制(例如,如何使線程干凈退出或占用一些線程)其他非客戶端啟動的操作,如果該操作在recv()調用中被無限期阻止,則該問題沒有任何好的解決方案,只有較差的解決方案)

  • 單線程要求您使用非阻塞I / O(否則,當服務器在send()recv()調用中被阻塞時,單個無響應的客戶端可以停止對所有其他客戶端的服務)和非阻塞I / O。 O很難正確執行,因為您必須妥善處理部分讀取和部分寫入。

  • 如果您的程序曾經需要執行大量的計算或文件I / O,請注意,單線程設計將強制所有客戶端等待任何客戶端的計算(或I / O)完成。 在多線程設計OTOH中,當客戶端A忙於從磁盤讀取數據或處理數字時,客戶端B到Z可以繼續在其他內核/線程上進行服務。

  • 生成和維護線程的開銷將因一個OS而異。 如果要同時運行數百個線程,則可能需要首先驗證目標操作系統(和硬件)將能夠有效處理該負載。 (您可以減少通過線程池產生和收獲線程的開銷,但要以增加RAM使用量為代價)

我個人更喜歡單線程/非阻塞I / O方法,因為如果您希望程序能夠干凈,可靠地關閉(如果應該這樣做,則應該這樣做),阻塞I / O是有問題的。例如,在valgrind下進行內存泄漏測試)。 如果單核性能不足,通常可以很簡單地將“ N個套接字處理”線程設計擴展到更強大的“ M個線程處理”線程設計,然后您可以嘗試使用不同的N和M值,直到找到可以提供最佳性能的值為止(例如,通過將M設置為主機上的內核數,並將新接受的套接字分發給任何線程)當前處理的套接字數量最少)

我曾經用Java創建一個程序,一個聊天應用程序,它與建立的服務器的每個連接都代表服務器中的一個新線程,用於管理相關客戶端。

在Server類內部,有一個靜態變量來管理連接了哪些客戶端。

我不知道推薦不同的技術是否是回答您問題的正確方法,但是我認為,對於您的情況,看看Erlang / Elixir平台是一個好主意,前提是能夠保持同時有很多客戶

當前,像Whatsapp這樣的大公司都在使用Erlang和Discord Elixir。

希望我的回答對您有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM