伺服器模型——從單執行緒阻塞到多執行緒非阻塞(上)

超人汪小建發表於2017-12-21

前言的前言

伺服器模型涉及到執行緒模式和IO模式,搞清楚這些就能針對各種場景有的放矢。該系列分成三部分:

  • 單執行緒/多執行緒阻塞I/O模型
  • 單執行緒非阻塞I/O模型
  • 多執行緒非阻塞I/O模型,Reactor及其改進

前言

這裡探討的伺服器模型主要指的是伺服器端對I/O的處理模型。從不同維度可以有不同的分類,這裡從I/O的阻塞與非阻塞、I/O處理的單執行緒與多執行緒角度探討伺服器模型。

對於I/O,可以分成阻塞I/O與非阻塞I/O兩大型別。阻塞I/O在做I/O讀寫操作時會使當前執行緒進入阻塞狀態,而非阻塞I/O則不進入阻塞狀態。

對於執行緒,單執行緒情況下由一條執行緒負責所有客戶端連線的I/O操作,而多執行緒情況下則由若干執行緒共同處理所有客戶端連線的I/O操作。

單執行緒阻塞I/O模型

單執行緒阻塞I/O模型是最簡單的一種伺服器模型,幾乎所有程式設計師在剛開始接觸網路程式設計時都從這個簡單的模型開始。這種模型只能同時處理一個客戶端訪問,並且在I/O操作上是阻塞的,執行緒會一直在等待,而不會做其他事情。對於多個客戶端訪問,必須要等到前一個客戶端訪問結束才能進行下一個訪問的處理,請求一個一個排隊,只提供一問一答服務。

伺服器模型——從單執行緒阻塞到多執行緒非阻塞(上)

首先,伺服器必須初始化一個套接字伺服器,並繫結某個埠號並使之監聽客戶端的訪問。接著,客戶端1呼叫伺服器的服務,伺服器接收到請求後對其進行處理,處理完後寫資料回客戶端1,整個過程都是在一個執行緒裡面完成的。最後,處理客戶端2的請求並寫資料回客戶端2,期間就算客戶端2在伺服器處理完客戶端1之前就進行請求,也要等伺服器對客戶端1響應完後才會對客戶端2進行響應處理。

這種模型的特點在於單執行緒和阻塞I/O。單執行緒即伺服器端只有一個執行緒處理客戶端的所有請求,客戶端連線與伺服器端的處理執行緒比是n:1,它無法同時處理多個連線,只能序列處理連線。而阻塞I/O是指伺服器在讀寫資料時是阻塞的,讀取客戶端資料時要等待客戶端傳送資料並且把作業系統核心複製到使用者程式中,這時才解除阻塞狀態。寫資料回客戶端時要等待使用者程式將資料寫入核心併傳送到客戶端後才解除阻塞狀態。這種阻塞給網路程式設計帶來了一個問題,伺服器必須要等到客戶端成功接收才能繼續往下處理另外一個客戶端的請求,在此期間執行緒將無法響應任何客戶端請求。

該模型的特點:它是最簡單的伺服器模型,整個執行過程都只有一個執行緒,只能支援同時處理一個客戶端的請求(如果有多個客戶端訪問,就必須排隊等待),伺服器系統資源消耗較小,但併發能力低,容錯能力差。

多執行緒阻塞I/O模型

針對單執行緒阻塞I/O模型的缺點,我們可以使用多執行緒對其進行改進,使之能併發地對多個客戶端同時進行響應。多執行緒模型的核心就是利用多執行緒機制為每個客戶端分配一個執行緒。伺服器端開始監聽客戶端的訪問,假如有兩個客戶端傳送請求過來,伺服器端在接收到客戶端請求後分別建立兩個執行緒對它們進行處理,每條執行緒負責一個客戶端連線,直到響應完成。期間兩個執行緒併發地為各自對應的客戶端處理請求,包括讀取客戶端資料、處理客戶端資料、寫資料回客戶端等操作。

伺服器模型——從單執行緒阻塞到多執行緒非阻塞(上)

這種模型的I/O操作也是阻塞的,因為每個執行緒執行到讀取或寫入操作時都將進入阻塞狀態,直到讀取到客戶端的資料或資料成功寫入客戶端後才解除阻塞狀態。儘管I/O操作阻塞,但這種模式比單執行緒處理的效能明顯高了,它不用等到第一個請求處理完才處理第二個,而是併發地處理客戶端請求,客戶端連線與伺服器端處理執行緒的比例是1:1。

多執行緒阻塞I/O模型的特點:支援對多個客戶端併發響應,處理能力得到大幅提高,有較大的併發量,但伺服器系統資源消耗量較大,而且多執行緒之間會產生執行緒切換成本,同時擁有較複雜的結構。

=============廣告時間===============

公眾號的選單已分為“分散式”、“機器學習”、“深度學習”、“NLP”、“Java深度”、“Java併發核心”、“JDK原始碼”、“Tomcat核心”等,可能有一款適合你的胃口。

鄙人的新書《Tomcat核心設計剖析》已經在京東銷售了,有需要的朋友可以購買。感謝各位朋友。

為什麼寫《Tomcat核心設計剖析》

=========================

歡迎關注:

這裡寫圖片描述

相關文章