關於Web伺服器的運行知識(二)

四、Web 服務請求過程

關於Web服務器的運行知識(二)

在上面的講解中我們說明,Web服務器的如何提供服務的,有多進程的方式、多線程的方式還有異步方式我們先簡單這麼理解,後面我們慢慢說,現在我們不管Web服務器是如何提供服務的,多進程也好、多線程好,異步也罷。下面我們來說一下,一個客戶端的具體請求Web服務的具體過程,從上圖中我們可以看到有11步,下面我們來具體說一下,

1. 首先我們客戶端發送一個請求到Web服務器,請求首先是到網卡。

2. 網卡將請求交由內核空間的內核處理,其實就是拆包了,發現請求的是80端口。

3. 內核便將請求發給了在用戶空間的Web服務器,Web服務器接受到請求發現客戶端請求的index.html頁面。

4. Web服務器便進行系統調用將請求發給內核。

5. 內核發現在請求的是一頁面,便調用磁盤的驅動程序,連接磁盤。

6. 內核通過驅動調用磁盤取得的頁面文件。

7. 內核將取得的頁面文件保存在自己的緩存區域中便通知Web進程或線程來取相應的頁面文件。

8. Web服務器通過系統調用將內核緩存中的頁面文件複製到進程緩存區域中。

9. Web服務器取得頁面文件來響應用戶,再次通過系統調用將頁面文件發給內核。

10. 內核進程頁面文件的封裝並通過網卡發送出去。

11. 當報文到達網卡時通過網絡響應給客戶端

簡單來說就是:用戶請求-->送達到用戶空間-->系統調用-->內核空間-->內核到磁盤上讀取網頁資源->返回到用戶空間->響應給用戶。上述簡單的說明了一下,客戶端向Web服務請求過程,在這個過程中,有兩個I/O過程,一個就是客戶端請求的網絡I/O,另一個就是Web服務器請求頁面的磁盤I/O。 下面我們就來說說Linux的I/O模型。

五、Linux I/O 模型

1.I/O模型分類

說明:我們都知道web服務器的進程響應用戶請求,但無法直接操作I/O設備,其必須通過系統調用,請求kernel來協助完成I/O動作,如下圖:

關於Web服務器的運行知識(二)

對於數據輸入而言,即等待(wait)數據輸入至buffer需要時間,而從buffer複製(copy)數據至進程也需要時間

根據等待模式不同,I/O動作可分為五種模式。

1.阻塞I/O,2.非阻塞I/O,3.I/O複用(select和poll),4.信號(事件)驅動I/O(SIGIO),5.異步I/O(Posix.1的aio_系列函數)

2.I/O模型的相關術語

(1).阻塞和非阻塞:

阻塞和非阻塞指的是執行一個操作是等操作結束再返回,還是馬上返回。比如你去車站接朋友,這是一個操作。可以有兩種執行方式。第一種,你這人特實誠,老早就到了車站一直等到車來了接到朋友為止。第二種,你到了車站,問值班的那趟車來了沒有,“還沒有”,你出去逛一圈,可能過會回來再問。第一種就是阻塞方式,第二種則是非阻塞的。我認為阻塞和非阻塞講得是做事方法,是針對做事的人而言的。

(2).同步和異步:

同步和異步又是另外一個概念,它是事件本身的一個屬性。比如老闆讓你去搬一堆石頭,而且只讓你一個人幹,你只好自己上陣,最後的結果是搬完了,還是你砸到腳了,只有搬完了你才知道。這就是同步的事件。如果老闆還給你個小弟,你就可以讓小弟去搬,搬完了告你一聲。這就變成異步的了。其實異步還可以分為兩種:帶通知的和不帶通知的。前面說的那種屬於帶通知的。有些小弟幹活可能主動性不是很夠,不會主動通知你,你就需要時不時的去關注一下狀態。這種就是不帶通知的異步。 對於同步的事件,你只能以阻塞的方式去做。而對於異步的事件,阻塞和非阻塞都是可以的。非阻塞又有兩種方式:主動查詢和被動接收消息。被動不意味著一定不好,在這裡它恰恰是效率更高的,因為在主動查詢裡絕大部分的查詢是在做無用功。對於帶通知的異步事件,兩者皆可。而對於不帶通知的,則只能用主動查詢。

(3).I/O

回到I/O,不管是I還是O,對外設(磁盤)的訪問都可以分成請求和執行兩個階段。請求就是看外設的狀態信息(比如是否準備好了),執行才是真正的I/O操作。在Linux 2.6之前,只有“請求”是異步事件,2.6之後才引入AIO把“執行”異步化。別看Linux/Unix是用來做服務器的,這點上比Windows落後了好多,IOC(Windows上的AIO)在Win2000上就有了。

(4).總結

Linux上的前四種I/O模型的“執行”階段都是同步的,只有最後一種才做到了真正的全異步。第一種阻塞式是最原始的方法,也是最累的辦法。當然累與不累要看針對誰。應用程序是和內核打交道的。對應用程序來說,這種方式是最累的,但對內核來說這種方式恰恰是最省事的。還拿接人這事為例,你就是應用程序,值班員就是內核,如果你去了一直等著,值班員就省事了。當然現在計算機的設計,包括操作系統,越來越為終端用戶考慮了,為了讓用戶滿意,內核慢慢的承擔起越來越多的工作,IO模型的演化也是如此。非阻塞I/O ,I/O複用,信號驅動式I/O其實都是非阻塞的,當然是針對“請求”這個階段。非阻塞式是主動查詢外設狀態。I/O複用裡的select,poll也是主動查詢,不同的是select和poll可以同時查詢多個fd(文件句柄)的狀態,另外select有fd個數的限制。epoll是基於回調函數的。信號驅動式I/O則是基於信號消息的。這兩個應該可以歸到“被動接收消息”那一類中。最後就是偉大的AIO的出現,內核把什麼事都幹了,對上層應用實現了全異步,性能最好,當然複雜度也最高。


分享到:


相關文章: