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的其他用法和配置指令的說明,有感興趣的朋友可以關注關注,共同探討;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM