I/O請求概述服務器
操做系統根據使用者的不一樣分爲用戶空間和內核空間,Apache、Nginx等是運行在用戶空間對外提供服務的程序,一個服務器應該儘量多的運行在用戶空間來接受業務請求。
網絡
一個完整的I/O請求步驟爲:併發
1.客戶端與服務器創建鏈接發出請求,服務器接受請求(1--2),此時的I/O爲網絡I/O,網絡I/O在服務器的內核中完成。異步
2.當服務器接收完請求,並在用戶空間啓動一個進程或線程代客戶端發起請求,直到構建響應完成的過程(3--5)稱爲服務器的I/O過程。ide
3.服務器將已構建好的響應再經過內核空間的網絡I/O發還給客戶端,同時將本次請求記錄到日誌中。函數
整個過程當中服務器先在內核空間接收響應,然後在用戶空間處理請求並構建響應,最後再經過內核空間的網絡I/O發送響應。在用戶空間處理請求構建響應的過程(3--5)就是咱們一般所說的I/O過程。優化
I/O的類型劃分spa
關注的角度不一樣,能夠將I/O請求類型分爲:操作系統
1.同步、異步線程
同步和異步關注的是消息通知機制。同步:進程或線程發出請求後不會當即返回,但一旦返回就能夠返回最終結果;異步:進程或線程發出請求後會當即獲得一個返回結果,但返回的非最終結果,當內核處理完成後經過通知機制告知進程,或經過回調函數來處理結果。
2.阻塞、非阻塞
阻塞和非阻塞關注的是等待結果(消息、返回值)時的狀態。阻塞:最終結果返回以前,使用的進程或線程會被掛起,只有在獲得結果以後纔會返回;非阻塞:最終結果返回以前,不會阻塞當前進程或線程。
I/O模型的劃分
根據上述類型,I/O模型就可分爲5種:同步阻塞、同步非阻塞、I/0複用、事件驅動和異步非阻塞(AIO)
要弄清I/O模型,首先要詳細瞭解一個請求從開始到響應結束的過程。咱們知道操做系統分爲內核空間和用戶空間,一個進程或線程同一時間只能處理一個I/0請求,當客戶端發出一個請求後,服務器端首先會經過內核中的TCP/IP協議棧來接受請求,並將客戶端請求傳遞給用戶空間內的一個進程或線程來代爲請求,此時操做系統會由內核空間轉入用戶空間,全部的請求最終調用的是本地文件系統上的一個資源,而能夠調用本地文件系統資源的只有內核,此時操做系統又由用戶空間轉入內核空間,從進程代客戶端發起請求開始,直到得到最終的結果或通知消息之間的這個階段稱爲wait for data,當內核將本地文件系統上的資源加載到內核內存後,因爲內核內存不容許用戶空間的程序訪問,還要將內核內存中的資源複製到用戶空間的進程或線程內存中,此時階段爲copy data,複製完成後再由內核空間轉入用戶空間構建響應發送給客戶端。5種I/O模型的區別就是在wait for data和copy data階段的不一樣。
1.同步阻塞
當客戶端發出請求,服務器端接收到請求並啓動一個進程代客戶端發起請求,直到返回最終結果,整個過程當中進程被掛起,再也不處理其餘請求。
2.同步非阻塞
當客戶端發出請求,服務器端接收到請求並啓動一個進程代客戶端發起請求,內核當即給進程返回一個消息,因爲沒有通知機制,進程不停的詢問處理是否完成,此時稱爲忙等待,在copy data階段進程仍然處於阻塞狀態。
3.I/O複用
此模型能夠理解爲服務器端有一個專門的進程只負責接收客戶端發起的請求,將接收到的請求交由其餘進程代客戶端發起請求和處理,和上述兩種模型不同的地方是接收和處理用戶請求不是同一個進程,此時代理用戶發出請求的進程是被阻塞在代理進程上。Apache默認prefork工做模式的select模型就是使用的這種I/O模型,prefork模式默認支持1024個併發鏈接,超出這個併發數量就會由於進程間調度的開銷致使效率遞減。
4.事件驅動
當客戶端發出請求,服務器端接收到請求並啓動一個進程代客戶端發起請求,內核當即給進程返回一個消息,儘管在copy data階段進程仍然處於阻塞狀態,但在wait data階段因爲進程沒有被阻塞,因此依然能夠接收其餘的用戶請求。epoll機制採用的就是這種事件驅動I/O模型,經過前文知道一個進程在同一時間只能處理一種I/O,當有這麼一種狀況發生:第一個請求的copy data階段完成後,進程恰巧在接收另外一個用戶的請求,此時內核就會發送通知讓進程來取數據,通知分爲水平觸發和邊緣觸發2種方式,水平觸發:進程不斷的給請求者發送通知直到來取數據爲止;邊緣觸發:進程只給請求者發送一次通知。同時epoll還支持mmap機制。
5.異步非阻塞(AIO)
當客戶端發出請求,服務器端接收到請求並啓動一個進程代客戶端發起請求,內核當即給進程返回一個消息,轉而接收下一個用戶請求,後續的處理由內核來完成,完成後發送通知給進程。整個過程當中進程都沒有被阻塞,提升了併發處理請求的能力。
優化機制
常常聽到的優化機制有send file和mmap,經過一個I/O請求從開始到響應結束的過程咱們知道,系統先把請求的資源加載到內核空間,而後再複製到用戶空間構建響應完成後再到內核空間進行發送,其中內核空間複製到用戶空間打包再轉入內核空間的過程當中數據自己並無改變,而白白浪費了時鐘週期,因此send file機制就是當資源在內核空間加載完成後直接構建響應發送給請求者,而不進入用戶空間,以減小中間環節提高效率;mmap是在用戶空間內存中開一片區域將內核的存儲區域映射進去,數據再也不須要在內核與用戶空間中來回複製。