測試技術老大應該有的修養

weixin_33850890發表於2018-05-25

前兩篇文章我們用物件導向的思想,分析了一個作業系統的基本構成和設計思路。今天我們繼續來聊Web和應用伺服器的設計,聊一下怎麼高效的利用網路IO和CPU資源。

 Socket物件

  上一篇我們聊到,作業系統通過核心表中的物件來管理網路IO,這個物件就是Socket類。我們來看一下整個讀取和傳送資料的過程。

  我們把Socket物件比作快遞公司,他幫助大家收發各種快件。Socket的IP、埠號和程式ID等資訊就是貨物的具體地址。當我們寄送快遞的時候,快遞員上門取貨,但是他不會直接送往目的地,而是先送往中轉站。為什麼要這麼做,因為把發往同一個地點的貨物合併傳送,當然效率更高。Socket傳送資料也是如此,他會先將資料傳送到緩衝區中,然後再一起傳送。

  同樣,收快遞的時候,貨物也會先傳送到配送點,然後再由快遞員送貨上門。Socket接收資料也是如此,會先存在緩衝區中。我們上一篇聊過,核心物件的資料是存在核心態地址空間中,使用者程式是沒法直接讀取的。我們需要把資料從核心態拷貝到使用者態,才可以訪問。

 高效Socket讀取

  Socket的讀取和寫入預設都是同步的過程,對使用者執行緒來說就是阻塞的。傳送資料的情況還好,不會等待多久;讀取資料就比較尷尬,因為我們不知道對方什麼時候會傳送資料,也就不知道要等多久;對一個高效能的Web或者應用伺服器來說,解決這個問題就是最重要的。下面我們看看對這塊的解決方案是怎麼演化的。

 同步阻塞模型

  最簡單的方式就是同步阻塞式讀取。對應到伺服器設計上,每來一個網路請求,我們就生成一個執行緒來服務。沒有請求資料的時候,這個執行緒就阻塞著。這就是同步阻塞模型。

  同步阻塞模型最大的問題就是,沒有資料的時候也要無謂的等待。這種設計的確會浪費執行緒和Socket資源,但是這種模型足夠簡單,開發容易。如果併發量並不大的情況,可以考慮採用。

同步非阻塞模型

  我們改進一下,在讀取資料之前,先檢測一下,如果這時沒有資料,就先去幹點別的。這就是同步非阻塞模型。

  採用這個模型,只需要Socket讀取資料的時候設定成非阻塞就可以。但是這種模型缺點也很大,每個使用者執行緒總要輪詢去檢測,如果一直沒有資料,就白白浪費了計算資源。

多路複用模型

再優化一下,如果我們只用一個執行緒去做所有Socket的檢測工作,當真正有資料到達的時候,再提醒使用者執行緒去處理。這樣就很好的解決了同步非阻塞模型的缺點。這就是多路複用模型。Linux的epoll就是這樣的方式。

  這裡我們要考慮一點,多路複用模型只有一個執行緒做檢測工作,增加了伺服器處理請求的能力,但是如果併發量並不大的時候,其實效能並沒有提高。

  非同步模型

前面所說的各種模型,都需要我們自己做大量的工作。有沒有一種方式,讓作業系統把全部工作承包了呢。當然是有的。作業系統來監聽Socket,當有資料到來時,讀取這個資料,拷貝資料到使用者態程式空間,完成這一切工作後,再來告知我們。這就是非同步模型,Windows作業系統的完成埠模式就是這樣的方式。

總結一下,對伺服器設計來說,高效管理網路IO和CPU資源很重要,我們聊了4種不同的模型設計。

10256972-e6415d4804ce9068.png

相關文章