中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

服務端的多路復用如何解決連接高并發問題

發布時間:2021-12-06 17:31:22 來源:億速云 閱讀:235 作者:柒染 欄目:互聯網科技

服務端的多路復用如何解決連接高并發問題,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

在淘寶上購物,比如雙11秒殺某個商品,對后臺都是一次考驗。一個網站系統,在很短時間內收到巨量請求時,穩定性至關重要,用戶都不喜歡看自己的app老是轉菊花。具體的后臺并發詳見前文:大白話描述淘寶服務端分布式架構演進之路----系列一大白話分布式系統演進之路----系列二

這里先不講策略性的東西,講講socket層面多連接下的并發問題。先來看I/O操作,調用read可以從流中讀入數據,調用write可以往流寫入數據。那么如果調用read,但流中沒有數據怎么辦呢?只能使用阻塞I/O。對于服務端,有多個連接的情況,如果一個描述符fd阻塞了,導致另一個描述符fd即使收到數據也無法處理。對于這種情況,就得采用特殊方法處理。

一種方法是使用多進程,可使每個進程都執行阻塞read,但是進程間的信號同步就比較麻煩。

服務端的多路復用如何解決連接高并發問題

另一種辦法就是使用一個進程執行程序,使用非阻塞I/O讀取數據。采用輪詢方式讀取所有套接字是否能收到數據。這種方法不足之處就是浪費CPU的計算資源。

       這里要說的就是I/O多路復用,也就是poll、epoll、pselect、select這幾個調用。可以通過以太驅動程序來大概看一下網卡接收數據的過程:

服務端的多路復用如何解決連接高并發問題

MAC網卡接收到數據包后通過DMA寫入內存約定地址(這里如果剛好內存的數據緩存在cache里,就有DMA和Cache數據不一致的問題,不過這里不是本文重點),然后觸發硬件中斷通知CPU,CPU調用中斷程序讀取內存中的數據。

       接下來可以看看操作系統如何通過select來實現多個socket的讀寫操作。前文講過進程調度的幾種方式:進程調度與fork,大致就是操作系統會維護一個隊列(假定任務優先級相同),任務調度器按順序撈取隊列上的任務執行:

服務端的多路復用如何解決連接高并發問題

當任務A創建socket時,操作系統會創建一個socket對象(一切描述符都是文件)。這個socket對象里面包含了發送接收緩沖區、任務等待隊列等成員。參考lwip的實現:

服務端的多路復用如何解決連接高并發問題

創建socket:

服務端的多路復用如何解決連接高并發問題

進程A當執行read時,由于無數據可讀,進程A由運行態變為阻塞態,操作系統會把進程A掛在socket的等待隊列下,并從工作隊列移除,這個時候只有進程B和C占用CPU資源。

服務端的多路復用如何解決連接高并發問題

這里要注意,并非直接把進程A掛接在等待隊列下,而是把進程A的郵箱recvbox掛上去了:

服務端的多路復用如何解決連接高并發問題

       當接收到數據時,任務調度器會將進程A設置為就緒態并掛到工作隊列中,重新接受任務調度。

那么,服務器需要管理多條連接,而一個read/recv只能阻塞一個socket,這里就用到了select。這里不放代碼,而是直接用圖說明:

服務端的多路復用如何解決連接高并發問題

進程A會監視所有的socket,任何一個連接收到數據后,中斷程序都會喚醒等待隊列上的進程,然后只有真正收到數據的那個進程運行,其余進程繼續阻塞。這個就是服務器的”驚群”現象。

有沒有更合適的方法監聽事件呢?答案是epoll

epoll的接口如下:

int epoll_create(int size);//創建一個epoll的句柄,size為監聽的數目int epoll_ctl(int epfd, int op, int fd,struct epoll_event *event);int epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout);

select的缺點就是進程不知道哪些sock收到了數據,因此只能遍歷所有sock。而epoll維護了一個就緒列表,引用收到數據的socket,可以避免遍歷:

服務端的多路復用如何解決連接高并發問題

當進程調用epoll_create時,會創建一個 eventpoll 對象。eventpoll對象與socket對象類似,也有等待數組。然后進程可以使用epoll_ctl添加所要監聽的socket,內核會將eventpoll添加到socket的等待隊列中。

服務端的多路復用如何解決連接高并發問題

當socket收到數據后,中斷程序會給eventpoll的“就緒列表”添加發生事件的socket序號,如sock2上面收到了數據,就把2寫入eventpoll的rdlist數組里面:

服務端的多路復用如何解決連接高并發問題

       當進程執行epoll_wait時,如果rdlist里面有socket,那么epoll_wait直接返回,否則阻塞進程,阻塞的進程掛在eventpoll的等待隊列下面,如下面的圖表示進程A和進程F被阻塞:

服務端的多路復用如何解決連接高并發問題

收到數據時,中斷程序將對應的socket序號寫入rdlist,同時喚醒eventpoll 等待隊列中的進程,進程A和F進入運行狀態。

關于服務端的多路復用如何解決連接高并發問題問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

平湖市| 兰溪市| 象山县| 达日县| 积石山| 汉川市| 祁东县| 陆河县| 扶沟县| 南陵县| 苍山县| 乌拉特中旗| 阿克| 大竹县| 寿光市| 新乡县| 东乡族自治县| 合肥市| 名山县| 尖扎县| 昆山市| 龙南县| 深州市| 南宁市| 平果县| 金溪县| 集安市| 康保县| 轮台县| 双流县| 蒙山县| 萍乡市| 通辽市| 武山县| 贵港市| 二连浩特市| 永吉县| 门源| 新晃| 汝南县| 东光县|