<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] ## 5、單點Server的N種并發模型匯總 本文主要介紹常見的Server的并發模型,這些模型與編程語言本身無關,有的編程語言可能在語法上直接透明了模型本質,所以開發者沒必要一定要基于模型去編寫,只是需要知道和了解并發模型的構成和特點即可。 那么在了解并發模型之前,我們需要兩個必備的前置知識: * socket網絡編程 * 多路IO復用機制 * 多線程/多進程等并發編程理論 ### 模型一、單線程Accept(無IO復用) #### (1) 模型結構圖 ![](https://img.kancloud.cn/3c/14/3c1458b97e48e71ea216e996aa3f2dc0_1920x1080.jpeg) #### (2) 模型分析 ① 主線程`main thread`執行阻塞Accept,每次客戶端Connect鏈接過來,`main thread`中accept響應并建立連接 ② 創建鏈接成功,得到`Connfd1`套接字后, 依然在`main thread`串行處理套接字讀寫,并處理業務。 ③ 在②處理業務中,如果有新客戶端`Connect`過來,`Server`無響應,直到當前套接字全部業務處理完畢。 ④ 當前客戶端處理完后,完畢鏈接,處理下一個客戶端請求。 #### (3) 優缺點 **優點**: * socket編程流程清晰且簡單,適合學習使用,了解socket基本編程流程。 **缺點**: * 該模型并非并發模型,是串行的服務器,同一時刻,監聽并響應最大的網絡請求量為`1`。 即并發量為`1`。 * 僅適合學習基本socket編程,不適合任何服務器Server構建。 ### 模型二、單線程Accept+多線程讀寫業務(無IO復用) #### (1) 模型結構圖 ![](https://img.kancloud.cn/75/eb/75ebef29690b072e206535c28e950301_1920x1080.jpeg) #### (2) 模型分析 ① 主線程`main thread`執行阻塞Accept,每次客戶端Connect鏈接過來,`main thread`中accept響應并建立連接 ② 創建鏈接成功,得到`Connfd1`套接字后,創建一個新線程`thread1`用來處理客戶端的讀寫業務。`main thead`依然回到`Accept`阻塞等待新客戶端。 ③ `thread1`通過套接字`Connfd1`與客戶端進行通信讀寫。 ④ server在②處理業務中,如果有新客戶端`Connect`過來,`main thread`中`Accept`依然響應并建立連接,重復②過程。 #### (3) 優缺點 **優點**: * 基于`模型一:單線程Accept(無IO復用)` 支持了并發的特性。 * 使用靈活,一個客戶端對應一個線程單獨處理,`server`處理業務內聚程度高,客戶端無論如何寫,服務端均會有一個線程做資源響應。 **缺點**: * 隨著客戶端的數量增多,需要開辟的線程也增加,客戶端與server線程數量`1:1`正比關系,一次對于高并發場景,線程數量收到硬件上限瓶頸。 * 對于長鏈接,客戶端一旦無業務讀寫,只要不關閉,server的對應線程依然需要保持連接(心跳、健康監測等機制),占用連接資源和線程開銷資源浪費。 * 僅適合客戶端數量不大,并且數量可控的場景使用。 僅適合學習基本socket編程,不適合任何服務器Server構建。 ### 模型三、單線程多路IO復用 #### (1) 模型結構圖 ![](https://img.kancloud.cn/b7/8b/b78b7c25b26b1bf40a84ee7ea5bae313_1920x1080.jpeg) #### (2) 模型分析 ① 主線程`main thread`創建`listenFd`之后,采用多路I/O復用機制(如:select、epoll)進行IO狀態阻塞監控。有`Client1`客戶端`Connect`請求,I/O復用機制檢測到`ListenFd`觸發讀事件,則進行`Accept`建立連接,并將新生成的`connFd1`加入到`監聽I/O集合`中。 ② `Client1`再次進行正常讀寫業務請求,`main thread`的`多路I/O復用機制`阻塞返回,會觸該套接字的讀/寫事件等。 ③ 對于`Client1`的讀寫業務,Server依然在`main thread`執行流程提繼續執行,此時如果有新的客戶端`Connect`鏈接請求過來,Server將沒有即時響應。 ④ 等到Server處理完一個連接的`Read+Write`操作,繼續回到`多路I/O復用機制`阻塞,其他鏈接過來重復 ②、③流程。 #### (3) 優缺點 **優點**: * 單流程解決了可以同時監聽多個客戶端讀寫狀態的模型,不需要`1:1`與客戶端的線程數量關系。 * 多路I/O復用阻塞,非忙詢狀態,不浪費CPU資源, CPU利用率較高。 **缺點**: * 雖然可以監聽多個客戶端的讀寫狀態,但是同一時間內,只能處理一個客戶端的讀寫操作,實際上讀寫的業務并發為1。 * 多客戶端訪問Server,業務為串行執行,大量請求會有排隊延遲現象,如圖中⑤所示,當`Client3`占據`main thread`流程時,`Client1,Client2`流程卡在`IO復用`等待下次監聽觸發事件。 ### 模型四、單線程多路IO復用+多線程讀寫業務(業務工作池) #### (1) 模型結構圖 ![](https://img.kancloud.cn/14/8f/148fb61338b6de7dd669acd4d611369d_1920x1080.jpeg) #### (2) 模型分析 ① 主線程`main thread`創建`listenFd`之后,采用多路I/O復用機制(如:select、epoll)進行IO狀態阻塞監控。有`Client1`客戶端`Connect`請求,I/O復用機制檢測到`ListenFd`觸發讀事件,則進行`Accept`建立連接,并將新生成的`connFd1`加入到`監聽I/O集合`中。 ② 當`connFd1`有可讀消息,觸發讀事件,并且進行讀寫消息 ③ `main thread`按照固定的協議讀取消息,并且交給`worker pool`工作線程池, 工作線程池在server啟動之前就已經開啟固定數量的`thread`,里面的線程只處理消息業務,不進行套接字讀寫操作。 ④ 工作池處理完業務,觸發`connFd1`寫事件,將回執客戶端的消息通過`main thead`寫給對方。 ##### (3) 優缺點 **優點**: * 對于`模型三`, 將業務處理部分,通過工作池分離出來,減少多客戶端訪問Server,業務為串行執行,大量請求會有排隊延遲時間。 * 實際上讀寫的業務并發為1,但是業務流程并發為worker pool線程數量,加快了業務處理并行效率。 **缺點**: * 讀寫依然為`main thread`單獨處理,最高讀寫并行通道依然為1. * 雖然多個worker線程處理業務,但是最后返回給客戶端,依舊需要排隊,因為出口還是`main thread`的`Read + Write` ### 模型五、單線程IO復用+多線程IO復用(鏈接線程池) #### (1) 模型結構圖 ![](https://img.kancloud.cn/16/2b/162b19e0bfe51092569c58c06afe8cfb_1920x1080.jpeg) #### (2) 模型分析 ① Server在啟動監聽之前,開辟固定數量(N)的線程,用`Thead Pool`線程池管理 ② 主線程`main thread`創建`listenFd`之后,采用多路I/O復用機制(如:select、epoll)進行IO狀態阻塞監控。有`Client1`客戶端`Connect`請求,I/O復用機制檢測到`ListenFd`觸發讀事件,則進行`Accept`建立連接,并將新生成的`connFd1`分發給`Thread Pool`中的某個線程進行監聽。 ③ `Thread Pool`中的每個`thread`都啟動`多路I/O復用機制(select、epoll)`,用來監聽`main thread`建立成功并且分發下來的socket套接字。 ④ 如圖, `thread`監聽`ConnFd1、ConnFd2`, `thread2`監聽`ConnFd3`,`thread3`監聽`ConnFd4`. 當對應的`ConnFd`有讀寫事件,對應的線程處理該套接字的讀寫及業務。 #### (3) 優缺點 **優點**: * 將`main thread`的單流程讀寫,分散到多線程完成,這樣增加了同一時刻的讀寫并行通道,并行通道數量`N`, `N`為線程池`Thread`數量。 * server同時監聽的`ConnFd套接字`數量幾乎成倍增大,之前的全部監控數量取決于`main thread`的`多路I/O復用機制`的最大限制***(select 默認為1024, epoll默認與內存大小相關,約3~6w不等)***,所以理論單點Server最高響應并發數量為`N*(3~6W)`(`N`為線程池`Thread`數量,建議與CPU核心成比例1:1)。 * 如果良好的線程池數量和CPU核心數適配,那么可以嘗試CPU核心與Thread進行綁定,從而降低CPU的切換頻率,提升每個`Thread`處理合理業務的效率,降低CPU切換成本開銷。 **缺點**: * 雖然監聽的并發數量提升,但是最高讀寫并行通道依然為`N`,而且多個身處同一個Thread的客戶端,會出現讀寫延遲現象,實際上每個`Thread`的模型特征與`模型三:單線程多路IO復用`一致。 ### 模型五(進程版)、**單進程多路I/O復用+多進程多路I/O復用(進程池)** #### (1) 模型結構圖 ![](https://img.kancloud.cn/9c/05/9c0554e28f77056946d3696f73ab2915_1920x1080.jpeg) #### (2) 模型分析 與`五、單線程IO復用+多線程IO復用(鏈接線程池)`無大差異。 不同處 * 進程和線程的內存布局不同導致,`main process`(主進程)不再進行`Accept`操作,而是將`Accept`過程分散到各個`子進程(process)`中. * 進程的特性,資源獨立,所以`main process`如果Accept成功的fd,其他進程無法共享資源,所以需要各子進程自行Accept創建鏈接 * `main process`只是監聽`ListenFd`狀態,一旦觸發讀事件(有新連接請求). 通過一些IPC(進程間通信:如信號、共享內存、管道)等, 讓各自子進程`Process`競爭`Accept`完成鏈接建立,并各自監聽。 #### (3) 優缺點 與`五、單線程IO復用+多線程IO復用(鏈接線程池)`無大差異。 不同處: 多進程內存資源空間占用稍微大一些 多進程模型安全穩定型較強,這也是因為各自進程互不干擾的特點導致。 ### 模型六、**單線程多路I/O復用+多線程多路I/O復用+多線程** #### (1) 模型結構圖 ![](https://img.kancloud.cn/b0/7b/b07bc6b3ca5cba69e780509d405a228f_1920x1080.jpeg) #### (2) 模型分析 ① Server在啟動監聽之前,開辟固定數量(N)的線程,用`Thead Pool`線程池管理 ② 主線程`main thread`創建`listenFd`之后,采用多路I/O復用機制(如:select、epoll)進行IO狀態阻塞監控。有`Client1`客戶端`Connect`請求,I/O復用機制檢測到`ListenFd`觸發讀事件,則進行`Accept`建立連接,并將新生成的`connFd1`分發給`Thread Pool`中的某個線程進行監聽。 ③ `Thread Pool`中的每個`thread`都啟動`多路I/O復用機制(select、epoll)`,用來監聽`main thread`建立成功并且分發下來的socket套接字。一旦其中某個被監聽的客戶端套接字觸發`I/O讀寫事件`,那么,會立刻開辟一個新線程來處理`I/O讀寫`業務。 ④ 但某個讀寫線程完成當前讀寫業務,如果當前套接字沒有被關閉,那么將當前客戶端套接字`如:ConnFd3`重新加回線程池的監控線程中,同時自身線程自我銷毀。 #### (3) 優缺點 **優點**: * 在`模型五、單線程IO復用+多線程IO復用(鏈接線程池)`基礎上,除了能夠保證同時響應的`最高并發數`,又能解決`讀寫并行通道`局限的問題。 * 同一時刻的讀寫并行通道,達到`最大化極限`,一個客戶端可以對應一個單獨執行流程處理讀寫業務,讀寫并行通道與客戶端數量`1:1`關系。 **缺點**: * 該模型過于理想化,因為要求CPU核心數量足夠大。 * 如果硬件CPU數量可數(目前的硬件情況),那么該模型將造成大量的CPU切換成本浪費。因為為了保證讀寫并行通道與客戶端`1:1`的關系,那么Server需要開辟的`Thread`數量就與客戶端一致,那么線程池中做`多路I/O復用`的監聽線程池綁定CPU數量將變得毫無意義。 * 如果每個臨時的讀寫`Thread`都能夠綁定一個單獨的CPU,那么此模型將是最優模型。但是目前CPU的數量無法與客戶端的數量達到一個量級,目前甚至差的不是幾個量級的事。 ### 總結 綜上,我們整理了7中Server的服務器處理結構模型,每個模型都有各自的特點和優勢,那么對于多少應付高并發和高CPU利用率的模型,目前多數采用的是模型五(或模型五進程版,如Nginx就是類似模型五進程版的改版)。 至于并發模型并非設計的約復雜越好,也不是線程開辟的越多越好,我們要考慮硬件的利用與和切換成本的開銷。模型六設計就極為復雜,線程較多,但以當今的硬件能力無法支撐,反倒導致該模型性能極差。所以對于不同的業務場景也要選擇適合的模型構建,并不是一定固定就要使用某個來應用。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看