1. 程式人生 > >WEB應用之http協議和httpd閒聊

WEB應用之http協議和httpd閒聊

  什麼是web?在日常生活中我們常常聽到web這個詞,它到底是什麼呢?今天我們來聊一聊web應用http協議;相信生活在如今網際網路時代的我們,http這個協議應該對我們不是很陌生吧!比如雙十一雙十二我們去某寶、某東去搶購商品,它背後就是用一堆web伺服器通過http協議或https協議在給我們提供服務;簡單點說web服務就是一個C/S架構,服務端提供服務,客戶端通過http協議或https協議進行訪問,拿到服務端對應的資源,這就是web服務;所謂C/S架構就是客戶端和服務端架構;對於服務端一側在iso七層網路模型中應用層協議存在的意義是實現某一具體應用,通常情況下他們都會向核心空間註冊一眾所周知的服務埠,並監聽在某一地址,或多個地址上,對外提供服務;這也通常是C/S架構的軟體服務工作的特點;而http協議就是工作在應用層的80埠對外提供服務;對於客戶端一側就沒有監聽這一說了,通常情況下客戶端也是工作在應用層或者我們可以這樣理解,它實際不是工作在應用層;我們知道網路資源對於計算機來說只有核心的特權指令才能夠操作,而對於普通使用者來說,核心的功能我們必須在使用者空間提供一應用程式,通過應用程式對核心提供的API進行系統呼叫,從而實現操作網路資源的能力;實現客戶端的軟體有很多,圖形介面下常見的瀏覽器chrome呀,firefox呀,ie等等,這些程式都是web服務的客戶端,當然除此之外,像在Linux字元介面的web客戶端有,wget、curl、elinks等等;這些客戶端在使用者空間訪問服務端時,會隨機向核心註冊一埠,然後把自己的請求資訊通過封裝應用層首部,傳輸層,網路層,資料鏈路層,物理層,最後通過網絡卡傳送給服務端,服務端收到客戶端的請求會對客戶端封裝的報文,層層拆除,從而拿到客戶端的請求,拿到客戶端的請求後,然後封裝響應報文,封裝響應報文的過程類似客戶端封裝請求報文,先封裝應用層首部,然後傳輸層,網路層,資料鏈路層,物理層,然後傳送給客戶端;客戶端拿到報文後,層層拆封裝,最終拿到服務端的響應;這就是http協議的一次事務過程,無外乎就是客戶端請求,服務端響應;

  提示:以上是乙太網的封裝報文和解封裝報文的一個過程,http協議是應用層協議,通常情況下應用層就是上面三層;應用層是工作在使用者空間的,而下面四層是工作在核心空間,通常我們把下面四層稱為通訊子網層;這也是我們之前的iptables裡面經常提到的核心空間功能必須要由使用者空間程式對核心發起系統呼叫才能夠操作核心空間功能,所以像iptables、ipvsadm這類工具我們不稱他們叫服務,而是工具的原因;同理像web客戶端我們通常也只是叫它是工具,而不叫服務;通常所謂服務就是需要向核心註冊一埠,然後監聽在某一地址上,我們把這種工作在使用者空間(或者核心空間的功能)的程式叫服務,簡單點講服務需要被監聽,之所以要被監聽是因為通訊的需要;

  IPC(Inter-Process Communication,程序間通訊),所謂程序間通訊就是兩個程序互相交換資料;程序間通訊的方式有很多,比如記憶體共享、記憶體對映、BSD socket等等;其中最為常見的一種BSD socket,它允許位於不同主機(當然同一主機也是可以的,只不過同一主機用這種socket機制顯得不那麼高效)上的程序之間進行通訊;什麼叫socket?相信懂點網路程式設計的人都聽過這個詞吧! 所謂socket就是IP加埠,對於套接字可以分TCP套接字、udp套接字、raw套接字,它們通常情況下是通過socket API(封裝了核心中的socket通訊相關的系統呼叫)來建立不同的套接字型別;如SOCK_STREAM就是表示TCP套接字,SOCK_DGRAM就表示UDP套接字,SOCK_RAW就表示raw套接字;根據套接字所使用的地址格式,我們又可以分為IPV4的套接字、ipv6套接字和unix_sock(同一主機上的不同程序間基於socket套接字通訊使用的一種地址);例如AF_INET就表示ipv4格式的套接字,AF_INET6就表示ipv6套接字格式,AF_UNIX就表示unix_sock套接字格式;其中前兩者用於網路通訊,通常是位於不同主機間程序通訊,而後者unix_sock用於同一主機的兩個程序通訊較為常見;後者就是我們常見的sock檔案,例如mysql客戶端連線本地服務端就是用的這種機制;

  瞭解上面的底層通訊原理,我們再來聊聊今天的主題http吧

  http是hyper text transfer protocol的簡寫,它是應用層協議,預設工作在tcp協議的80埠,屬於文字協議;在http協議0.9版本中,它就只能用於傳輸html文字,也是在網際網路上使用的最原始的版本,功能相當簡陋;1.0版本引進了cache機制,MIME機制和更多的method,使得http協議一下子被廣泛使用,MIME是多用途網際網路郵件擴充套件型別,它的主要作用是讓一些非文字格式的附件能夠通過網際網路互相傳輸,並且在接收方接收後能夠將其還原成原有格式的附件的機制,什麼意思呢?它能夠讓一些非文字格式的附件在通過網際網路傳輸後還原成原來格式的附件的一種機制;這使得http協議可以傳輸非文字格式的資料,比如圖片、視訊、音樂等;所謂method就是客戶端請求服務端資源時資料傳輸請求的方法,在0.9版本http協議只支援GET這一種方法,在1.0版本中http協議支援了更多的請求方法,如GET、PUT、POST、DELETE、HEAD等等;在這之後有1.1版本,它主要是在1.0版本上增強了快取功能;隨後就是2.0,2.0主要是在1.1版本上做了很多優化,使得原有1.1本版的諸多效能問題得以解決,現在主流使用的http協議版本是1.1和2.0版本;

  http工作模式

  http的工作模式非常簡單,在上面我們也提到過,不外乎就是客戶端請求,服務端響應;其中我們把請求報文叫做http request響應報文叫做http response;對於客戶端的一次請求和服務端的一次響應響應我們把這一過程叫做http協議的一次事務;

  web資源:web resource

  web資源分靜態資源和動態資源,所謂靜態資源就是無需服務端做額外的處理的資源,我們叫靜態資源,什麼意思呢?客戶端請求的資源,在服務端是什麼樣通過http協議傳輸後到客戶端上就是什麼樣,我們就把這種不需要服務端額外處理的資源叫靜態資源,常見的靜態資源有.jpg, .png, .gif, .html, txt, .js, .css, .mp3, .avi等;所謂動態資源就與之相反,客戶端請求的資源通常是需要被程式執行或處理後,然後把執行結果或處理後的結果傳送給客戶端,我們把這種需要服務端通過某一執行程式作出處理的資源叫動態資源;常見的有.php.jsp.asp等;這裡還需要注意一點的是,我們平常看到的網頁資源往往不是單獨的一個資源,它可能是有很多資源組成,有動態的,也有靜態的,每個資源都需要單獨請求,如下所示;

  提示:可以看到我們訪問一個頁面的背後其實是有很多資源組成;

  資源的標識機制:URL

  所謂資源識別符號就是用於描述伺服器某特定資源的位置;簡單點就是用於告訴服務端客戶端要訪問的資源;通常情況下URL由協議加“://”加伺服器地址(可以是域名,或主機名)[:port](若服務端工作在非標準埠,我們還需要指定埠)然後加資源路徑或資源名稱(這裡的資源路徑指的是web服務的根路徑開始,而非檔案系統的根路徑)例如http://www.test.com/index.html這就是一個URL,客戶端介入這樣一個URL對應的服務端就知道客戶端請求的資源是www.test.com這臺主機上的index.html檔案,服務端就會把對應目錄下的檔案響應給客戶端;對於服務端它怎麼去自己的檔案系統上找index.html這個檔案,通常情況下是通過我們對服務端定義的documentroot來決定的,在nginx中我們可以通過root指令來指定虛擬主機的根目錄對應檔案系統路徑的對映;

  一次完整的http請求處理過程通常是有以下幾步來完成:

  (1) 建立或處理連線:接收請求或拒絕請求;
  (2) 接收請求:接收來自於網路上的主機請求報文中對某特定資源的一次請求的過程;

  http的響應模型,http的響應模型主要有單程序I/O模型、多程序、複用I/O模型和服用多程序模型,其中單程序I/O模型就是啟動一個程序處理使用者的請求,這意味著,一次只能處理一個請求,多個請求被序列響應;多程序I/O模型表示由父程序並行啟動多個子程序,每個子程序進行相應一個使用者請求;複用單程序I/O模型有兩個模式,多執行緒模式和事件驅動模式,前者表示一個程序生成N個執行緒,一個執行緒處理一個請求;而事件驅動模式中一個程序直接處理N個請求,沒有執行緒的說法;複用多程序I/O模型中,啟動多個程序,每個程序生成n個執行緒,每個執行緒處理一個請求,響應的請求數量是程序數量乘每個程序生成的執行緒數;
  (3) 處理請求:伺服器對請求報文進行解析,並獲取請求的資源及請求方法等相關資訊,根據方法,資源,首部和可選的主體部分對請求進行處理

    元資料:請求報文首部
    <method> <URL> <VERSION>
    HEADERS 格式 name:value
    <request body>

      ……

    示例:

  (4) 訪問資源:獲取請求報文中請求的資源;伺服器獲取請求報文中請求的資源web伺服器,即存放了web資源的伺服器,負責向請求者提供對方請求的靜態資源,或動態執行後生成的資源;資源放置於本地檔案系統特定的路徑:DocRoot

    示例:如果我們將web資源根目錄對映成檔案系統上的/var/www/html,即www.test.com/   ---->>  /var/www/html,使用者訪問www.test.com/index.html,就相當於訪問檔案系統上的/var/www/html/index.html,通常情況下web伺服器資源路徑對映方式有4種,第一種是通過定義docroot來指定,第二種是alias別名來指定,第三種是虛擬主機的docroot第四種是使用者家目錄的docroot

  (5) 構建響應報文:一旦Web伺服器識別除了資源,就執行請求方法中描述的動作,並返回響應報文。響應報文中 包含有響應狀態碼、響應首部,如果生成了響應主體的話,還包括響應主體;

    響應實體:如果事務處理產生了響應主體,就將內容放在響應報文中回送過去。響應報文中通常包括:描述了響應主體MIME型別的Content-Type首部,描述了響應主體長度的Content-LengthContent-Type首部和實際報文的主體內容

    示例:

  (6) 傳送響應報文:Web伺服器通過連線傳送資料時也會面臨與接收資料一樣的問題。伺服器可能有很多條到各個客戶端的連線,有些是空閒的,有些在向伺服器傳送資料,還有一些在向客戶端回送響應資料。伺服器要記錄連線的狀態,還要特別注意對持久連線的處理。對非持久連線而言,伺服器應該在傳送了整條報文之後,關閉自己這一端的連線。對持久連線來說,連線可能仍保持開啟狀態,在這種情況下,伺服器要正確地計算Content-Length首部,不然客戶端就無法知道響應什麼時候結束了;
  (7) 記錄日誌:最後,當事務結束時,Web伺服器會在日誌檔案中新增一個條目,來描述已執行的事務;

   HTTP伺服器應用

  http伺服器程式有httpd、nginx、lighttpd等nginx相關使用和說明可參考本人前面的部落格https://www.cnblogs.com/qiuhom-1874/category/1646010.html;接下來我們著重來說說httpd;

  httpd是20世紀90年代初,國家超級計算機應用中心NCSA開發,1995年開源社群釋出apache(a patchy server)它是一款高度模組化,支援動態加解除安裝模組,支援多路處理模組,所謂多路處理模組就是httpd的三種響應模型;

  第一種是prefork多程序模型,每個程序響應一個請求,一個主程序,主程序程負責生成子程序以及回收子程序、套接字的建立和接收請求並將其派發給某個子程序處理;n個子程序(一個子程序中生成一個執行緒處理一個請求),子程序主要用於處理請求;工作模型:會預先生成幾個空閒程序,隨時等待用於響應使用者請求;最大空閒和最小空閒;

  第二種是worker多程序多執行緒模型,在這種模型中每個執行緒處理一個使用者請求;同樣的它也會由一個主程序負責生成子程序,套接字的建立和接收請求並將請求派發給某個子程序進行處理;n個子程序,和上面的profork不同的是,這裡的子程序主要負責生成多個執行緒,而每個執行緒處理一個請求;這樣一來在這種模型中併發響應數量就是n個子程序乘每個子程序生成的M個執行緒;

  第三種是event:事件驅動模型,多程序模型,一個主程序生成m個子程序,每個程序直接響應n個請求,併發響應請求:m*n,有專門的執行緒來管理這些keep-alive型別的執行緒,當有真實請求時,將請求傳遞給服務執行緒,執行完畢後,又允許釋放。這樣增強了高併發場景下的請求處理能力

以上就是httpd的一些簡單介紹,在後續的文章中我會持續更新httpd的其他用法和配置指令的說明,有感興趣的朋友可以關注關注,共同探