HTTP協(xié)議相關(guān)介紹及深度理解

總結(jié)了自己在實際工作場景中遇到的與http協(xié)議相關(guān)的一些內(nèi)容的理解。

HTTP協(xié)議相關(guān)介紹及深度理解

  Request & Response

  Request格式

比如:GET /api/index.json HTTP/1.1

比如:Accept: */*; User-Agent: Mozilla/4.0;……

[] 比如:id=1&timestamp=xxxxxx

  Response格式

比如:HTTP/1.1 200 OK

比如:Content-Type: application/json;……

[] 比如:{“id”:1,”username”:”testuser”}

  Status Code

  http的狀態(tài)碼有將近60個,我這里主要記錄一些常見的非正常情況下產(chǎn)生的狀態(tài)碼,在平常應(yīng)用中或多或少會碰到,有助于我們?nèi)ダ斫夂桶l(fā)現(xiàn)問題。

206 – 斷點下載時用到,客戶端請求了一部分內(nèi)容,服務(wù)器成功把這部分內(nèi)容返回給它,這時候就是用這個狀態(tài)。

301 – 永久跳轉(zhuǎn),原地址不存在了,url被指向到另一個地址。這個主要是搜索引擎相關(guān),影響爬蟲的檢索行為。

302 – 臨時跳轉(zhuǎn),服務(wù)器會返回一個新的url給客戶端,客戶端可以繼續(xù)訪問這個url來獲取內(nèi)容。

304 – 資源沒有改變,客戶端可以使用本地緩存的內(nèi)容,常見于靜態(tài)內(nèi)容訪問。

413 – 請求實體太大。常見的情況是上傳大文件,但超出了服務(wù)器(比如nginx)限制。或者請求頭或請求體超出了后端的server(比如tomcat)的設(shè)置(比如當(dāng)前域名下cookie太多,超出了請求頭限制)

416 – 跟斷點續(xù)傳有關(guān),客戶端請求的范圍超出了服務(wù)器上文件大小。

500 – 服務(wù)器內(nèi)部錯誤,不能返回正常的結(jié)果。比如最常見的應(yīng)用拋出空指針異常未進(jìn)行處理。

502 – 網(wǎng)關(guān)錯誤。常見的情況是反向代理后端的服務(wù)器(比如resin或tomcat)沒有啟動。

503 – 服務(wù)不可用。比如服務(wù)器負(fù)載太高或者服務(wù)器已經(jīng)停止服務(wù)。

504 – 網(wǎng)關(guān)超時。比如請求時長超出了服務(wù)器的響應(yīng)時間限制。

  Headers

  http headers分為請求頭(Request Header)和響應(yīng)頭(Response Header)兩類。下面是我們經(jīng)常用到的一些header.

  1.緩存控制

  在互聯(lián)網(wǎng)站的應(yīng)用中,緩存幾乎無處不在,在基于http的服務(wù)中,我們也可以對一些不常改變的內(nèi)容在客戶端進(jìn)行緩存,這樣在多次訪問中可以復(fù)用緩存內(nèi)容,加快訪問速度,提升用戶體驗。http的協(xié)議里規(guī)定了一些用于緩存控制的http消息頭:

Cache-Control(HTTP/1.1)/Pragma(HTTP/1.0):指示客戶端是否進(jìn)行緩存以及緩存的時間是多長。默認(rèn)值是private,也就是把內(nèi)容緩存在用戶私有空間。比如:Cache-Control:max-age=86400,must-revalidate,這是告訴客戶端所請求的資源緩存一天(max-age單位是秒,相對時間),過期之后必須進(jìn)行重新檢驗。

Expires:指定客戶端(如果不強制刷新的話)在多長時間里可以不向服務(wù)器發(fā)請求,直接讀本地緩存。

注意:

優(yōu)先級:Cache-Control > Expires;

詳細(xì)參數(shù)說明:http://condor.depaul.edu/dmumaugh/readings/handouts/SE435/HTTP/node24.html

不同瀏覽器的不同行為(刷新,后退,地址欄回車等)在實現(xiàn)上可能有差異;

Last-Modified/If-Modified-Since:Last-Modified是服務(wù)器端返回給客戶端的資源最后修改時間戳,這樣,客戶端在下次請求時(比如強制刷新)會帶上If-Modified-Since參數(shù)來校驗資源是否有更新,沒有更新的話服務(wù)器就返回304狀態(tài)碼,客戶端直接取本地緩存的資源。這個時候只有請求開銷,沒有網(wǎng)絡(luò)傳輸開銷。注意:時間戳必須是格林威治(GMT)時間,比如:Last-Modified:Sat, 19 Oct 2013 09:20:15 GMT

ETag/If-None-Match:ETag是根據(jù)文件屬性通過一定算法生成的資源標(biāo)識,也是用來確定客戶端請求的資源是否有更新。如果服務(wù)器返回了一個ETag值給客戶端,那么下次客戶端請求時會帶上If-None-Match參數(shù)來校驗資源是否更新,沒有更新的就返回304狀態(tài)碼。(效果基本等同于Last-Modified)

注意:

ETag需要計算,對于計算資源緊張的服務(wù)器來說是一種消耗,所以有些網(wǎng)站直接不使用ETag;

如果服務(wù)器在負(fù)載均衡后面,同一個資源的請求可能分發(fā)到不同的后端機器上,由于ETag的計算依賴于文件屬性,不同機器上內(nèi)容相同的文件可能生成的ETag不同,這樣就可能使本來內(nèi)容沒變的文件通過ETag校驗失敗。這里有兩種解決方案:一是etag計算不依賴于本地機器,比如直接算文件內(nèi)容的md5值;二是在負(fù)載均衡器上把相同的url請求分發(fā)到同一臺后端機器。

  在我們的實際業(yè)務(wù)場景下,http的緩存具有非常大的用途,下面列舉一些:

充分利用客戶端的資源,比如一些客戶端需要頻繁訪問的靜態(tài)文件,像LOGO,廣告圖等,完全可以緩存在客戶端本地。這樣可以減少網(wǎng)絡(luò)請求,加快客戶端展示,還能減少服務(wù)器請求的壓力。

我們的一些靜態(tài)內(nèi)容,比如新聞,博客等,在被搜索引擎爬蟲抓取的時候,通過控制緩存參數(shù),就可以減少爬蟲的抓取頻率,減少不必要的資源浪費。

如果我們的靜態(tài)資源使用了CDN,那么設(shè)置了http緩存就可以在CDN節(jié)點上保存一份文件,減少CDN的回源次數(shù),減少網(wǎng)絡(luò)延時和源站服務(wù)器壓力。

  2.斷點請求

Accept-Ranges:服務(wù)端支持?jǐn)帱c下載時會返回這個響應(yīng)頭給客戶端,當(dāng)客戶端知道這個以后就可以發(fā)送斷點請求了。

Content-Length:響應(yīng)信息的長度,告訴客戶端當(dāng)前請求返回了多少數(shù)據(jù)。這里要注意一下,用head方法提交請求時不會返回具體數(shù)據(jù),但是這個Content-Length會返回完整數(shù)據(jù)的大小。

Range/Content-Range:客戶端請求時提交名為Range的header,告訴服務(wù)器自己要請求哪部分的數(shù)據(jù)。比如:Range: bytes=0-1023表示請求第0到1023個字節(jié).然后服務(wù)器返回這1024個字節(jié)的內(nèi)容給客戶端,響應(yīng)頭中會帶上Content-Range。即:Content-Range: bytes 0-1023/4096,這個4096就是文件總大小。客戶端下次請求可以從第1024個字節(jié)處開始,Range: bytes=1024-xxxx

  3.編碼

Accept-Encoding/Content-Encoding:前者是客戶端支持接收的消息編碼類型。默認(rèn)是identity,可選值有g(shù)zip,compress等。后者是服務(wù)器端響應(yīng)信息的內(nèi)容編碼類型,常用的就是壓縮。壓縮的好處顯而易見,可以大大減少網(wǎng)絡(luò)傳輸?shù)拈_銷,相對于服務(wù)器端壓縮產(chǎn)生的cpu消耗,網(wǎng)絡(luò)傳輸?shù)臏p少顯然更實在。常見形式:Content-Encoding: gzip,deflate,compress.通常我們對html,js,css,xml,json之類的響應(yīng)結(jié)果可以進(jìn)行壓縮傳輸。

Transfer-Encoding:response header.響應(yīng)消息的傳輸編碼類型,規(guī)定了網(wǎng)絡(luò)傳輸?shù)男问健R话愣际窍旅孢@種形式:Transfer-Encoding: chunked。當(dāng)服務(wù)器產(chǎn)生動態(tài)內(nèi)容,不知道響應(yīng)信息的具體長度時,可以通過這個指定分塊進(jìn)行傳輸,處理多少數(shù)據(jù)就返回多少數(shù)據(jù),這樣不用等到數(shù)據(jù)都準(zhǔn)備好了一次性返回。結(jié)合上面的內(nèi)容編碼,比如gzip,可以分塊壓縮并進(jìn)行傳輸。另外,請注意,在使用這種編碼傳輸時,我們是看不到Content-Length的,因為內(nèi)容還沒有完全生成。

  4.其他

X-Forward-For:request header. 用來標(biāo)識用戶的真實ip,特別是通過代理(正向或反向)訪問服務(wù)器或是服務(wù)器在負(fù)載均衡設(shè)備后面的情況。格式:X-forward-For: client,proxy1,proxy2,…最左邊的是最接近客戶端的ip。

User-Agent:request header.服務(wù)器用來識別客戶端基本信息的請求頭。一般這個在識別搜索爬蟲的時候有用,某些場景下也可以用這個來做一些客戶端的統(tǒng)計。

Referer:request header.客戶端訪問服務(wù)器時,這個Referer來指定請求來源,比如是從哪個網(wǎng)站鏈接過來的,我們在一些統(tǒng)計中會經(jīng)常用到這個。另外,還有一個重要的用途就是在需要資源防盜鏈的場景中來過濾非法的請求來源(但是,這個referer是客戶端可以偽造的)。

Location:response header.在301/302狀態(tài)碼的響應(yīng)頭中,都會帶上這個Location頭,來指示客戶端用新的地址去訪問需要的資源。

Connection:request/response header.在http/1.1中,客戶端和服務(wù)端默認(rèn)都是保持連接的,也就是Connection: keep-alive.如果任何一方不想保持連接,都可以把這個值設(shè)置為close.默認(rèn)情況下,客戶端和服務(wù)端會保持一個長連接,這樣客戶端就可以用這個連接發(fā)送多次http請求,減少頻繁創(chuàng)建連接帶來的消耗。對于這個參數(shù),在服務(wù)端可能要做更多的設(shè)置,比如連接keep-alive的時間,服務(wù)器內(nèi)核的一些網(wǎng)絡(luò)參數(shù)設(shè)置(針對tcp)。

  Session和Cookie

  http請求是無狀態(tài)的請求,但是在我們的互聯(lián)網(wǎng)應(yīng)用中,經(jīng)常需要標(biāo)識用戶狀態(tài)信息來完成一些交互性的操作,比如用戶認(rèn)證要記錄用戶登錄狀態(tài),購物車應(yīng)用要記住用戶選擇的商品,廣告投放應(yīng)用要記錄用戶的歷史瀏覽行為等等。這里就會用到session和cookie了。

session:是指http請求-響應(yīng)的過程中客戶端與服務(wù)器端的交互狀態(tài),這些信息被保存在服務(wù)器端,比如內(nèi)存,數(shù)據(jù)庫等。每個session都有一個唯一標(biāo)識,由服務(wù)器生成,這個標(biāo)識也要在客戶端進(jìn)行保存,這樣客戶端在下次請求時可以帶上這個標(biāo)識,方便服務(wù)器判斷客戶端的狀態(tài)。

客戶端對session的支持:

通過cookie保存session id,在請求時發(fā)送給服務(wù)器。

通過url的參數(shù)攜帶session id與服務(wù)器通信。

通過表單的隱藏字段攜帶session id與服務(wù)器通信。

session共享的問題:

在分布式應(yīng)用中,我們的http server一般都架在反向代理或是負(fù)載均衡設(shè)備后面,這就會面臨一個session共享的問題。也就是同一個用戶的多個請求可能被分發(fā)到多個不同的機器,如果我們把session保存在機器本地內(nèi)存中的話,就無法在多個機器間共享用戶的session。這個問題,一般來說,我們可以有兩種方式來解決:

把session存放到分布式的內(nèi)存(eg:memcached)或是集中式存儲中(eg:database)。

在反向代理或負(fù)載均衡設(shè)備上把相同用戶的請求分發(fā)到同一臺機器(這里要處理好機器宕機后請求重新分配的問題)。

cookie:在客戶端保持狀態(tài)化信息,每個cookie內(nèi)容都屬于特定的域(domain)和路徑(path),出于安全考慮,不同域或路徑下的cookie不能共享。

會話cookie:沒有指定過期時間,保存在內(nèi)存,瀏覽器關(guān)閉后就失效。

持久cookie:指定了過期時間,保存在瀏覽器本地。

詳細(xì)內(nèi)容可以參考:http://en.wikipedia.org/wiki/HTTP_cookie

需要注意的是cookie會存在一些安全方面的問題。

  在這里我只是總結(jié)了自己在工作中遇到的與http協(xié)議相關(guān)的一些內(nèi)容的理解,http協(xié)議還有很多需要挖掘的東西,也需要不斷去探索,對http協(xié)議的理解將會給我們的開發(fā)應(yīng)用帶來很大的便利。

  最后,推薦兩個很NB的http調(diào)試工具:fiddler(windows)和charles(mac)有http代理功能,對于不是基于瀏覽器的http應(yīng)用(比如mobile app),可以用這兩個工具來監(jiān)控http請求。

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點贊11 分享