HTTP權威指南學習筆記
第一部分 HTTP:WEB的基礎
第一章 HTTP概述
媒體類型
http給每種要通過web傳輸的對象都打上了名為MIME(Multipurpose Internet Mail Extension,多用途網際網路郵件擴充)類型的資料格式标簽。
Web伺服器會為所有HTTP對象資料附加一個MIME類型。當Web浏覽器從伺服器中取回一個對象時,回去檢視相關的MIME類型,看看它是否知道應該如何處理這個對象。
MIME類型是一種文本标記,表示一種主要的對象類型和一個特定的子類型,中間由斜杠來分隔。
1、HTML格式的文本文檔由 text/html 類型來标記
2、普通的ASCII文本文檔由 text/plain 類型來标記
3、JPEG版本的圖檔為 image/jpeg 類型
4、GIF格式的圖檔為 image/gif類型
5、Apple的QuickTime電影為 video/quidktime 類型
6、微軟的PowerPoint示範檔案為 application/vnd.ms-powerpoint 類型
URI
伺服器資源名被稱為統一資源辨別符(Uniform Resource Identifier,URI).URI就像網際網路上的郵政位址一樣,在世界範圍内唯一辨別并定位資訊資源。
例如一個圖檔資源的URI:
http://www.baidu.com/specials/sky.gif
當給定了URI,HTTP就可以解析出對象。URI有兩種形式,分别稱為URL和URN。
URL
統一資源定位符(URL)是資源辨別符最常見形式。它描述了一台特定伺服器上的某資源的特定位置。
URL說明了協定、伺服器和本地資源。如下圖:

URL執行個體:
大部分的URL都遵循一種标準格式,這種格式包含三個部分:、
①方案(scheme),說明了通路資源所使用的協定類型。這部分通常是HTTP協定(http://)
②給出伺服器的網際網路位址(www.baidu.com)
③其餘部分指定了WEB伺服器上的某個資源(/specials/sky.gif)
現在,幾乎所有的URI都是URL。
URN
URI的第二種形式就是URN(統一資源名)。URN是作為特定内容的唯一名稱使用的,與目前的資源所在地無關。使用這些與位置無關的URN,就可以将資源四處搬移。通過URN,還可以用同一個名字通過多種網絡通路協定來通路資源。
例如:RFC 2141 無論在何處,甚至可以複制到多個地方,都可以用以下URN來命名:
urn:ietf:rfc:2141
URN仍處于試驗階段。
*事務*
一個HTTP事務由一條請求指令和一個響應結果組成。這種通信是通過名為HTTP封包的格式化資料塊進行的。
方法
HTTP支援幾種不同的請求指令,這些指令被稱為HTTP方法(HTTP method)。
常見的HTTP方法:
GET—-從伺服器向客戶的發送命名資源
PUT—-将來自客戶的的資料存儲到一個命名的伺服器資源中去
DELETE—-從伺服器中删除命名資源
POST—-将用戶端資料發送到一個伺服器網關應用程式
HEAD—-僅發送命名資源響應中的HTTP首部
狀态碼
每條HTTP響應封包傳回時都會攜帶一個狀态碼。狀态碼是一個三位數字的代碼,告知用戶端請求是否成功,或者是否需要采取其他動作。
常見狀态碼:
200—-OK,文檔傳回正确
302—-Redirect,重定向,到其他地方擷取資源
404—-Not Found,無法找到這個資源
WEB頁面中可以包含多個對象
一個WEB頁面是一組資源的集合。web浏覽器會釋出一系列HTTP事務來擷取并顯示一個包含了豐富資源的頁面。
*封包*
HTTP封包是由一行一行的簡單字元串組成。它是純文字,并非二進制代碼。
HTTP封包包含以下三個部分:
1、起始行
封包的第一行,在請求封包中用來說明要做些什麼。在響應封包中說明出現了什麼情況。
2、首部字段
起始行後面有零個或者多個首部字段。每個字段都包含一個名字和一個值,為了便于解析,兩者之間用冒号(:)分隔。首部以一個空行結束。
3、主體
空行之後就是可選的封包主體了,其中包含了所有類型的資料。請求主體中包括了要發送個web伺服器的資料;響應主體中裝載了要傳回給用戶端的資料。起始行和首部都是文本形式且都是結構化的,而主體則不同,主體可以包含任意的二進制資料和文本。
*連接配接*
TCP/IP
HTTP是個應用層協定,聯網的細節都交給了TCP/IP協定。
TCP提供:
無差錯的資料傳輸;按序傳輸;未分段的資料流(可以在任意時刻以任意尺寸将資料發送出去)
連接配接、IP位址及端口号
在HTTP用戶端向伺服器發送封包之前,需要用網際協定(Internet Protocol,IP)位址和端口号在用戶端與伺服器之間建立一條TCP/IP 連接配接。
協定版本
HTTP/0.9
HTTP的1991原型版本。僅支援GET方法,不支援多媒體内容的MIME類型、各種HTTP首部,或者版本号。
HTTP/1.0
1.0是第一個得到廣泛使用的HTTP版本。HTTP/1.0添加了版本号、各種HTTP首部、一些額外的方法以及對多媒體對象的處理。
HTTP/1.0+
由很多流行的web用戶端和伺服器向HTTP中添加各種特性,包括keep-alive連接配接、虛拟主機支援、以及代理連接配接支援等,稱為非官方的事實标準。這種的HTTP擴充版本通常稱為HTTP/1.0+
HTTP/1.1
這個版本重點關注的是校正HTTP設計中的結構性缺陷,明确語義,引入重要的性能優化措施,并删除一些不好的特性。它還包含了對20世紀90年代末正在發展中的更複雜的WEB應用程式和部署方式的支援。它也是目前使用的版本。
HTTP-NG(HTTP/2.0)
是HTTP/1.1後繼結構的原型建議,它重點關注的是性能的大幅優化以及更強大的服務邏輯遠端執行架構。它的研究工作終止于1998年。
*WEB的結構元件*
代理
代理位于用戶端和伺服器之間,接收所有用戶端的HTTP請求,并将這些請求轉發給伺服器(可能會對請求進行修改之後轉發)。
緩存
WEB緩存(cache)或代理緩存是一種特殊的HTTP代理伺服器,可将經過代理傳送的常用文檔複制儲存起來。下一個請求同一文檔的用戶端就可以享受緩存的私有副本所提供的服務了。
網關
網關(gateway)是一種特殊的伺服器,作為其他伺服器的中間實體使用。通常用于将HTTP流量轉換成其他的協定。網關接受請求時就好像自己是資源的源端伺服器一樣,用戶端可能并不知道自己在與一個網關進行通信。
隧道
隧道(tunnel)是建立起來之後,就會在兩條連接配接之間對原始資料進行盲轉發的HTTP應用程式。通常用來在一條或多條HTTP連接配接上轉發非HTTP資料,轉發時不會窺探資料。
HTTP隧道一種常見用途是通過HTTP連接配接承載加密的安全套接字層(SSL,Secure Sockets Layer)流量。這樣SSL流量就可以穿過隻允許WEB流量通過的防火牆了。
Agent代理
Agent代理是代表使用者發起HTTP請求的用戶端程式。所有釋出WEB請求的應用程式都是HTTP Agent代理。web浏覽器。
第二章 URL與資源
浏覽網際網路資源
URL 可以通過HTTP之外的其他協定來通路資源。它們可以指向網際網路上的任意資源。比如個人郵箱賬戶。或者其他協定FTP、或者從流視訊伺服器下載下傳電影
rtsp://www.xxxx.com:554/cto_video
URL的文法
大多數URL方案的URL文法都建立在這個由9部分構成的通用格式上:
://:@:/;?#
方案
實際上是規定如何通路指定資源的主要辨別符,它會告訴負責解析URL的應用程式應該使用什麼協定。方案元件必須以一個字母符号開始,由第一個“:”符号将其與URL的其餘部分分隔開來,大小寫無關。
主機與端口
主機元件辨別了網際網路上能夠通路資源的主控端器。可以用主機名或者IP位址來表示。端口元件辨別了伺服器正在監聽的網絡端口。
使用者名和密碼
常見的如FTP伺服器需要使用者名和密碼才允許使用者通路。
如果某應用程式使用的URL方案要求使用者輸入使用者名和密碼,比如FTP,但是使用者并未提供,它通常會插入一個預設的使用者名和密碼。比如FTP,會插入anonymous(匿名使用者)作為你的使用者名,并發送一個預設密碼(IE會發送IEUser,Netscapegoat Navigator則會發送mozilla)。
路徑
路徑元件說明了資源位于伺服器的什麼地方,路徑通常很像一個分級的檔案系統路徑。可以用“/”将HTTP URL 的路徑元件劃分成一些路徑段(path segment),每個路徑段都有自己的參數(param)元件。
參數
參數元件就是URL中的鍵值對清單,有字元“:”将其與URL的其他部分(以及各鍵值對)分隔開來,它們為應用程式提供了通路資源所需的所有附加資訊。
ftp://prep.ai.mit.edu/pub/gnu;type=d
http://www.joes-hardware.com/hammers;sale=false/index.html;graphics=true
查詢字元串
比如資料庫服務,可以通過提問題或者進行查詢來縮小所請求資源類型範圍。
http://www.joes-hardware.com/inventory-check.cgi?item=12731
“?”右邊的内容稱為查詢元件,它和辨別網關資源的URL路徑元件一起被發送給網關資源,基本上可以将網關當做通路其他應用程式的通路點。
按照正常,很多網關都希望查詢字元串以一系列“鍵/值”對的形式出現,鍵值對之間用“&”分隔。
片段
有些資源類型,比如HTML,除了資源級之外,還可以做進一步的劃分。比如一個帶章節的大型文本文檔,資源的URL會指向整個文檔,但是理想情況是能夠指向資源中那些章節。
為了引用部分資源或者資源的一部分,URL支援使用片段(frag)元件來表示一個資源内部的片段。比如:http://www.xxxx.com/tools.html#drills
HTTP伺服器通常隻處理整個對象,而不是對象的片段,用戶端不能将片段傳送給伺服器。浏覽器從伺服器擷取了整個資源後,會根據片段來顯示感興趣的那部分資源。
URL快捷方式
WEB用戶端可以了解并使用集中URL快捷方式。相對URL是在某資源内部指定一個資源的便捷縮略方式。很多浏覽器還支援URL 的“自動擴充”。
相對URL
相對URL是不完整的,要從相對URL中擷取通路資源所需的全部資訊,就必須相對于另一個,被稱為基礎的URL進行解析。相對URL是URL的一種便捷縮略記法。
上圖中的./hammers.html其實是個合法的相對URL,可以相對于它所在文檔的URL對其進行解析,本例中就是/tools.html
相對URL隻是URL的片段或是一小部分,處理URL的應用程式(浏覽器)要能在兩者之間進行轉換。
需要注意,相對URL為保持一組資源的便攜性提供了一種便捷方式。如果使用相對URL,就可以在搬移一組文檔的同時,仍然保持連結的有效性,因為相對URL是相對于新基礎進行解析的,這樣就能實作在其他伺服器上提供鏡像之類的功能了。
1、基礎URL
轉換處理的第一步就是找到基礎URL,基礎URL 作為參考點可以來自以下幾個不同的地方:
①在資源中顯示提供
有些資源會顯式的指定基礎URL,比如,HTML文檔中可能包含一個定義了基礎 URL的HTML标記,通過它來轉換那個文檔中所有的相對URL。
②封裝資源的基礎URL
如果在一個沒有顯式指定基礎URL的資源中發現了一個相對URL,如上例,可以将它所屬資源的URL作為基礎。
③沒有基礎URL
某些情況下,沒有基礎URL,這通常意味着你有一個相對URL,但有時可能隻是一個不完整或損壞了的URL。
2、解析相對引用
要将相對URL轉換為一個絕對URL,下一步就是将相對URL和基礎URL劃分成元件段。
實際上,這樣隻是在解析URL,但這種做法會将其劃分成一個個元件,是以通常會稱作分解(decomposing)URL。隻要将基礎和相對URL劃分成了元件,就可以用如下的算法完成轉換。
自動擴充URL
也就是常見的自動補全URL。
有兩種方式:
1、主機名擴充
在主機名擴充中,隻要有些小提示,浏覽器通常就可以在沒有幫助的情況下将你輸入的主機名擴充為完整的主機名。比如輸入yahoo,浏覽器自動建構出www.yahoo.com
但是,這些主機名擴充技巧可能會為其他一些HTTP應用程式帶來問題,比如代理。
2、曆史擴充
将輸入的URL與曆史記錄中URL的字首進行比對,并提供一些完整的選項。
各種令人頭疼的字元
URL是可移植的(portable)。
URL字元集
預設是US-ASCII字元集。有些URL會包含任意的二進制資料。是以加入了轉義序列,通過轉義序列,就可用US-ASCII字元集的有限子集對任意字元值或資料進行編碼了。
編碼機制
轉義法—-包含一個百分号(%),後面跟兩個表示字元的ASCII碼的十六進制數。
例如:
字元限制
在URL中,有幾個字元被保留起來有着特殊的含義。有些字元不在定義的US-ASCII可列印字元集中。還有些字元會與某些網際網路網關和協定産生混淆,是以不贊成使用。
方案的世界
HTTP封包
HTTP封包是在HTTP應用程式之間發送的資料塊。這些資料塊以一些文本形式的元資訊(meta-information)開頭,這些資訊描述了封包的内容以及含義。
HTTP使用術語流入(inbound)和流出(outbound)來描述事務處理(transaction)的方向。封包流入源端伺服器,工作完成後,會流回使用者的Agent代理中。如下圖:
封包的組成部分
HTTP封包是簡單的格式化資料塊。每條封包都包含一條來自用戶端的請求,或者一條來自伺服器的響應。由三個部分組成:對封包描述的起始行(start line)、包含屬性的首部(header)塊,以及可選的、包含資料的主體(body)部分。
起始行和首部就是由行分隔的ASCII文本。每行都以一個由兩個字元組成的行終止符作為結束,其中包括一個回車符和換行符。這個行終止序列可以寫作CRLF。封包的主體是一個可選的資料塊。與起始行和首部不同的是,主體中可以包含文本或二進制資料,也可以為空。
封包的文法
所有的HTTP封包都可以分為:請求封包(request message)和響應封包(response message)。請求封包會向WEB伺服器請求一個動作。響應封包會将請求的結果傳回給用戶端。
各部分的簡要描述:
1、方法(method)
用戶端希望伺服器對資源執行的動作,是一個單獨的單詞。
2、請求URL
命名了所請求的資源,或者URL路徑元件的完整URL。
3、版本
封包所使用的HTTP版本
HTTP/.
主要版本号 次要版本号 都是整數。
4、狀态碼
這三位數字描述了請求過程中所發生的情況。每個狀态碼的第一位數字都用于描述狀态的一般類别(成功、出錯等)
5、原因短語(reason-phrase)
數字狀态碼的可讀版本,包含行終止序列之前的所有文本。
6、首部
可以有零個或多個首部,每個首部都包含一個名字,後面跟着一個冒号(:),然後是一個可選的空格,接着是一個
值,最後是一個CRLF。首部是由一個空行(CRLF)結束的,表示了首部清單的結束和封包主體部分的開始。
7、實體的主體部分(entity-body)
這個部分包含一個由任意資料組成的資料塊。
起始行
1、請求行
請求封包請求伺服器對資源進行一些操作。請求封包的起始行或稱為請求行,包含了一個方法和一個請求URL,還包含
了HTTP的版本,用來告知伺服器,用戶端使用的是哪種HTTP。
2、響應行
響應封包承載了狀态資訊和操作産生的所有結果資料,将其傳回個用戶端。它的起始行或稱為響應行,包含了響應報
文使用的HTTP版本、數字狀态碼、以及描述操作狀态的文本形式的原因短語。
3、方法
請求的起始行以方法作為開始,方法用來告知伺服器要做些什麼。
除了這些方法,其他伺服器可能還會實作一些自己的請求方法,這些附加的方法是對HTTP規範的擴充,是以被稱作擴
展方法。
4、狀态碼
狀态碼用來告知用戶端,發生了什麼事情。它位于響應的起始行中。通過三位數字代碼對不同狀态碼進行分類。200
到299之間的狀态碼表示成功,300到399之間的表示資源已經被移走。400到499之間的表示用戶端的請求出錯了。
500到599之間的表示伺服器出錯了。
5、原因短語
原因短語是響應起始行中的最後一個元件。它為狀态碼提供了文本形式的解釋。比如 HTTP/1.0 200 OK 中的OK 就是
原因短語。
6、版本号
使用版本号的目的是為使用HTTP的應用程式提供線索,以便互相了解對方的能力和封包格式。
首部
1、首部分類
通用首部–既可以出現在請求封包中,也可以出現在響應封包中。
請求首部
響應首部
實體首部–描述主體的長度和内容,或者資源自身。
擴充首部–規範中未定義的。
2、首部延續行
将長的首部行分為多行可以提高可讀性,多出來的每行前面至少要有一個空格或制表符(tab)
例如:
HTTP/1.0 200 OK
Content-Type: image/gif
Content-Length: 8572
Server: Test Server
Version 1.0
這個例子中,響應封包裡的server首部,其完整的值為: Test Server Version 1.0
版本0.9的封包
該封包也由請求和響應組成,但請求中隻包含方法和請求URL,響應中隻包含實體。他沒有版本資訊、狀态碼、原因短
語,也沒有首部。
方法
安全方法
HTTP定義了一組被稱為安全方法的方法。GET方法和HEAD方法都被認為是安全的。意味着使用GET和HEAD的HTTP請求都不會産生什麼動作。不産生動作就意味着HTTP請求不會在伺服器上産生什麼結果。
GET
用于請求伺服器發送某個資源
HEAD
與GET類似,但伺服器在響應中隻傳回首部。不傳回實體的主體部分。可以在不擷取資源的情況下了解資源的情況;通過檢視響應中的狀态碼,看看某個對象是否存在;測試資源是否被修改了。
PUT
向伺服器寫入文檔,有些釋出系統允許使用者建立WEB頁面,并用PUT直接将其安裝的WEB伺服器上。
PUT方法的語義就是讓伺服器用請求的主體部分來建立一個由所請求的URL命名的新文檔,如果那個URL存在的話,就用這個主體來替代它。
POST
該方法起初用來向伺服器輸入資料。實際上通常用來支援HTML的表單。
TRACE
用戶端發起一個請求時,這個請求可能要穿過防火牆、代理、網關或其他應用程式。每個中間節點都可能修改原始的HTTP請求。TRACE方法允許用戶端在最終請求發送給伺服器時,看它變成了什麼樣子。 TRACE請求會在目的伺服器端發起一個”環回“診斷。行程最後一站的伺服器會彈回一條TRACE響應,并在響應主體中攜帶它收到的原始請求封包。
TRACE方法主要用于診斷—-用于驗證請求是否如願穿過了請求/響應鍊。可以檢視代理和其他應用程式對使用者請求所産生效果。 缺點:它假定中間應用程式對各種不同類型請求的處理是相同的。但很多HTTP應用程式會根據不同的方法做不同的事情,比如代理會将POST直接發送給伺服器,而将GET發送給另外一個HTTP應用程式(比如WEB緩存)。但TRACE并不提供區分這些方法的機制。TRACE請求不能帶有實體的主體部分,響應的實體的主體部分是伺服器收到的請求的精确副本。
OPTIONS
該方法請求WEB伺服器告知其支援的各種功能。可以詢問伺服器通常支援哪些方法,或者對某些特殊資源支援哪些方法。
DELETE
請伺服器删除請求URL所指定的資源,但是用戶端應用程式無法保證删除操作一定會被執行。因為HTTP規範允許伺服器在不通知用戶端的情況下撤銷請求。
擴充方法
如果能夠在不破壞端到端行為的情況下将帶有未知方法的封包傳遞給下遊伺服器的話,代理會嘗試着傳遞這些封包的,否則,它們會以501 Not Implemented(無法實作)狀态碼進行響應。
狀态碼
狀态碼為用戶端提供了一種了解事務處理結果的便捷方式。
100-199—-資訊性狀态碼
HTTP/1.1向協定中引入了資訊性狀态碼。這些狀态碼較新。
1、用戶端與100 Continue
如果用戶端在向伺服器發送一個實體,且願意在發送實體之前等待100 Continue響應,那麼用戶端就要發送一個攜帶了值為100 Continue Expect 首部。發送了值為100 Continue的Expect首部的用戶端不應該永遠等待伺服器發送100 Continue響應。超過一段時間之後,用戶端應該直接将實體發送出去。
2、伺服器與100 Continue
有些出錯的伺服器可能在沒有收到100 Continue的Expect首部的請求,也會發出響應碼。 出于某種原因,伺服器在發送100 Continue 響應之前就收到了部分(或全部)實體,就說明用戶端已經決定繼續發送資料了,這樣,伺服器就不需要在發送這個狀态碼了。但是伺服器讀完請求之後,還是應該為請求發送一個最終狀态碼(它可以跳過100 Continue狀态)。 如果伺服器收到了帶有100 Continue的請求,而且它決定在讀取實體的主體部分之前結束請求(比如因為出錯),就不應該僅僅是發送一條響應并關閉連接配接,因為這樣會妨礙用戶端接收響應。
3、代理與100 Continue
代理收到該請求後,若它知道下一跳伺服器是HTTP/1.1相容的,或者并不知道下一跳伺服器與那個版本相容,都應該将Expect首部放在請求中向下轉發。如果它知道下一跳伺服器隻能與HTTP/1.1之前的版本相容,就應該以417 Expectation Failed錯誤進行響應。(還有一種方法,就是想用戶端傳回100 Continue ,向伺服器發送時删掉Expect首部)
200~299—-成功狀态碼
300~399—-重定向狀态碼
重定向狀态碼要麼告知用戶端使用替代位置來通路他們所感興趣的資源,要麼就提供一個替代的響應而不是資源的内容。
可以通過某些重定向狀态碼對資源的應用程式本地副本與源端伺服器上的資源進行驗證。
當HTTP/1.0用戶端發起一個POST請求,并在響應中收到302狀态碼,它會接受Location首部的重定向URL,并向那個URL發起一個GET請求(而不是POST請求)。 在HTTP/1.1中使用303狀态碼來實作上述行為,為了避開這個問題,對于HTTP/1.1 用戶端,用307狀态碼取代302進行臨時重定向。這樣伺服器就可以将302儲存起來為HTTP/1.0用戶端使用了。
400~499—-用戶端錯誤狀态碼
500~599—-伺服器錯誤狀态碼
首部
五個主要的類型:
一、通用首部
比如Date首部,每一端都可以用它來說明建構封包的時間和日期:
Date: Tue, 3 Oct 1974 02:16:00 GMT
通用緩存首部—HTTP/1.0引入了第一個允許HTTP應用程式緩存對象本地副本的首部。
二、請求首部
請求封包特有,比如Accept首部用來告知伺服器用戶端會接受與其請求相符的任意媒體類型:
Accept: /
條件請求首部
安全請求首部
代理請求首部
三、響應首部
比如Server首部用來告知用戶端與哪一個版本的伺服器進行互動。
Server: TiKi-Hut/1.0
1、協商首部
資源有多種表示方法,比如某文檔的法語和德語譯稿,HTTP/1.1可以為伺服器和用戶端提供對資源的協商能力。
2、安全響應首部
四、實體首部
比如可以用實體首部來說明實體主體部分的資料類型。通過下列Content-Type首部告知應用程式,資料是以iso-latin-
I 字元集表示的HTML文檔。
Content-Type: text/html; charset=iso-latin-1
實體首部提供了有關實體及其内容的大量資訊,從有關對象類型的資訊,到能夠對資源使用的各種有效的請求方法。
1、内容首部—–提供了與實體内容有關的特定資訊,說明其類型、尺寸以及處理它所需的其他有用資訊。
2、實體緩存首部—-提供了與被緩存實體有關的資訊——比如,驗證已緩存的資源副本是否仍然有效所需的資訊,以
及更好地估計已緩存資源何時失效所需的線索。
五、擴充首部
非标準首部,由應用程式開發者建立,還未添加到已準許的HTTP規範中。即使不知道這些擴充首部的含義,HTTP程
序也要接受它們并轉發。
第四章 連接配接管理
一、TCP連接配接
4.1.1 TCP的可靠資料管道
HTTP連接配接實際上就是TCP連接配接和一些使用連接配接的規則。TCP為HTTP提供了一條可靠的比特傳輸管道。
4.1.2 TCP流是分段的、由IP分組傳送
TCP的資料是通過名為IP分組(或IP資料報)的小資料塊來發送的。這樣的話,如圖所示,HTTP就是協定棧的最頂層
了,其安全版本HTTPS就是在HTTP和TCP之間插入了一個(稱為TLS或者SSL的)密碼加密層。
4.1.3 保持TCP連接配接的正确運作
在任意時刻計算機都可以有幾條TCP連接配接處于打開的狀态。TCP是通過端口号來保持這些連接配接的正确運作的。TCP連接配接
是通過4個值來識别的:
<源IP,源端口,目的IP,目的端口> 這4個值一起唯一确定一條連接配接。
4.1.4 用TCP套接字程式設計
4.2 對TCP性能的考慮
4.2.1 HTTP事務的時延
事務時延的主要原因:
1、 若之前未通路過某主機,則需要DNS解析,花費數十秒。但大多數HTTP用戶端都有一個小的DNS緩存,用來儲存
近期的IP位址。
2、 TCP連接配接建立大概一二秒,但如果有數百個HTTP事務,這個值會快速疊加。
3、 建立連接配接後,開始發送HTTP請求,到達server 來處理的時延
4、 server回送HTTP響應封包時延
4.2.2 性能聚焦區域
TCP連接配接建立握手
TCP慢啟動擁塞控制
資料聚集的Nagle算法
用于捎帶确認的TCP延遲确認算法
TIME_WAIT時延的端口耗盡
4.2.3 TCP連接配接的握手時延
通常HTTP事務都不會交換太多資料。此時 SYN/SYN-ACK握手會産生一個可測量的時延。TCP連接配接的ACK分組通常足
夠大,可以承載整個HTTP請求封包。而且很多HTTP伺服器響應封包都可以放入一個IP分組中去(比如小型HTML檔案
或是對浏覽器高速緩存請求産生的304響應)。 這樣就會導緻小的HTTP事務可能會在TCP建立上花費%50多的時間。
4.2.4 延遲确認
TCP的确認機制。确認封包很小,是以TCP允許在發往相同方向的輸出資料分組中對其進行”捎帶“。TCP将傳回的确
認資訊與輸出的資料分組結合在一起,可以有效利用網絡。
為了增加确認封包找到同向傳輸資料分組的可能性,很多TCP棧都實作了一種”延遲确認“算法。該算法會在一個特定
的視窗時間(100–200毫秒)内将輸出确認存放在緩沖區,以尋找能夠捎帶它的輸出資料分組,若沒有找到,則單獨
傳送。
但是,HTTP具有雙峰特征的請求-應答行為降低了捎帶資訊的可能,是以延遲确認算法會引入相當大的時延。
4.2.5 TCP慢啟動
TCP起初限制連接配接的最大速度,若資料傳輸成功,随着時間推移提高傳輸速度。
慢啟動限制了一個TCP端點在任意時刻可以傳輸的分組數。每成功傳輸1個,發送方就獲得了可以傳送2個的權限。以
此類推,将會是4個,這樣的方式稱為”打開擁塞視窗”。由于存在擁塞控制,新連接配接的傳輸速度就比已經交換過資料
的連接配接慢。
4.2.6 Nagle算法與TCP_NODELAY
TCP有一個資料流接口,應用程式可以通過它将任意大小的資料放入TCP棧中——即使一次放一個位元組。但是每個TCP
段中都至裝載了40個位元組的标記和首部,這樣大量的包含少資料的分組就會影響網絡性能。
Nagle算法試圖在發送一個分組之前,将大量的TCP資料綁定在一起,提高網絡效率。 RFC 896
該算法鼓勵發送全尺寸(LAN上為約1500位元組,網際網路上是幾百位元組)的段。隻有當所有其他分組都被确認後,此算
法才允許發送非全尺寸的分組。若其他分組仍在傳輸中,就将那部分資料緩存起來。隻有當挂起分組被确認,或者緩
存中積累了足夠發送一個全尺寸分組的資料時,才會将緩存資料發送出去。
該算法會引發幾種HTTP性能問題,首先,小的HTTP封包可能無法填滿一個分組,可能會因為等待那些永遠不會到來
的額外資料而産生延遲。其次,Nagle算法與延遲确認之間的互動存在問題——Nagle算法會阻止資料的發送,直到有
确認分組抵達為止,但是确認分組本身會被延遲确認算法延遲100~200毫秒。
HTTP應用程式通常會在自己的棧中設定參數TCP_NODELAY禁用此算法。但這樣就要確定向TCP寫入大塊資料。
4.2.7 TIME_WAIT累積與端口耗盡
當TCP端點關閉TCP連接配接時,會在記憶體中維護一個小的控制塊,用來記錄最近所關閉連接配接的IP位址和端口号。通常維持
是所估計的最大分段使用期的兩倍左右(2MSL,通常為2分鐘),以確定在這段時間内不會建立具有相同位址和端口
的連接配接。
2MSL的連接配接關閉延遲通常不是問題。但在性能基準環境下,通常隻有一台或幾台用來産生流量的計算機連接配接到某系統
中去,這樣就限制了連接配接到伺服器的用戶端IP位址數。而且,伺服器通常會在HTTP的預設80端口監聽。用
TIME_WAIT防止端口号重用時,這些情況也限制了可用的連接配接值組合。
在隻有一個伺服器一個用戶端情況下,client每次連到server上都有一個新的源端口,實作連接配接的唯一性,但源端口數
量有限,且在2MSL秒(120s)内無法重用,這樣連接配接率就限制在了500次/秒。若再進行優化,且server的連接配接率不
高于500次/秒,就能確定不會遇到TIME_WAIT端口耗盡問題。要修正此問題,可以增加client負載生産機器的數量,
或者確定client和server在循環使用幾個虛拟IP。
即使沒有遇到端口耗盡問題,也要特别小心有大量連接配接處于打開狀态的情況,或者為處于等待狀态的連接配接配置設定了大量
控制塊的情況。
4.3 HTTP連接配接的處理
4.3.1 常被誤解的Connection首部
HTTP允許在用戶端和最終的源端伺服器之間存在一串HTTP中間實體(代理、高速緩存等)。在某些情況下,兩個相
鄰的HTTP應用程式會為它們共享的連接配接應用一組選項。HTTP的Connection首部字段中有一個由逗号分隔的連接配接标簽
清單,這些标簽為此連接配接指定了一些不會傳播到其他連接配接中去的選項。比如,可以用Connection:close 來說明發送
完下一條封包之後必須關閉的連接配接。
Connection首部可以承載3中不同類型的标簽:
HTTP首部字段名,列出隻與此連接配接有關的首部
任意标簽值,用于描述此連接配接的非标準選項
值close,說明操作完成後需關閉這條持久連接配接
如果連接配接标簽中包含了一個HTTP首部字段的名稱,那麼這個首部字段就包含了與一些連接配接有關的資訊,不能将其轉發
出去。在将封包轉發出去之前,必須删除Connection首部列出的所有首部字段。由于Connection首部可以防止無意
中對本地首部的轉發,是以将逐跳首部名放入Connection首部被稱為“對首部的保護”。
HTTP應用程式收到一條帶有Connection首部的封包時,接收端會解析發送端請求的所有選項,并應用。然後會在将
此封包轉發給下一跳位址之前,删除Connection首部以及Connection中列出的所有首部。而且還會有少量沒有作為
Connection首部值列出,但一定不能被代理轉發的逐條首部。其中包括Proxy-Authenticate/Proxy-
Connection/Transfer-Encoding/Upgrade.
4.3.2 串行事務處理時延
連接配接時延和慢啟動時延會因為串行疊加起來。
串行加載另一缺點,有些浏覽器在對象加載完畢之前無法獲知對象的尺寸,而且它們可能需要尺寸資訊來決定将對象
放在螢幕的什麼位置,是以在加載足夠多對象前,無法在螢幕上顯示任何内容。
有幾種新的方法可以提高HTTP連接配接性能:
并行連接配接—-通過多條TCP連接配接發起并發的HTTP請求
持久連接配接—-重用TCP連接配接,以消除連接配接以及關閉時延
管道化連接配接—-通過共享的TCP連接配接發起并發的HTTP請求
複用的連接配接—-交替傳送請求和響應封包(實驗階段)
4.4 并行連接配接
4.4.1 并行連接配接可能會提高頁面的加載速度
包含嵌入對象的組合頁面如果能通過并行連接配接克服單條連接配接的空載時間和帶寬限制,加載速度也會有所提高。時延
可以重疊起來,而且如果單條連接配接沒有充分利用用戶端帶寬,可以将未用帶寬配置設定來裝載其他對象。
4.4.2 并行未必更快
用戶端網絡帶寬不足時(比如,浏覽器是通過一個28.8Kbps的Modem連接配接到網際網路上去),大部分的時間可能
都是用來傳輸資料。這樣,一個連接配接到速度較快的伺服器的HTTP事務就會很容易耗盡所有可用Modem帶寬。如果
并行加載多個對象時,每個對象都去競争這有限的帶寬,每個對象都會以較慢的速度按比例加載,這樣帶來的性能
提升就很小,甚至沒有。
實際上,浏覽器确實使用了并行連接配接,但是會将連接配接的總數限制在一個較小的值(通常是4個)。伺服器可以随意關
閉來自特定用戶端的超量連接配接。
4.5 持久連接配接
WEB用戶端經常會打開到同一個站點的連接配接。比如,一個WEB頁面上的大部分内嵌圖檔通常來自同一個WEB站點,而
且相當一部分指向其他對象的超連結都是指向同一個站點。是以,初始化了對某伺服器的應用程式很可能在不久的将
來對那台伺服器發起更多的請求。這種性質被稱為站點本地性。
是以,HTTP/1.1允許HTTP裝置在事務處理結束之後将TCP連接配接保持在打開狀态,以便為未來的HTTP請求重用現存的
連接配接。持久連接配接會在不同僚務之間保持打開狀态,直到用戶端或者伺服器決定将其關閉。
4.5.1 持久及并行連接配接
并行連接配接可以提高複合頁面的傳輸速度。但也有一些缺點:
1、每個事務都會打開/關閉一條新的連接配接、會耗費時間和帶寬
2、由于TCP慢啟動特性,每條新連接配接的性能都會有所降低
3、可打開的并行連接配接數量有限
持久連接配接比并行連接配接更好在降低了時延和建立連接配接的開銷。但是管理持久連接配接需要特别小心。
4.5.2 HTTP/1.0+keep-alive連接配接
4.5.3 Keep-Alive操作
實作HTTP/1.0 keep-alive連接配接的用戶端可以通過包含 Connection: Keep-Alive首部請求将一條連接配接保持在打開
狀态。
如果伺服器願意為下一條請求将連接配接保持在打開狀态,就在響應中包含相同的首部。如果響應中沒有 Connection:
Keep-Alive 首部,用戶端就會認為伺服器不支援keep-alive,會在響應封包之後關閉連接配接。
4.5.4 Keep-Alive選項
keep-alive首部隻是請求将連接配接保持在活躍狀态。發出keep-alive請求之後,用戶端和伺服器并不一定同意進行
keep-alive會話。它們可以在任意時刻關閉空閑的keep-alive連接配接,并可随意限制keep-alive連接配接所處理事務數量
可以用keep-alive通用首部中指定的、由逗号分隔的選項來調節行為:
1、timeout是在keepalive響應首部發送的。它估計了伺服器希望将連接配接保持在活躍狀态的時間。并非承諾值
2、max也是在響應首部發送的。估計了伺服器還希望為多少個事務保持此連接配接的活躍狀态,并非承諾值。
3、keep-alive首部還可以支援任意未經處理的屬性,這些屬性主要用于診斷調試。文法:name [=value]
4.5.5 keep-alive連接配接的限制和規則
*HTTP/1.0中,并非預設使用,用戶端需發送一個請求首部來激活keep-alive連接配接
*請求首部必須随所有希望保持持久連接配接的封包一起發送
*如果此響應中沒有Connection: Keep-Alive響應首部,就可以知道伺服器發出響應後是否會關閉連接配接了
*代理和網關必須執行Connection首部的規則。代理或網關必須在将封包轉發出去或将其高速緩存之前,删除在
Connection首部中命名的所有首部字段以及首部自身。
*嚴格來說,不該與無法确定是否支援Connection首部的代理伺服器建立keep-alive連接配接
*除非重複發送請求會産生其他一些副作用,否則如果在用戶端收到完整的響應之前連接配接就關閉了,用戶端就一定要
做好重試請求的準備。
4.5.6 Keep-Alive和啞代理
WEB用戶端的Connection: keep-alive首部應該隻會對這條離開用戶端的
TCP鍊路産生影響。
1、Connection首部和盲中繼
問題出在代理上—-尤其是那些不了解Connection首部,而且不知道在沿
着轉發鍊路将其發送出去之前,應該将該首部删除的代理。很多老的或簡
單的代理都是盲中繼(blind relay),它們隻是将位元組從一個連接配接轉發到
另一個連接配接中去,不對Connection首部進行特殊處理。
2、代理和逐跳首部
為避免此類代理通信問題,現代的代理都決不能轉發Connection首部和
所有名字出現在Connection值中的首部。另外,還有幾個不能作為
Connection首部值列出,也不能被代理轉發或作為緩存響應使用的首
部。其中包括:Proxy-Authenticate/Proxy-Connection/Transfer-
Encoding/Upgrade.
4.5.7 插入Proxy-Connection
Netscape的做法是,浏覽器向代理發送非标準的Proxy-Connection擴充首
部,而不是官方的Connection首部。如果代理是盲中繼,會将無意義的
Proxy-Connection首部轉發給伺服器,而伺服器會忽略此首部。但如果是一
個能夠了解持久連接配接的代理,就會用一個Connection首部代替這個首部,将
其發送給伺服器。
在用戶端和伺服器之間隻有一個代理時,可以使用這種方案來解決問題,但
是,一旦在啞代理的任意一側還有一個聰明的代理,問題就會再次發生。
4.5.8 HTTP/1.1 持久連接配接
HTTP/1.1 逐漸停止了對keep-alive的支援,用一種名為持久連接配接
(persistent connection)的改進型設計取代。
HTTP/1.1 持久連接配接在預設情況下是激活的,除非特别指明,否則,HTTP/1.1
假定所有的連接配接都是持久的。要在事務結束之後将連接配接關閉,HTTP/1.1應用
程式必須向封包中顯式地添加一個Connection: close首部。但是,用戶端
和伺服器仍然可以随時關閉空閑連接配接,不發送close并不意味着伺服器承諾永
遠将連接配接保持在打開狀态。
4.5.9 持久連接配接的限制和規則
*發送了Connection: close請求首部後,用戶端就無法在那條連接配接上發送更
多的請求了。
*若用戶端不想在連接配接上發送其他請求了,就應該在最後一個請求中發送close
*隻有當連接配接上所有的封包都有正确的、自定義封包長度時(也就是說,實體
部分的長度和相應的Content-Length一緻,或者是用分塊傳輸編碼方式編碼
的)—–連接配接才能持久保持
*HTTP/1.1的代理必須能分别管理與用戶端和伺服器的持久連接配接—-每個持久
連接配接都隻适用于一跳傳輸
*由于較老的代理會轉發Connection首部,是以,HTTP/1.1的代理伺服器不
應與HTTP/1.0用戶端建立持久連接配接。
*盡管伺服器不該在傳輸封包的過程中關閉連接配接,而且在關閉連接配接之前至少應
該響應一條請求。但不管Connection首部取什麼值,HTTP/1.1裝置都可在
任意時刻關閉連接配接。
*HTTP/1.1 應用程式必須能從異步的關閉中恢複出來,隻要不存在可能會累積
起來的副作用,用戶端都應該重試這條請求。
*除非重複發起請求會産生副作用,否則如果在用戶端收到整條響應之前連接配接
關閉了,用戶端都必須要重新發起請求。
*一個使用者用戶端對任何伺服器或代理最多隻能維護兩條持久連接配接,以防止服
務器過載。代理可能需要更多到伺服器的連接配接來支援并發使用者的通信,是以,
如果有N個使用者試圖通路伺服器,代理最多要維持2N條到任意伺服器或父代
理的連接配接。
4.6 管道化連接配接
在響應到達之前,可以将多條請求放入隊列。當第一條請求通過網絡流向另一端
的伺服器時,第二條和第三條請求也可以開始發送了。這樣可以降低網絡的環回
時間,提高性能。
對管道化連接配接有幾條限制:
!如果HTTP用戶端無法确認連接配接是持久的,就不該使用管道
!必須按照與請求相同的順序回送HTTP響應。HTTP封包中沒有序列号标簽,
是以如果收到的響應失序了,就無法進行比對
!HTTP用戶端必須做好連接配接會在任意時刻關閉的準備,還要準備好重發所有
未完成的管道化請求
!HTTP用戶端不應該用管道化的方式發送會産生副作用的請求(如POST)。總
之,出錯的時候,管道化方式會阻礙用戶端了解伺服器執行的是一系列管道
化請求中的哪一些。由于無法安全的重試POST這樣的非幂等請求,是以出
錯時,就存在某些方法永遠不會被執行的風險。
4.7 關閉連接配接的奧秘
4.7.1 “任意”解除連接配接
所有HTTP用戶端,伺服器或代理都可在任意時刻關閉一條TCP傳輸連接配接。通常
在一條封包結束時關閉。
4.7.2 Content-Length及截尾操作
每條HTTP響應都應該有精确的length首部,用以描述響應主體的尺寸。一些
老的HTTP伺服器會省略這個首部或者包含錯誤的長度訓示,這樣就要依賴服
務器發出的連接配接關閉來說明資料的真實結尾。
用戶端或代理收到一條随連接配接關閉而結束的HTTP響應,且實際傳輸的實體長
度與length首部不比對,接收端就該質疑長度的正确性。
如果接收端是個緩存代理,就不該緩存這條響應(降低今後将潛在的錯誤封包
混合起來的可能)。代理應将有問題的封包原封不動的轉發出去。
4.7.3 連接配接關閉容限、重試以及幂等性
如果一個事務,不管是執行一次還是多次,得到的結果都相同,這個事務就是
幂等的。實作者們可以認為GET/HEAD/PUT/DELETE/TRACE/OPTIONS方法
都共享這一特性。用戶端不該以管道化方式傳送非幂等請求(如POST)。否
則連接配接的過早終止就會造成一些不确定的後果。要發送一條非幂等請求,就需
要等待來自前一條請求的響應狀态。
盡管使用者Agent代理可能會讓操作員來選擇是否對請求進行重試,但一定不能
自動重試非幂等方法或序列。比如,大多數浏覽器會在重載一個緩存的POST
響應時提供一個對話框,詢問使用者是否希望再次發起事務處理。
4.7.4 正常關閉連接配接
1、完全關閉與半關閉
應用程式可以關閉TCP輸入和輸出信道中的任意一個,或者将兩者都關閉
了。套接字調用close()會将TCP連接配接的輸入和輸出信道都關閉了—-完全
關閉。還可以用套接字調用shutdown()單獨關閉輸入或輸入信道—-半
關閉。
2、TCP關閉及重置錯誤
簡單的HTTP應用程式可以隻使用完全關閉。但當應用程式開始與很多其他
類型的HTTP用戶端、伺服器和代理進行對話且開始使用管道化持久連接配接
時,使用半關閉來防止對等實體收到非預期的寫入錯誤就變得很重要了。
總之,關閉連接配接的輸出信道總是很安全的。連接配接另一端的對等實體會在從其
緩沖區中讀出所有資料後收到一條通知,說明流結束了,這樣它就知道你将
連接配接關閉了。
關閉連接配接的輸入信道比較危險,除非你知道另一端不打算再發送其他資料
了。若另一端向你已經關閉的信道發送資料,作業系統就會向另一端的機器
回送一條TCP“連接配接被對端重置”的封包。大部分作業系統會将這種情況作
為很嚴重的錯誤來處理,删除對端還未讀取的所有緩存資料。
3、正常關閉
實作正常關閉的應用程式首先應該關閉它們的輸出信道,然後等待連接配接另一
端的對等實體關閉它的輸出信道。之後,連接配接就會被完全關閉。
但不幸的是,無法確定對等實體會實作半關閉,或對其進行檢查。是以,想
要正常關閉連接配接的應用程式應該先半關閉其輸出信道,然後周期性地檢查其
輸入信道的狀态(查找資料,或流的末尾)。如果在一定時間區間内對端沒
有關閉輸入信道,應用程式可以強制關閉連接配接,以節省資源。
第二部分 HTTP結構
第五章 WEB伺服器
WEB伺服器會做些什麼
1、建立連接配接—-接受一個用戶端連接配接,或者如果不希望與這個用戶端建立連接配接,就将
其關閉
2、接受請求—-從網絡中讀取一條HTTP請求封包
3、處理請求
4、通路資源
5、建構響應
6、發送響應
7、記錄事務處理過程
5.1 第一步—-接受用戶端連接配接
5.1.1 處理新連接配接
用戶端請求一條道伺服器的TCP連接配接時,伺服器會建立連接配接,判斷連接配接的另一端
是哪個用戶端,從TCP連接配接中将IP位址解析出來。(不同作業系統在對TCP連接配接
進行操作時會使用不同的接口和資料結構,Unix下,TCP連接配接由一個套接字表
示,可以用getpeername調用從套接字中擷取用戶端IP)一旦新的連接配接建立起來
并被接受,伺服器就會将新連接配接添加到其現存伺服器連接配接清單中,做好監視連接配接
上資料傳輸的準備。
5.1.2 用戶端主機名識别
可以用‘反向DNS’對大部分web伺服器進行配置,以便将用戶端IP位址轉換成
用戶端主機名。web伺服器可以将用戶端主機名用于詳細的通路控制和日志記
錄。但需要注意的是,主機名查找可能花費較長時間,這會降低事務處理的速
度。很多大容量的伺服器要麼禁止主機名解析,要麼隻允許對特定内容進行解
析。 可以用HostnameLookups啟用Apache的主機查找功能。
5.1.3 通過ident确定用戶端使用者
有些web伺服器支援IETF的ident協定。伺服器可以通過ident協定找到發起
HTTP連接配接的使用者名。這些資訊對web伺服器的日志記錄很有用—流行的通用日
志格式(CommonLogFormat)的第二個字段就包含了每條HTTP請求的ident
使用者名。
如果用戶端支援ident協定,就在TCP端口113上監聽ident請求。
可以通過Apache的identitycheck on指令告知Apache web伺服器使用ident查
找功能。若沒有ident資訊可用,Apache會用連字元來填充ident日志字段。
5.2 第二步—-接受請求封包
連接配接上有資料到達時,web伺服器會從網絡連接配接中讀取資料,并将請求封包中的内
容解析出來
**解析請求行,查找請求方法、指定的資源辨別符(URI)以及版本号,各項間由
一個空格分隔,并以一個回車換行(CRLF)序列作為行的結束。
**讀取以CRLF結尾的封包首部
**檢測到以CRLF結尾的、辨別首部結束的空行(如果有)
**如果有的話,讀取請求主體
解析請求封包時,伺服器會不定期從網絡上接收輸入資料。網絡連接配接可能随時有延
遲。伺服器需要從網絡中讀取資料,将部分資料臨時存儲在記憶體中,直到收到足以
進行解析的資料并了解其意義為止。
5.2.1 封包的内部表示法
有些web伺服器還會用便于進行封包操作的内部資料結構來存儲請求封包。比
如,資料結構中可能包含有指向請求封包中各個片段的指針及其長度,這樣就可
以将這些首部存在一個快速查詢表中,以便快速通路特定的首部的具體值。
5.2.2 連接配接的輸入/輸出處理結構
因為請求可能會在任意時刻到達,是以WEB伺服器會不停的觀察有無新的WEB
請求,不同的伺服器結構會以不同的方式為請求服務。
①單線程伺服器
單線程的伺服器一次隻處理一個請求,直到其完成為止。一個事務處理結束之
後,才會處理下一條連接配接。在處理過程中,其他所有連接配接都會被忽略,隻适用
于低負荷的伺服器。
②多程序及多線程伺服器
多程序和多線程伺服器用多個程序,或更高效的線程同時對請求進行處理。可
以根據需要建立,或者預先建立一些線程/程序(會預先建立一些線程的系
統,被稱為“工作池”系統,因為池中會有一組線程在等待工作)。有些服務
器會為每條連接配接配置設定一個線程/程序,但當伺服器同時要處理很多連接配接時,需
要的程序或線程數量可能會消耗太多的記憶體或系統資源。是以很多多線程服務
器都會對線程/程序的最大數量進行限制。
③複用I/O的伺服器
為了支援大量的連接配接,很多WEB伺服器都采用了複用結構。在複用結構中,
要同時監視所有連接配接上的活動。當連接配接的狀态發生變化時(比如有資料可
用,或者出現錯誤時),就對那條連接配接進行少量的處理。處理結束之後,将
連接配接傳回到開放連接配接清單中,等待下一次的狀态變化。隻有在有事情可做時
才會對連接配接進行處理,在空閑連接配接上等待的時候并不會綁定程序和線程。
④複用的多線程伺服器
有些系統會将多線程和複用功能結合在一起,以利用計算機平台上的多個
CPU。多個線程(通常是一個實體處理器)中的每一個都在觀察打開的連接配接
(或打開的連接配接中的一個子集),并對每條連接配接執行少量的任務。
注:程序是一個獨立的程式控制流,有自己的變量集。線程是一種更快、更高效的程序版本。
5.3 第三步 處理請求
一旦WEB伺服器收到了請求,就可以根據方法、資源、首部和可選的主體部分來
對請求進行處理了。
5.4 第四步 對資源的映射及通路
5.4.1 docroot
WEB伺服器支援各種不同類型的資源映射,但最簡單的資源映射形式就是用請
求URI作為名字來通路WEB伺服器檔案系統中的檔案。通常,WEB伺服器會有
一個文檔的根目錄(document root 或docroot)。伺服器從請求封包中擷取
URI,并将其附加在文檔根目錄後面。
伺服器要注意,不能讓URL退到docroot之外,将檔案系統的其他部分暴露出
來。
1、虛拟托管的docroot
虛拟托管的WEB伺服器會在同一台WEB伺服器上提供多個web站點,每個站點
在伺服器上都有自己獨有的文檔根目錄。虛拟托管web伺服器會根據URI或
Host首部的IP位址或主機名來識别要使用的正确文檔的目錄。通過這種方式,
即使請求URI完全相同,托管在同一伺服器上的兩個web站點亦可以擁有完全
不同的内容了。
對于大多數web伺服器來說,配置虛拟托管的文檔根目錄是很簡單的。對常見
的Apache web伺服器來說,需要為每個虛拟web站點配置一個VirtualHost
塊,而且每個虛拟伺服器都要包含DocumentRoot。
2、使用者的主目錄docroot
Docroot的另一種常見應用是在WEB伺服器上為人們提供私有的web站點。通
常會把那些以斜杠和波浪号(/~)開始,後面跟着使用者名的URI映射為此使用者的
私有文檔目錄。私有docroot通常是使用者主目錄下那個名為public_html的目
錄,但也可将其配置為其他值。
5.4.2 目錄清單
web伺服器可以接受對目錄URL的請求,其路徑可以解析為一個目錄,而不是
檔案。我們可以對大多數的伺服器進行配置,使其在用戶端請求目錄URL時采
取不同的動作。
@傳回一個錯誤
@不傳回目錄,傳回一個特殊的預設“索引檔案”
@掃描目錄,傳回一個包含目錄内容的HTML頁面
大多數伺服器都會去查找目錄中一個名為index.html或index.htm的檔案來代
表此目錄。如果使用者請求的是一個目錄的URL,而且這個目錄中有一個名為
index.html或者index.htm的檔案,伺服器就會傳回那個檔案的内容。
在Apache伺服器上可以用配置指令DirectoryIndex來配置要作為預設目錄文
件使用的檔案名集合。該指令會按照優先順序列出所有可以作為目錄索引檔案
使用的檔案名。下列配置會使Apache在收到一個目錄URL請求時,在目錄中
搜尋指令中列出來的任意一個檔案:
DirectoryIndex index.html index.htm home.html home.htm index.cgi
如果使用者請求目錄URI時,沒有提供預設的索引檔案,而且沒有禁止使用目錄
索引,很多web伺服器都會自動傳回一個html檔案,此檔案中會列出那個目錄
裡的檔案名以及每個檔案的大小和修改日期,還包括到每個檔案的URI連結。
可以通過以下Apache指令禁止自動生成目錄索引檔案:
Options-Indexes
5.4.3 動态内容資源的映射
web伺服器還可以将URI映射為動态資源—-也就是說,映射到按需動态生成内
容的程式上去。
Apache允許使用者将URI路徑名元件映射為可執行檔案目錄。伺服器收到一條帶
有可執行路徑元件的對URI請求時,會試着去執行相應的伺服器目錄中的程
序。例如,下列Apache配置就表明所有路徑以/cgi-bin/開頭的URI都應該執
行在目錄/usr/local/etc/httpd/cgi-programs/中找到的相應檔案。
ScriptAlias /cgi-bin/ /usr/local/etc/httpd/cgi-programs/
Apache還允許使用者用一個特殊的檔案擴充名來辨別可執行檔案。通過這種方
式就可以将可執行腳本放在任意目錄中了。下面的配置指令說明要執行所有
以.cgi 結尾的web資源
AddHandler cgi-script .cgi
CGI是早期出現的一種簡單、流行的伺服器應用程式執行接口。現代的應用程
序伺服器都有更強大有效的伺服器動态内容支援機制,包括微軟的動态伺服器
頁面(Active Server Page)和Java servlet。
5.4.4 伺服器端包含項
很多WEB伺服器還提供了對伺服器端包含項(SSI)的支援。如果某個資源被
辨別為存在伺服器端包含項,伺服器就會在将其發送給用戶端之前對資源内容
進行處理。
要對内容進行掃描,以查找(通常包含在特定的HTML注釋中的)特定的模
闆,這些模闆可以是變量名,也可以是嵌入式腳本。可以用變量的值或可執行
腳本的輸出來取代特定模闆。這是建立動态内容的一種簡便方式。
5.4.5 通路控制
伺服器可以為特定資源進行通路控制。
5.5 第五步 建構響應
5.5.1 響應實體
如果事務處理産生了響應主體,就将内容放在響應封包中回送過去。如果有響
應主體的話,響應封包中通常包括:
!描述了響應主體MIME類型的Content-Type首部
!描述了響應主體長度的Content-Length首部
!實際封包的主體内容
5.5.2 MIME類型
!MIME類型
伺服器可以用檔案的擴充名來說明MIME類型。
!魔法分類
Apache伺服器可以掃描每個資源的内容,并将其與一個已知模式表(魔法文
件)進行比對,以決定每個檔案的MIME類型,這樣會比較慢,但是很友善,
尤其是檔案沒有标準擴充名的時候。
!顯式分類(Explicit typing)
可以對伺服器進行配置,使其不考慮檔案的擴充名或内容,強制特定檔案或目
錄内容擁有某個MIME類型。
!類型協商
有些伺服器可以以多種文檔格式來存儲資源,這種情況下,通過配置伺服器,
使其可以通過與使用者協商來決定使用哪種格式及相關的MIME類型最好。
5.5.3 重定向
**永久删除的資源
資源肯能以及被移動到新位置,或重新命名,有了新的URL。301 Moved
Permanently 就用于此類重定向
**臨時删除的資源
狀态碼303 See Other 以及狀态碼 307 Temporary Redirect 用于此類。
**URL增強
伺服器通常用重定向來重寫URL,往往用于嵌入上下文。當請求到達時,服
務器會生成一個新的包含了嵌入式狀态資訊的URL,并将使用者重定向到這個
新的URL上去。用戶端會跟随這個重定向資訊,重新發起請求,但這次的請
求會包含完整的、經過狀态增強的URL。這是在事務間維護狀态的一種有效
方式。303、307用于此類重定向。
**負載均衡
若一個超載的伺服器收到一條請求,可以将用戶端重定向到一個負載不太重
的伺服器上去。303、307用于此類重定向。
**伺服器關聯
伺服器上可能會有某些使用者的本地資訊。伺服器可将用戶端重定向到包含了
用戶端資訊的那個伺服器上去。303、307可用于此類重定向。
**規範目錄名稱
用戶端請求的URI是一個不帶尾部斜線的目錄名時,大多數伺服器都會将客
戶端重定向到一個加了斜線的URI上,這樣相對連結就可以正常 工作了。
5.6 第六步 發送響應
伺服器通過連結發送資料時也會面臨與接收資料一樣的問題。伺服器可能有很多條
到各個用戶端的連接配接。伺服器要記錄連接配接的狀态,還要特别注意對持久連接配接的處
理。對非持久連接配接來說,伺服器應在發送了整條封包之後,關閉自己這一端的連
接。
對持久連接配接來說,連接配接可能扔保持打開狀态,這種情況下,伺服器要注意正确的計
算Content-Length首部,不然用戶端就無法知道響應什麼時候結束。
5.7 第七步 記錄日志
第六章 代理
6.1 WEB的中間實體
HTTP的代理伺服器既是WEB伺服器又是用戶端。
6.1.1 私有和共享代理
**公共代理
集中式代理的費效比更高,更容易管理。某些代理應用,比如高速緩存代理服
務器,會利用使用者間共同的請求,這樣彙入同一個代理伺服器的使用者越多,它
就越有用。
**私有代理
有些浏覽器輔助産品,以及一些ISP服務,會在使用者的PC上直接運作一些小型
代理,以便擴充浏覽器特性,提高性能。
6.1.2 代理和網關的對比
嚴格來說,代理連接配接的是兩個或多個使用相同協定的應用程式,而網關連接配接的則
是兩個或多個使用不同協定的端點。網關扮演“協定轉換器”角色,即使用戶端
和伺服器使用不同協定,用戶端也能通過它和伺服器完成事務處理。
實際上,代理和網關的差別很模糊,由于浏覽器和伺服器實作的是不同版本的
HTTP,代理也需要做協定轉換工作。而商業化代理伺服器也會實作網關功能來
支援SSL安全協定,socks防火牆、ftp通路以及基于web的應用程式。
6.2 為什麼使用代理
改善安全些,提高性能,節省費用。代理伺服器可以看到并接觸到所有流過HTTP
流量,是以代理可以監視流量并對其進行修改,實作WEB增值服務。
**在集中式代理伺服器上可以對所有通路控制功能進行配置。
為防止有些使用者刻意繞過,可以靜态配置伺服器,使其僅接受來自代理的請求。
**安全防火牆
代理伺服器會在網絡中單一安全節點上限制哪些應用層協定的資料可以流入或流
出一個組織。還可以提供用來消除病毒的WEB和E–mail代理使用的那種挂鈎程
序。
**WEB緩存
**反向代理
代理可以假扮WEB伺服器,這些被稱為替代物(surrogate)或反向代理
(reverse proxy)的代理接收發給WEB伺服器的真實請求,但與WEB伺服器不
同的是,它們可以發起與其他伺服器的通信,以便按需定位所請求的内容。
可以用這些反向代理來提高通路慢速WEB伺服器上公共内容時的性能。在這種配
置中,通常将這些反向代理稱為伺服器加速器(server accelerator)。還可以
将反向代理與内容路由功能配合使用,以建立按需複制内容的分布式網絡。
**内容路由器
代理可以根據網際網路流量狀況以及内容類型将請求導向特定的WEB伺服器。
**轉碼器
代理伺服器在将内容發給用戶端之前,可以修改内容的主體格式。在這種資料表
示法之間進行的透明轉換被稱為轉碼。
轉碼代理可以在傳輸GIF圖檔時将其轉換成JPEG圖檔,也可以對圖檔進行壓縮,
或降低顔色的色彩飽和度以便在電視上看。也可以對文本檔案進行壓縮,甚至可
以在傳輸文檔過程中将其轉換成外語。
**匿名者
匿名者代理會主動從HTTP封包中删除身份特性(用戶端IP,From首部、
Referer首部、cookie、URI的會話ID),進而提供高度的私密性和匿名性。
(但是由于删除了識别資訊,使用者浏覽體驗可能會下降,有些WEB站點可能無法
正常工作)
6.3 代理會去往何處
6.3.1 代理伺服器的部署
**出口代理
将代理固定在本地網絡的出口點,以便控制本地網絡與Internet之間的流量。
**通路(入口)代理
代理常被放在ISP通路點上,用以處理來自客戶的聚合請求。ISP使用緩存代理
來存儲常用的文檔副本,以提高使用者的下載下傳速度。
**反向代理
代理常被部署在網絡邊緣,在WEB伺服器之前,作為反向代理使用,在那裡
它們可以處理所有傳送給web伺服器的請求。并隻在必要時向WEB伺服器請
求資源。反向代理可以提高web伺服器的安全性,或者将快速的web伺服器緩
存存放在較慢的伺服器之前,提高性能。反向代理通常會直接冒用web伺服器
的名字和IP位址,這樣所有的請求就會被發送給代理而不是伺服器了。
**網絡交換代理
将具有足夠處理能力的代理放在網絡之間的Internet對等交換點上,通過緩存
來減輕Internet節點的擁塞,并對流量進行監視。
6.3.2 代理的層次結構
可通過代理層次結構(proxy hierarchy)将代理級聯起來。在層次結構中,會
将封包從一個代理傳給另一個,直到原始伺服器,在通過代理傳回用戶端。
層次結構中的代理伺服器被賦予了父和子的關系。靠近伺服器的的被稱作父代
理,靠近用戶端的被稱作子代理。
代理層次結構的内容路由
層次不一定都是靜态,代理伺服器可以根據衆多因素,将封包轉發給一個不斷
變化的代理伺服器和原始伺服器集。
**負載均衡
子代理可能會根據目前父代理上的工作負載級别來決定如何選擇一個父代
理
**地理位置附近的路由
子代理可能會選擇負責原始伺服器所在實體區域的父代理。
**協定/類型路由
子代理可能會根據URI将封包轉發到不同的父代理和原始伺服器上去。某些
特定類型的URI可能要通過一些特殊的代理伺服器轉發請求,以便進行特殊
的協定處理。
6.3.3 代理如何擷取流量
①修改用戶端
很多web用戶端,包括網景和微軟的浏覽器,都支援手動和自動的代理配置。
②修改網絡
網絡基礎設施通過各種手段将網絡流量導入代理
③修改DNS的命名空間
手工編輯DNS名稱清單,或者用特殊的動态DNS伺服器根據需要來确定适當
的代理或伺服器。
④修改伺服器
通過重定向
6.4 用戶端的代理設定
手工配置
預先配置浏覽器
代理的自動配置(提供一個URI,指向JavaScript編寫的配置檔案,用戶端取回這個
檔案,并運作以決定是否使用代理以及使用哪個代理)
WPAD的代理發現(Web Proxy Autodiscovery Protocol)
6.4.1 手工配置
6.4.2 用戶端代理配置:PAC檔案
PAC檔案是一些小的JavaScript程式,可以在運作過程中計算代理設定。通路每
個文檔時,JavaScript函數都會選擇恰當的代理伺服器。
要使用PAC檔案,就要用JavaScript PAC檔案的URI來配置浏覽器(與手工配置
類似,但要在“automatic configuration”框中提供一個URI)。浏覽器會從這
個URI擷取PAC檔案,并用JavaScript邏輯為每次通路計算恰當的代理伺服器。
PAC檔案字尾通常是.pac,MIME類型為 application/x-ns-proxy-autoconfig
6.4.3 用戶端代理配置:WPAD
WPAD協定的算法會使用發現機制和逐級上升政策為浏覽器查找合适的PAC文
件。實作WPAD協定的用戶端需要:
用WPAD找到PAC的URI
從指定的URI擷取PAC檔案
執行PAC 檔案來判定代理伺服器
為請求使用代理伺服器
WPAD會使用一系列的資源發現技術來判定适當的PAC檔案。目前的WPAD協定
規範按順序定義了下列技術:
動态主機配置協定(Dynamic Host Configuration Protocol,DHCP)
服務定位協定(Service Location Protocol ,SLP)
DNS知名主機名
DNS SRV記錄
TXT記錄中的DNS伺服器URI
6.5 與代理請求有關的一些棘手問題
6.5.1 代理URI與伺服器URI的不同
用戶端向伺服器發送請求時,請求行中隻包含部分URI(沒有協定、主機或端
口),如下圖:
但用戶端向代理發送請求時,請求行中則包含完整的URI。如:
在原始的HTTP設計中,用戶端會直接與單個伺服器進行對話。不存在虛拟主
機,也沒有為代理制定什麼規則。單個伺服器都知道自己的主機名和端口,所
以,為了避免發送備援資訊,用戶端隻需給出部分URI即可。
代理出現後,使用部分URI就有問題了。代理需要知道目标伺服器的名稱,這
樣它們才能自己建立自身與伺服器的連接配接。基于代理的網關要知道URI的協定
才能連接配接到FTP資源和其他協定上去。
6.5.2 與虛拟主機一樣的問題
代理缺少協定、主機、端口的問題與虛拟主機伺服器面臨的問題相同。但是解
決方案卻有所不同。
**顯式的代理要求在請求封包中使用完整的URI來解決這個問題;
**虛拟主機要求使用Host首部來承載主機和端口資訊。
6.5.3 攔截代理會收到部分URI
隻要用戶端正确地實作了HTTP,它們就會在請求中包含完整的URI,發送給
經過顯式配置的代理。這樣就解決了部分問題。但是,用戶端并不總是知道自
己在與代理進行對話,因為有些代理對于用戶端是不可見的。用戶端的流量可
能經過反向代理或者攔截代理。這兩種情況下,用戶端都會認為它在與WEB
伺服器進行對話,不會發送完整的URI。
6.5.4 代理既可以處理代理請求,也可以處理伺服器請求
由于将流量重定向到代理伺服器的方式有所不同,通用的代理伺服器應該同時
支援完整URI和部分URI。使用規則如下:
**如果是完整URI,代理就應該是這個完整URI
**如果提供的是部分URI,而且有HOST首部,就應該用HOST首部來确定
原始伺服器的名字和端口号
**如果是部分URI且沒有host首部
##若代理是反向代理,可以用真實的伺服器位址和端口号來配置代理
##若流量被攔截,且攔截者可以提供原始的IP位址和端口,代理就可以
使用攔截技術提供的IP位址和端口号
##所有方法都失敗了,代理沒有足夠資訊來确定原始伺服器,就必須返
回一條錯誤封包
6.5.5 轉發過程中對URI 的修改
代理伺服器要在轉發封包時修改請求URI的話,需要特别小心,對URI的微小
修改,甚至是看起來無害的修改,都可能給下遊伺服器帶來一些互操作性問
題。
特别是,HTTP規範禁止一般的攔截代理在轉發URI時重寫其絕對路徑部分。
唯一的例外是可以用“/” 來取代空路徑。
6.5.6 URI的用戶端自動擴充和主機名解析
沒有代理時,浏覽器會擷取你輸入的URI,嘗試着尋找響應的IP位址。如果找
到了主機名,浏覽器會嘗試相應的IP位址直到擷取成功的連接配接為止。
但是,如果沒有找到主機,很多浏覽器會嘗試某種主機名自動“擴充”機制。
6.5.7 沒有代理時URI的解析
6.5.8 有顯式代理時URI的解析
使用顯式代理時,使用者URI會直接發送給代理,浏覽器就不再執行所有這些便
捷的擴充功能了。
6.5.9 有攔截代理時URI的解析
使用不可見的攔截代理時,對主機名的解析會略有不同,因為對用戶端來說,
是沒有代理的!這種情況下的行為與使用伺服器的情形很類似,浏覽器會自動
擴充主機名,知道DNS成功為止。建立到伺服器的連接配接時有一個很重要的區
别。
6.6 追蹤封包
由于代理的使用,我們需要能追蹤經過代理的封包流,以檢測出各種問題。
6.6.1 Via首部
Via首部字段列出了與封包途徑的每個中間節點(代理或網關)有關的資訊。
代理也可以用Via首部來檢測網絡中的路由環路。代理應該在發送一條請求之前,
在Via首部插入一個與其自身有關的獨特字元串,并在輸入的請求中查找這個字元
串,以檢測網絡中是否存在路由環路。
1、Via的文法
Via首部字段包含一個由逗号分隔的路标(waypoint)。每個路标都表示一個獨立
的代理伺服器或網關,且包含與那個中間節點的協定和位址有關的資訊。
Vi首部的正規文法如下:
**協定名
中間節點收到的協定。如果協定為HTTP,協定名就是可選的。否則,要在版本
之前加上協定名,中間用“/”分隔。網關将HTTP請求連接配接到其他協定時,可
能會使用非HTTP協定。
**協定版本
所受到的封包版本。版本的格式與協定有關。
**節點名
中間節點的主機和可選端口号(若沒有就使用預設的)。某些情況下,可以用
一個假名來代替。
**節點注釋
進一步描述這個節點的可選注釋。
2、Via的請求和響應路徑
請求和響應封包都會經過代理傳輸,是以,請求和響應封包中都要有Via首部。
3、Via與網關
有些代理會為使用非HTTP協定的伺服器提供網關功能,Via首部記錄了這些協定轉
換。
4、Via首部和Server
Server響應首部字段對原始伺服器使用的軟體進行了描述。
如果響應封包是通過代理轉發,一定要確定代理沒有修改Server首部。Server首部
是用于原始伺服器的,代理應該添加的是Via首部。
5、Via的隐私和安全問題
對那些需要隐藏内部網絡的組織來說,代理應該将一個(接受協定值相同的)有序
Via路标條目序列合并成一個聯合條目。
除非這些條目都在同一個組織的控制下,而且已經用了假名取代了主機名,否則不
能合并。同樣,接收協定值不同的條目也不能合并。
6.6.2 TRACE方法
當TRACE請求到達目的伺服器時,整條請求封包都會被封裝在一條HTTP響應的主
體中回送給發送端。當TRACE響應到達時,用戶端可以檢查伺服器收到的确切報
文,已經所經過的代理清單。TRACE響應的Content-Type為 message/http,狀态
為200 OK。
Max-Forwards首部可以來限制TRACE和OPTIONS請求所經過的代理跳數,可用
來測試是否封包出現無限循環,或者檢視鍊中特定代理伺服器的效果。
Max-Forwards請求首部包含了一個整數,用來說明這條請求封包還可以被轉發的
次數。若為零,那麼接收者即使不是伺服器,也必須将TRACE封包回送用戶端
6.7 代理認證
代理可作為通路控制裝置使用。HTTP定義了一種名為代理認證的機制,這種機制可
以阻止對内容的請求,直到使用者向代理提供了有效的通路權限證書為止。
##對受限内容的請求到達一台代理伺服器時,代理伺服器可以傳回一個要求使用訪
問證書的407 Proxy Authnenticate Required狀态碼,以及一個用于描述怎樣提
供這些證書的Proxy-Authenticate首部字段。
##用戶端收到407響應,會嘗試從本地資料庫中,或通過提示使用者來搜集所需證書
##隻要獲得了證書,用戶端就會重新發請求,在Proxy-Authentication首部字段提
供證書
##若證書有效,代理會将請求沿着鍊路往下傳送,否則傳回另一條407應答
6.8 代理的互操作性
6.8.1 處理代理不支援的首部和方法
代理必須對不認識的首部字段進行轉發,而且必須維持同名首部字段的相對順
序。若代理不熟悉某個方法,隻要有可能,就應該嘗試着将封包轉發到下一跳節
點上去。
6.8.2 OPTIONS: 發現對可選特性的支援
通過OPTIONS方法,用戶端或代理可以發現伺服器或其上某個特定資源所支援的
功能。通過這個方法,用戶端可以在與伺服器進行互動之前,确定伺服器的能
力,這樣就可以更友善地與具備不同特性的代理和伺服器進行互操作了。
如果OPTIONS請求的URI是個星号(*),請求的就是整個伺服器所支援的功能。
如果URI是個實際資源位址,OPTIONS請求就是在查詢那個資源的可用特性。如
果成功,OPTIONS方法就會傳回一個包含了各種首部字段的200 OK響應。
HTTP/1.1在響應中唯一指定的首部字段是Allow首部,這個首部用于描述伺服器
所支援的各種方法。
6.8.3 Allow首部
Allow實體首部字段列出了請求URI辨別的資源所支援的方法,若是星号,則是整
個伺服器所支援的方法清單。可以将Allow首部作為請求首部,建議在新的資源上
支援某些方法,但應該在相應的響應中包含一個Allow首部,列出它實際支援的方
法。代理不能對Allow首部字段進行修改。
第七章 緩存
WEB緩存是可以自動儲存常見文檔副本的HTTP裝置。
緩存減少了備援的資料傳輸;緩解了網絡瓶頸問題,不需要更多帶寬就能更快加載頁面;降低了對原始伺服器的要求;降低了距離延時。
7.1 備援的資料傳輸
7.2 帶寬瓶頸
本地網絡帶寬比遠端伺服器提供的帶寬要寬。
7.3 瞬間擁塞(Flash Crowds)
7.4 距離延時
每台路由器都會增加流量的延時,光速自身也會造成延時。
7.5 命中和未命中的
可以用已有的副本為某些到達緩存的請求提供服務。稱為緩存命中(cache hit),
其他請求由于沒有副本可用而不轉發給伺服器,稱為緩存未命中(cache miss)
7.5.1 再驗證
緩存不時對伺服器内容進行檢測,稱為HTTP再驗證(revalidation)。為了有效
地進行再驗證,HTTP定義了一些特殊的請求,不用從伺服器上擷取整個對象,就
可以檢測出内容是否為最新。
大部分緩存隻有在用戶端發起請求,且副本舊得足以需要檢測的時候,才會對副
本進行再驗證。
緩存對緩存的副本進行再驗證時,會向原始伺服器發送一個小的再驗證請求,若
内容無變化,會得到響應304 Not Modified。若緩存知道副本仍有效,就會再次
将副本标記為暫時新鮮,并将副本提供給用戶端。這稱為再驗證命中或緩慢命
中。這種會比單純的緩存命中要慢,但是比緩存未命中更快些。
HTTP提供了幾個工具用于再驗證。最常用的是 If-Modified-Since首部,将這個
首部添加到GET請求中,就可以告訴伺服器,隻有在緩存了對象的副本後,又對
其進行了修改,才發送此對象。
如果伺服器對象與已緩存副本不同,伺服器向客戶的發送一條普通的帶有完整内
容的HTTP 200 OK響應
若伺服器對象被删除,回送404, 緩存也會将其副本删除。
7.5.2 命中率
有緩存提供服務的請求所占比例。40%的命中率對于中等規模的WEB緩存來說是
比較合理的。有時也被稱為文檔命中率。
7.5.3 位元組命中率
由于文檔并非同一尺寸,是以文檔命中率不能說明一切,是以有些人更願意用字
節命中率作為路徑成本。緩存提供的位元組在所有位元組中所占的比例。
文檔命中率說明阻止了多少通往外部網絡的web事務,事務有一個通常都很大的
固定時間成分,提高文檔命中率對降低整體時延很有好處。提高位元組命中率則可
以節省帶寬。
7.5.4 區分命中和未命中的情況
HTTP并未提供一種手段來區分響應時緩存還是原始伺服器的。響應碼都是200
OK,有些商業代理會在Via首部添加一些額外情況來描述緩存中發生的情況。
用戶端可用使用Date首部來判定,若響應中的日期比較早,用戶端通常可以認為
這是一個緩存響應。
7.6 緩存的拓撲結構
7.6.1 私有緩存
WEB浏覽器一般内建有私有緩存。 chrome://cache about:cache
7.6.2 共有代理緩存
7.6.3 代理緩存的層次結構
7.6.4 網狀緩存、内容路由以及對等緩存
網狀緩存結構中的代理更加複雜,它們做出動态的緩存通信決策,決定與哪個父
緩存進行對話,或者直連伺服器。這種代理緩存會決定選擇何種路由對内容進行
通路、管理和傳送,是以可将其稱為内容路由器。
網狀緩存中為内容路由設計的緩存需要完成:
根據URL動态選擇父緩存或伺服器
根據URL動态選擇一個特定父緩存
前往父緩存之前,在本地搜尋已緩存的副本
允許其他緩存對其緩存的部分内容進行通路,但不允許網際網路流量通過它們的
緩存
緩存之間這些更為複雜的關系允許不同的組織互為對等實體,将它們的緩存連接配接
起來以實作共赢。提供可選的對等支援的緩存被稱為兄弟緩存(sibling
cache)。HTTP并不支援sibling cache,是以通過一些協定進行擴充,比如因特
網緩存協定(Internet Cache Portocol,ICP)和超文本緩存協定(HyperText
Caching Protocol,HTCP).
7.7 緩存的處理步驟
接受–解析–查詢—新鮮度檢測–建立響應–發送–日志
建立響應時,緩存将已緩存伺服器的響應首部作為起點,然後進行修改和擴充。比
如修改HTTP/1.0為 HTTP/1.1。緩存還會加入新鮮度資訊(Cache-Control、Age以
及Expires首部),而且通常會有一個Via首部來說明請求由一個代理緩存提供的。
但是,緩存不應該調整Date首部。Date首部表示的元素伺服器最初産生這個對象的
日期。
7.8 保持副本的新鮮
7.8.1 文檔過期
通過特殊的HTTP Cache-Control首部和Expires首部,HTTP讓原始伺服器向每
個文檔附加了一個“過期日期”。
7.8.2 過期日期和使用期
伺服器用HTTP/1.0+的Expires首部或HTTP/1.1 的Cache-Control:max-age響
應首部來指定過期日期。由于Cache-Control首部使用的是相對日期而不是絕對
日期,是以我們傾向于使用比較新的Cache-Control首部。絕對日期依賴于計算
機時鐘的正确設定。
7.8.3 伺服器再驗證
僅僅是已緩存文檔過期了并不意味着它和原始伺服器上目前處于活躍狀态的文檔
有實際的差別;這隻是意味着到了要進行核對的時間了。這種情況稱為“伺服器
再驗證“。
—-如果再驗證顯示内容發生了變化,緩存會擷取一份新的文檔副本,并将其存儲
在舊文檔的位置上,然後發送給用戶端。
—-若再驗證顯示沒有變化,緩存隻需要擷取新的首部,包括一個新的過期日期,
并對緩存中的首部進行更新。
若原始伺服器不可通路,但緩存需要再驗證,那麼緩存必須傳回一條錯誤或用來
描述通信故障的警告封包。否則,來自已經移除的伺服器上的頁面可能在緩存中
存留任意長時間。
7.8.4 用條件方法進行再驗證
HTTP的條件方法可以高效的實作再驗證。
HTTP定義了5個條件請求首部。再驗證最有用的2個首部是If-Modified-Since和
If-None-Match。其他分别是:If-Unmodified-Since(在進行部分檔案的傳輸
時,擷取檔案的其餘部分之前要確定檔案未發生變化)、If-Range(支援對不完
整文檔的緩存)、If-Match(用于與WEB伺服器打交道時的并發控制)
7.8.5 If-Modified-Since:Date再驗證
IMS請求,隻有在某個日期之後資源發生了變化,IMS請求才會訓示伺服器執行請
求。
—-若在指定日期之後,文檔未被修改,條件為假,向客戶的傳回一個小的304響
應封包,但是隻會傳回那些需要在源端更新的首部。比如Content-Type首部通常
不會被修改,是以一般不會發送。
If-Modified-Since首部可以與Last-Modified伺服器響應首部配合工作。
注意:有些伺服器并未将If-Modified-Since作為真正的日期來比對。相反,它們
在IMS日期和最後修改日期間進行字元串比對。這樣得到的語義就是“如果最後
的修改不是在這個确定的日期進行的“,而不是”如果在這個日期之後沒有被修
改過“。
7.8.6 If-None-Match:實體标簽再驗證
有些情況僅使用最後修改日期進行再驗證時不夠的。
—-有些文檔可能會周期性重寫(比如從一個背景程序中寫入),但實際包含的數
據常常是一樣的,但是日期會變化。
—-有些文檔的修改并不重要,不需要讓全世界範圍内的緩存都重裝資料(比如對
拼寫或注釋的修改)。
—-有些伺服器無法準确的判斷其頁面的最後修改日期
—-有些伺服器提供的文檔會在亞秒間隙發生變化,這樣一來,以一秒為粒度的修
改日期可能就不夠用了
為解決這些問題,HTTP允許使用者對被稱為實體标簽(ETag)的“版本辨別
符”進行比較。當釋出者對文檔進行修改時,可以修改文檔的實體标簽來說明這
個新的版本。這樣如果實體标簽被修改了。緩存就可以用If-None-Match來GET
文檔的新副本了。
可以在If-None-Match首部包含幾個實體标簽,來告訴伺服器,帶有這些實體标
簽的對象副本在緩存上已經有了:
7.8.7 強弱驗證器
有時,伺服器希望在對文檔進行一些非實質性或不重要的修改時,不要使所有的
已緩存副本都失效。HTTP/1.1 支援“弱驗證器”,如果隻對内容進行了少量修
改,就允許伺服器聲明那是“足夠好”的等價體。
伺服器用”W/”來辨別弱驗證器。
ETag: W/”v2.6”
If-None-Match: W/”V2.6”
不管相關實體以何種方式變化,強實體标簽都要發生變化,而相關實體在語義上
發送了比較重要的變化時,弱實體标簽也應該發送變化。
7.8.8 什麼時候應該使用實體标簽和最近修改日期
若伺服器回送實體标簽,用戶端就必須使用實體标簽驗證器。若伺服器隻傳回
Last-Modified值,用戶端就可以使用If-Modified-Since驗證。若伺服器兩種都
提供了,用戶端就應該使用兩種驗證方案。
如果HTTP/1.1 緩存或伺服器收到的請求帶有兩種驗證首部,那麼隻有當兩個條件
都滿足時,才能傳回304響應。
7.9 控制緩存的能力
伺服器可以通過HTTP定義的幾種方式來指定在文檔過期之前可以将其緩存多長時
間。按照優先級遞減的順序,伺服器可以:
附加Cache-Control:no-store 首部到響應
no-cache
must-revalidate
max-age
附件一個Expires日期到響應
7.9.1 no-Store 與 no-Cache響應首部
這兩個首部可以防止緩存提供未經證明的已緩存對象:
辨別為no-store的響應會禁止緩存對響應進行複制。緩存通常會像非緩存代理服
務器一樣,向客戶轉發一條no-store響應,然後删除對象。
辨別為no-cache的響應實際上是可以存儲在本地緩存區中的。隻是在與原始服務
器進行新鮮度再驗證之前,不能将其提供給用戶端使用。
HTTP/1.1 提供pragma:no-cache首部是為了相容于HTTP/1.0+。
7.9.2 max-age響應首部
這個首部表示從伺服器将文檔傳來開始,可以認為此文檔處于新鮮狀态的秒數。
還有一個s-maxage,與max-age類似,但是僅适用于共享緩存。
伺服器可以請求緩存不要緩存文檔,或将其最大使用期設定為0。
7.9.3 Expires響應首部
不推薦适用這個首部,它指定的是實際過期日期而不是秒數。因為很多伺服器的
時鐘都不同步。
7.9.4 must-revalidate響應首部
可以配置緩存,使其提供一些過期的對象,以提高性能。如果伺服器希望緩存嚴
格遵守過期資訊,可以在原始響應中附加Cache-Control: must-revalidate首
部。這個響應首部告訴緩存,在事先沒有跟原始伺服器進行再驗證的情況下,不
能提供這個對象的過期副本。緩存仍可以任意提供新鮮副本。如果在緩存進行
must-revalidate新鮮度檢查時,原始伺服器不可用,緩存就必須傳回一條504
Gateway Timeout錯誤。
7.9.5 試探性過期
若響應中沒有任何關于過期的首部。緩存可以計算出一個試探性最大使用期。可
以使用任意算法,但是如果得到的最大使用期大于24小時,就應該向首部添加一
個Heuristic Expiration Warning (試探性過期警告,警告13)首部。實際很少有
浏覽器為使用者提供這種告警資訊。
LM-Factor算法是一種常用的試探性過期算法,如果文檔中包含了最後修改日
期,就可以使用這種算法。
—-如果文檔最後一次修改發生在很久以前,那麼可能是一份穩定的文檔,是以将
其繼續儲存在緩存中比較安全。若是最近被修改過,說明它可能頻繁發生變化,
是以在與伺服器進行再驗證之前,應該隻緩存很短一段時間。
實際的這個算法會計算緩存與伺服器對話的時間跟伺服器聲明文檔最後被修改的
時間的內插補點,取這個間隔時間的一部分,将其作為緩存中新鮮度持續時間。
如果連最後修改日期也沒有的話,緩存通常會設定一個預設的一小時或一天,有
的緩存會設定為0。
7.9.6 用戶端的新鮮度限制
web浏覽器都有Refresh(重新整理)或Reload按鈕,可以強制對浏覽器或代理緩存
中可能過期的内容進行重新整理。Refresh按鈕會釋出一個附加了Cache-Control請求
首部的GET請求,但是其具體行為取決于特定的浏覽器、文檔以及攔截緩存的配
置。
7.10 設定緩存控制
7.10.1 控制Apache的HTTP首部
mod_headers
通過這個子產品可以對單獨的首部進行設定。裝載了這個子產品,就可以用設定單個
HTTP首部的指令來擴充Apache的配置檔案了。
下面這個例子将某目錄下所有HTML檔案都辨別為非緩存的:
mod_expires
這個子產品提供的程式邏輯可以自動生成帶有正确過期日期的Expires首部。通過這
個子產品可以為不同的檔案類型設定不同的過期日期,還可以使用便捷的冗長描述
資訊。
7.10.2 通過HTTP-EQUIV控制HTML緩存
HTML 2.0定義了标簽,這個可選标簽位于HTML文檔頂部,
定義了與該文檔有關的HTTP首部。
最初,這個标簽是給伺服器使用的,但是這個特性會增加伺服器的負擔,這些值
也隻是靜态的,而且隻支援HTML,不支援很多其他檔案類型,所有很少有服務
器和代理支援此特性。
7.11 詳細算法
7.11.1 使用期和新鮮生存期
為了分辨已緩存的文檔是否足夠新鮮,緩存隻需要計算兩個值:已緩存副本的使
用期(age)和已緩存副本的新鮮生存期(freshness lifetime)。如果已緩存副
本的時長小于新鮮生存期,說明足夠新鮮。
文檔的使用期就是自從伺服器将其發送出來(或最後一此被伺服器再驗證)之
後“老去”的總時間。
7.11.2 使用期的計算
響應的使用期就是伺服器釋出響應(或伺服器對其進行再驗證)之後經過的總時
間。 包括響應在網絡和網關中遊蕩的時間,在中間緩存中存儲的時間,以及響應
在你的緩存中停留的時間。
1、表面使用期是基于Date首部的
web應用程式,尤其是緩存代理,要做好與時間值有很大差異的伺服器進行互動
的準備,這個問題被稱為“時鐘偏差”。如果使用期是負的,就将其置為零。
2、逐跳使用期的計算
這樣就可以去除時鐘偏差造成的負數使用期了。文檔經過代理和緩存時,
HTTP/1.1會讓每台裝置豆漿相對使用期累加到Age首部中,用來解決缺乏通用同
步時鐘的問題。但是非HTTP/1.1 的裝置無法識别Age首部。
3、對網絡時延的補償
Date首部說明了文檔是在什麼時候離開原始伺服器的,單并未說明文檔在到緩存
的傳輸過程中花費了多長時間。緩存知道它請求文檔的時間以及文檔抵達的時
間。HTTP/1.1會在這些網絡時延上加上整個往返時延,以便對其進行保守的校正
7.11.3 完整的使用期計算方法
7.11.4 新鮮生存期計算
新鮮生存期取決于伺服器和用戶端的限制。
第八章 內建點:網關、隧道及中繼
8.1 網關
網關可以作為某種翻譯器使用,它抽象出了一種能到到達資源的方法。應用程式可以(通
過HTTP或其他已經定義的接口)請求網關來處理某條請求,網關可以提供一條響應。網
關可以向資料庫發送查詢語句,或者生産動态内容。
web網關在一側使用HTTP協定,在另一側使用另一種協定。
可以用一個斜杠來分隔用戶端和伺服器端協定,并以此對網關進行描述:
<用戶端協定>/<伺服器端協定>
是以,将HTTP用戶端連接配接到NNTP新聞伺服器的網關就是一個HTTP/NNTP網關。
伺服器端網關通過HTTP與用戶端對話,通過其他協定與伺服器通信(HTTPHTTP)
8.2 協定網關
将HTTP流量導向網關時所使用的方式與将流量導向代理的方式相同。最常見的方式是顯
式的配置浏覽器使用網關,對流量進行透明攔截,或者将網關配置為反向代理。
8.2.1 HTTP/*:伺服器端web網關
請求流入原始伺服器,伺服器端web網關會将用戶端HTTP請求轉換為其他協定。
8.2.2 HTTP/HTTPS:伺服器端安全網關
8.2.3 HTTPS/HTTP:用戶端安全加速器網關
這些網關位于web伺服器之前,通常作為不可見的攔截網關或反向代理使用。
這些網關通常包含專用的解密硬體,比原始伺服器更加有效,減輕伺服器的負荷。
8.3 資源網關
最常見的網關–應用程式伺服器,會将目标伺服器與網關結合在一個伺服器中實作。應用
程式伺服器是伺服器端網關,與用戶端通過HTTP通信,并與伺服器端的應用程式相連。
如上圖,應用程式伺服器并未回送檔案,而是将請求通過一個網關應用程式設計接口
(Application Programming Interface,API)發送給運作在伺服器上的應用程式。
第一個流行的應用程式網關API就是通用網關接口(Common Gateway Interface,
CGI),CGI是一個标準接口集,web伺服器可以用它來裝載應用程式以響應對特定URL
的HTTP請求,并收集程式的輸出資料,将其放置HTTP響應中回送。
8.3.1 CGI
CGI應用程式是獨立于伺服器的。它的處理對使用者來說是不可見的。它在伺服器和衆多
資源類型直接提供了一種簡單的、函數形式的粘合方式,用來處理各種需要的轉換。
這個接口還能很好的保護伺服器。但是這種分離會造成性能的耗費,為每條CGI請求引
發一個新程序的開銷是很高的,會限制那些使用了CGI的伺服器的性能。為此,人們開
發了快速CGI,它會作為持久守護程序運作,消除了為每個請求建立或拆除新程序所帶
來的性能損耗。
8.3.2 伺服器擴充API
伺服器擴充API為web開發者提供了強大的接口,以便他們将自己的子產品與HTTP服務
器直接相連。擴充API允許程式員将自己的代碼嫁接到伺服器上,或者用自己的代碼将
伺服器的一個元件完整的替換。
大多數伺服器都會為開發者提供一個或多個擴充API,它們通常會綁定在伺服器自身結
構上,是以大多數都是某種伺服器類型特有的。
微軟的FPSE(FrontPage 伺服器端擴充)就是一個例子,它為使用frontpage的作者
進行web釋出提供支援。FPSE能夠對frontpage用戶端發送的RPC(remote
porcedure call 遠端過程調用)指令進行解釋,這些指令會在HTTP(POST方法)上
捎回。
8.4 應用程式接口和WEB服務
随着web應用程式提供的服務越來越多,HTTP可以作為一種連接配接應用程式的基礎軟體來
使用。網際網路委員會開發了一組允許web應用程式之間互相通信的标準和協定。web服務
是應用程式共享資訊的一種新機制,它是建構在标準的web技術(比如HTTP)之上的。
web伺服器可以用XML通過SOAP來交換資訊。XML(Extensible Markup Language,擴
展标記語言)提供了一種建立資料對象的定制資訊,并對其進行解釋的方法。
SOAP(Simple Object Access Protocol ,簡單對象通路協定)是向HTTP封包中添加
XML資訊的标準方式。
8.5 隧道
WEB隧道可以通過HTTP應用程式通路使用非HTTP協定的應用程式。它允許使用者通過
HTTP連接配接發送非HTTP流量,這樣這類流量就可以穿過隻允許WEB流量通過的防火牆
了。
8.5.1 用CONNECT 建立HTTP隧道
web隧道是用HTTP的CONNECT方法建立的。該方法請求隧道網關建立一條到達任意
目的的伺服器和端口的TCP連接配接,并對用戶端和伺服器之後的後繼資料進行盲轉發。
1、CONNECT請求
除了起始行,CONNECT的文法與其他HTTP方法類似。一個後面跟着冒号和端口号的
主機名取代了請求URI。主機和端口都必須指定。
2、CONNECT 響應
和普通HTTP封包一樣,響應碼200 表示成功。響應中的原因短語通常被設定
為“Connection Established”。與普通HTTP響應不同,這個響應不需要包含
Content-Type首部。
8.5.2 資料隧道、定時及連接配接管理
管道化資料對網關是不透明的,是以網關不能對分組的順序和分組流作任何假設。一
旦隧道建立,資料就可以在任意時間流向任意方向了。隧道的兩端必須做好在任意時
刻接受來自任一端分組的準備,且必須立即轉發。隧道一端對資料的消耗不足可能會
将另一端的資料生産者挂起,造成死鎖。
作為一種性能優化,允許用戶端發送了CONNECT請求之後,接受響應之前,發送隧道
資料。這就意味着網關必須能夠正确處理跟在請求之後的資料。尤其是,網關不能假
設網絡I/O請求隻會傳回首部資料,網關必須確定在連接配接準備就緒時,将與首部一同讀
進來的資料發送給伺服器。在請求之後以管道方式發送資料的用戶端,如果發現回送
的響應是認證請求,或者其他非200但不緻命的錯誤狀态,就必須做好從發請求的準
備。
如果在任意時刻,隧道的任意一個端點斷開了連接配接,那個端點發出的所有未傳輸資料
都會被傳送給另一端,之後,到另一端的連接配接也會被代理終止。如果還有資料要傳輸
給關閉連接配接的端點,資料會被丢棄。
8.5.3 SSL隧道
為了讓SSL流量經現存的代理防火牆進行傳輸,HTTP中添加了一項隧道特性,在此特
性中,可以将原始的加密資料放在HTTP封包中,通過普通的HTTP信道傳送。
8.5.4 SSL隧道與HTTP/HTTPS網關的對比
由網關初始化與遠端HTTPS伺服器的SSL會話,然後代表用戶端執行HTTPS事務。響應
會由代理接收并解密,然後通過不安全的HTTP傳送給用戶端。但是這樣會由幾個缺
點:
用戶端到網關之間的連接配接是非安全的HTTP;
盡管代理是已認證主體,但是用戶端無法對遠端伺服器執行SSL用戶端認證(基于
X509證書的認證;
網關要支援完整的SSL實作。
對于SSL 隧道機制來說,無需在代理中實作SSL,SSL會話是建立在産生請求的用戶端
和web伺服器之間的,中間的代理隻負責傳輸。
8.5.5 隧道認證
可以将代理的認證支援與隧道配合使用,對用戶端使用隧道的權利進行認證。
8.5.6 隧道的安全性考慮
總的來說,隧道網關無法驗證目前使用的協定就是它原本打算經過隧道傳輸的協定。
是以,比如說,一些使用者可能會通過本打算用于SSL 的隧道,越過防火牆來傳遞遊戲
流量,而惡意使用者可能會用隧道打開Tlenet會話,或用隧道繞過公司的E-mail掃描器
來發送E-mail。為降低對隧道的濫用,網關應該隻為特定的端口(比如443)打開隧
道。
8.6 中繼
HTTP中繼(relay)是沒有完全遵循HTTP規範的簡單HTTP代理。中繼負責處理HTTP中
建立連接配接的部分,然後對位元組進行盲轉發。
某些簡單的盲中繼實作中存在一個常見的問題是,由于它們無法正确處理Connection首
部,是以有潛在的挂起keep-alive連接配接的可能。
第九章 WEB機器人
WEB機器人是能在無需人類幹預的情況下自動進行一系列WEB事務處理的軟體程式。很多機器人會從一個站點逛到另一個站點,擷取内容,跟蹤超鍊,并對它們找到的資料進行處理。人文給它們起了一些各具特色的名字,比如“爬蟲”,“蜘蛛”等。
9.1 爬蟲及爬行方式
WEB爬蟲是一種機器人,它們會遞歸地對各種資訊性WEB站點進行周遊,擷取第一個
web頁面,然後擷取那個頁面指向的所有web頁面,然後是那些頁面指向的所有頁面。
遞歸進行追蹤這些web連結的機器人會沿着HTML超鍊建立的網絡爬行,是以将其稱為爬
蟲(crawler)或蜘蛛(spider)。
9.1.1 從哪兒開始:根集
爬蟲開始通路的URL初始集合,被稱作根集(root set)。挑選根集時,應該從足夠多
不同的站點中選擇URL。
如上圖,要抵達所有頁面,根集中隻需要有A,G,S就可以了。
通常,一個好的根集會包括一些大的流行WEB站點,一個新建立頁面的清單和一個不
經常被連結的無名頁面清單。
9.1.2 連結的提取以及相對連結的标準化
爬蟲在WEB上移動時,會不停地對HTML頁面進行解析。主要對每個頁面上的URL鍊
接進行分析,并将這些連結添加到需要爬行的頁面清單中去。這個清單經常會迅速擴
張。爬蟲要通過簡單的HTML解析,将這些連結提取出來,并将相對URL轉換為絕對形
式。
9.1.3 避免環路
機器人必須知道它們到過何處,以避免環路的出現。
9.1.4 循環與複制
環路對爬蟲的危害:
使爬蟲陷入循環之中。
爬蟲不斷地擷取相同的頁面時,另一端的伺服器也在遭受打擊,可能造成DoS。
爬蟲應用程式會被重複的内容所充斥。
9.1.5 面包屑留下的痕迹
由于URL數量巨大,是以要使用負載的資料結構以便快速判定哪些URL是曾經通路過
的。資料結構在通路速度和記憶體使用方面都應該是非常高效的。
機器人知曉要用到搜尋樹或散清單,以快速判定某個URL是否被通路過。
大規模爬蟲對其通路過的位址進行管理時使用的一些技術:
—-樹和散清單
複雜的機器人可能會用到搜尋樹或散清單來記錄已通路的URL,這些事加速URL查
找的軟體資料結構。
—-有損的存在位圖
為減小空間,使用有損資料結構,比如存在位數組(presence bit array)。用一
個散列函數将每個URL都轉換成一個定長的數字,這個數字在數組中有個相關
的“存在位”。爬行過一個URL時,就将相應的“存在位“置位。
—-檢查點
一定要将已通路URL清單儲存到硬碟上,以防止機器人程式崩潰。
—-分類
單個機器人的能力有限,大型web機器人采用“叢集”方式,每個獨立的計算機是
一個機器人,以彙接方式工作。為每個機器人配置設定特定的URL“片”來進行爬行。
機器人個體之間可能需要互相通信,來回傳送URL,以覆寫出故障的對等實體的爬
行範文或協調其工作。
9.1.6 别名與機器人環路
9.1.7 規範化URL
大多數web機器人都試圖通過将URL“規範化”為标準格式來消除上面那些顯而易見的
别名。通過下列步驟來轉換為規範的格式
1、若無指定端口,向主機名添加“:80”
2、将所有轉義字元%xx轉換成等價字元
3、删除#标簽
機器人需要知道web伺服器是否大小寫無關才能避免大小寫的别名問題 需要知道伺服器上這個目錄下的索引頁面配置才能知道預設頁面是否為别名
$即使知道主機名和IP位址都指向同一台計算機,它也還要知道WEB伺服器是否配置為
進行虛拟主機操作,才能判斷是否為别名。
9.1.8 檔案系統連接配接環路
檔案系統中的符号連接配接會造成特定的潛在環路。因為它們會在目錄層次深度有限的情
況下,造成深度無限的假象。
上圖b的問題是subdir/是個指向“/”的環路。但由于URL看起來有所不同,是以機器
人無法但從URL本身判斷出文檔時相同的。需要有某種循環檢測方式,才能避免陷入循
環。
9.1.9 動态虛拟WEB空間
惡意網管可能會有意建立一些複雜的爬蟲循環來陷害機器人。比如釋出一個看起來像
普通檔案,實際上卻是網關應用程式的URL。這個應用程式可以在傳輸中構造出包含了
到同一伺服器上虛構URL連結的HTML。請求這些虛構的URL時,伺服器就會捏造出一
個帶有新的虛構URL的新HTML頁面來。
即使這個惡意伺服器并不包含任何檔案,它也可以通過無限虛拟的WEB空間将機器人
帶入無盡的旅途。由于每次URL和HTML看起來有很大不同,機器人很難檢測的環路。
9.1.10 避免循環和重複
經過良好設計的機器人中要包含一組試探方式,以避免出現環路。
規範化URL
廣度優先的爬行
節流–限制從一個web站點擷取的頁面數量。
限制URL大小–通常是1KB。現在很多站點都會用URL來管理使用者的狀态(比如在一個
頁面引用的URL中存儲使用者ID)。用URL長度來限制爬蟲可能會帶來麻
煩,但如果每當請求的URL到達某個特定長度時,就記錄以及錯誤,就
可以為使用者提供一種檢測某特定站點上所發生情況的方法。
URL/站點黑名單
模式檢測–檔案系統的符号連接配接和類似的錯誤配置造成的環路會遵循某種模式。比如
URL随着元件的複制逐漸增加。有些機器人會将具有重複元件的URL當做潛
在的環路。重複并不都是立即出現,有些環路可能以其他間隔為周期。
/subdir/images/subdir/images/subdir/images/…
内容指紋–擷取頁面内容中的位元組,并計算出一個校驗和。必須對校驗和函數進行選
擇,以求不同頁面具有相同校驗和的幾率非常低。比如MD5這樣的。
有些伺服器會在傳輸過程中對頁面進行動态修改,是以有時機器人會在校驗
和的計算中忽略web頁面内容中的某些部分,比如嵌入的連結。而且,無論
定制了什麼頁面内容的動态服務端包含(比如添加日期,通路計數等)都可
能阻礙重複檢查。
人工監視–所有産品級的機器人都要有診斷和日志功能。
9.2 機器人的HTTP
9.2.1 識别請求首部
盡管機器人傾向于隻支援最小的HTTP集,但大部分機器人确實實作并發送了一些識别
首部—User-Agent。建議機器人實作者發送一些基本的首部資訊,以通知各站點機器
人的能力、辨別符、以及它是從何處起源。
基本識别首部應該包括如下内容:
User-Agent
From—-提供機器人的使用者、管理者的E-mail位址
Accept—-告知伺服器可以發送哪些媒體類型。
Referer—-提供包含目前請求URL的文檔的URL。
9.2.2 虛拟主機
請求中不包含Host首部的話,可能會使機器人将錯誤的内容與一個特定的URL關聯起
來。是以,HTTP/1.1要求使用Host首部。
9.2.3 條件請求
盡量減少機器人所要擷取内容的數量通常是很有意義的。隻在内容發生變化時才重新
擷取内容變得很重要。
有些機器人實作了條件HTTP請求,它們會對時間戳或實體标簽進行比較,檢視它們最
近擷取的版本是否已經更新。
9.2.4 對響應的處理
很多機器人的興趣主要在于用簡單的GET方法來擷取所請求的内容。但是,使用了某些
HTTP特性(比如條件請求)的機器人,想要與伺服器進行互動的機器人則要能對各種
不同類型的HTTP響應進行處理。
1、狀态碼
所有機器人都應該了解200和404這樣的狀态碼。它們還應該能夠根據響應的一般類别
對它并不十分了解的狀态碼進行處理。有些伺服器并不能總是傳回适當的錯誤代碼,
認識到這一點是很重要的。有些伺服器甚至會将HTTP 200 OK與描述錯誤狀态的封包
主體文本一同傳回。
2、實體
除了HTTP首部所嵌的資訊之外,機器人也會在實體中查找資訊。HTML原标簽,比如
原标簽http-equiv,就是内容編寫者用于嵌入資源附加資訊的一種方式。
有些伺服器實際上會在發送HTML頁面之前先對其内容進行解析,并将http-equiv指令
作為首部包含進去。
9.2.5 User-Agent導向
站點管理者應該設計一個處理機器人請求的政策。比如,它們可以為所有其他特性不
太豐富的浏覽器和機器人開發一些頁面,而不是将其内容限定在特定浏覽器所支援的
範圍。
9.3 行為不當的機器人
失控的機器人—-造成DoS
失效的URL
很長的錯誤URL
愛打聽的機器人—-一旦爬去到一些敏感資訊,應該有某種機制可以将這些資料丢棄,并
将所有搜尋索引或歸檔檔案中将其删除。
動态網關通路—-機器人并不知道它們通路的是什麼内容。機器人可能會擷取一個内容來
自網關應用程式的URL。
9.4 拒絕機器人通路
robots.txt。所有WEB伺服器都可在伺服器的文檔根目錄中提供一個可選的、名為
robots.txt的檔案。這個檔案包含的資訊說明了機器人可以通路伺服器的哪些部分。
9.4.1 拒絕機器人通路标準
目前大多采用0.0 和 1.0版本。
9.4.2 WEB站點和robots.txt檔案
如果一個web站點有robots.txt檔案,那麼在通路這個web站點上的任意URL 之前,機
器人都必須擷取并對它進行處理。每個站點僅有一個robots資源,每個虛拟站點的虛
拟的docroot都可以有一個不同的robots檔案。
1、擷取robots.txt
機器人通過GET方法擷取robots檔案。若有,伺服器将其放在一個text/plain主體中返
回。
2、響應碼
很多站點都沒有robots資源,機器人會根據robots檢索的結果采取不同的行動。
伺服器響應成功狀态,機器人則必須對内容進行解析,并使用排斥規則擷取站點内容
若為404,機器人則認為站點資源不收robots限制
若為401或403,機器人就應該認為此站點的通路時完全受限的
若是503,機器人就該推遲對站點的通路,知道可以擷取資源為止
若是重定向,機器人就該跟着重定向知道找到資源為止
9.4.3 robots.txt檔案的格式
采用了面向行的文法。robots.txt檔案中有三種類型的行:空行、注釋行、規則行。規
則行看起來就像HTTP首部一樣,用于模式比對。比如:
檔案中的行可以從邏輯上劃分成“記錄”。每條記錄都為一組特定的機器人描述了一
組排斥規則。
每條記錄都包含了一組規則行,由一個空行或者檔案結束符終止。記錄以一個或多個
User-Agent行開始,說明哪些機器人會受此記錄的影響,後面跟着一些disallow和
allow行,用來說明這些機器人可以通路哪些URL。
1、User-Agent行
如果機器人無法找到與其名字相比對的User-Agent行,而且也無法找到通配的User-
Agent: * 行,就是沒有記錄與之比對,通路不受限。
由于機器人名時與大小寫無關的子字元串進行比對,是以:User-Agent:bot 就與
Bot,Robot、Bottom-Feeder、Spambot等都相比對。
2、Disallow和Allow
用來說明顯示禁止或顯示允許特定機器人使用哪些URL路徑。
3、Disallow/Allow字首比對
Disallow和Allow規則要求大小寫相關的字首比對。空字元串可以起到通配符的效果。
進行比較之前,要将規則路徑或URL路徑中被轉義的字元都反轉為字元。%2f除外。
如果規則路徑為空字元串,就與所有内容都比對。
9.4.4 其他有關知識
機器人應該忽略所有他不了解的字段(在user-agent、disallow、allow之外)
為了實作向後相容,不能在中間斷行
注釋可以出現在檔案的任何地方
0.0版的機器人通路标準不支援Allow行。
9.4.5 緩存和robots.txt的過期
機器人會周期性擷取robots檔案,并緩存起來。在過期之前就一直使用緩存的副本。
緩存遵循标準的HTTP緩存控制機制。
如果沒有提供Cache-Control指令,規範草案允許将其緩存7天。
9.4.6 拒絕機器人通路的Perl代碼
9.4.7 HTML的robot-control元标簽
HTML頁面的作者有一種更直接的方式可以限制機器人通路那些獨立的頁面。可以直接
在HTML文檔中添加robot-control标簽。遵循這個HTML标簽規則的機器人仍然可以
擷取文檔,但如果有機器人排斥标簽,它們會自動忽略這些文檔。
機器人排斥标簽如下形式,通過HTML的META标簽實作:
1、機器人的META指令
NOINDEX:告訴機器人不要對頁面内容進行處理,忽略文檔(就是說不要在任何索引
或資料庫中包含此内容)
NOFOLLOW:告訴機器人不要爬行這個頁面的任何外連結。
INDEX:機器人可以對頁面内容進行索引
FOLLOW:機器人可以爬行外鍊
NOARCHIVE:機器人不該緩存這個頁面的本地副本
ALL:等價于INDEX/FOLLOW
NONE:等價于 NOINDEX/NOFOLLOW
與所有META标簽類似,機器人META标簽必須出現在HTML頁面的HEAD區域中。
2、搜尋引擎的META标簽
9.5 機器人規範
9.6 搜尋引擎
9.6.1 大格局
在WEB發展初期,搜尋引擎就是一些相當簡單的資料庫,可以幫助使用者在web上定位
文檔。而現在對于數十億頁面數百萬使用者,搜尋引擎就需要用複雜的爬蟲來擷取這些
頁面,還要用負載的查詢引擎處理使用者的查詢。
9.6.2 現代搜尋引擎結構
現在的搜尋引擎都建構了一些名為“全文索引”的複雜本地資料庫,裝載了全世界的
web頁面,以及這些頁面所包含的内容。這些索引就像web上所有文檔的卡片目錄一
樣。
搜尋引擎爬蟲會搜集web頁面,并将其添加到全文索引中去。同時,搜尋引擎使用者會
通過hotbot或Google這樣的web搜尋網關對全文索引進行查詢。web頁面總是在不斷
變化,而且爬行一大塊web很花時間,是以全文索引充其量就是web的一個快照。
9.6.3 全文索引
全文索引就是一個資料庫,給它一個單詞,它可以立即提供包含那個單詞的所有文
檔。建立了索引之後,就不需要對文檔自身進行掃描了。
9.6.4 釋出查詢請求
使用者向web搜尋引擎網關釋出一條請求時,會填寫一個HTML表單,他的浏覽器會用一
個HTTP GET或POST請求将這個表單發送給網關,網關程式對搜尋引擎請求進行解
析,并将web UI 查詢轉換成搜尋全文索引所需的表達式。
9.6.5 對結果進行排序,并提供查詢結果
一旦搜尋引擎通過其索引得到了查詢結果,網關應用程式就會擷取結果,并将其拼成
結果頁面提供給使用者。
相關性排名(relevancy ranking),這是對一系列搜尋結果的評分和排序處理。比
如,某個單詞出現在更多的文檔中。
9.6.6 欺詐
為了想要在搜尋引擎結果中排在前列,很多網管都列出了無數關鍵字,甚至是毫不相
關的,使用一些假冒頁面,或者采用欺詐的手段—-用網關應用程式來生成一些在某些
特定單詞上可以更好的欺騙搜尋引擎相關性算法的假冒頁面。
第十章 HTTP-NG
10.1 HTTP發展中存在的問題
複雜性:
HTTP相當複雜,而且其特性之間是互相依存的。由于複雜的、互相交織的要求,以及連
接管理、封包處理和功能邏輯之間的混合作用,想要實作HTTP軟體變得很難。
可擴充性:
HTTP很難實作遞增式擴充,很多流傳下來的HTTP應用程式中都沒有自主的功能性擴充技
術,使協定的擴充無法相容。
性能:
HTTP中的很多低效特性會随着高時延、低吞吐量的無線通路技術的廣泛使用而更加嚴重
傳輸依賴性:
HTTP是圍繞TCP/IP網絡協定棧設計的。
10.2 HTTP-NG的活動
10.3 子產品化及功能增強
NG工作組建議将協定子產品化為三層,而不是将連接配接管理、封包處理、伺服器處理邏輯和
協定方法全部混在一起。
第一層:封包傳輸層,這一層不考慮封包的功能,而是緻力于端點間封包的不透明傳輸。
該層支援各種子協定棧,主要負責處理高效封包傳輸以及處理。NG組為本層提出了一個
名為WebMUX的協定
第二層:遠端調用層,定義了請求/響應的功能,用戶端可以通過這些功能調用對伺服器
資源進行操作。本層試圖提供一種像CORBA/DCOM和JaveRMI那樣的面向對象的可擴充
架構。
第三層:web應用層,提供大部分的呢榮管理邏輯,所有的HTTP方法,以及HTTP/1.1首
部參數都是在這裡定義的。本層還支援其他建構在遠端調用基礎上的服務,比如
WebDAV。
10.4 分布式對象
分布式對象系統對可擴充性和功能特性都很有幫助。
10.5 第一層:封包傳輸
封包傳輸層為封包傳輸提供了一個API,無論底層實際采用的是什麼網絡協定棧都可以使
用。
本層關注的是提高封包傳輸的性能、其中包括:
對封包進行管道化和批量化傳輸
重用連接配接
同一條連接配接并行的複用多個封包流
對封包進行有效的分段,使封包邊界的确定更容易
10.6 第二層:遠端調用
本層提供了通用的請求/響應架構,用戶端可通過此架構對伺服器資源操作。本層并不關
心特定操作的實作及語義(緩存、安全性、方法邏輯等),它隻關心允許用戶端遠端調用
伺服器操作的接口。NG小組建議本層采用二進制連接配接協定。這個協定支援一種高性能的
可擴充技術,通過這種技術可以調用伺服器上經過良好描述的操作,并傳回結果。
10.7 第三層:web應用
本層是執行語義和應用程式特定邏輯的地方。這一層描述了一個用于提供應用程式特定服
務的系統,這些服務并不單一,不同的應用程式可能使用不同的API。HTTP-NG結構允
許多個應用共存于本層,共享底層特性,它還提供了一種添加新應用程式的機制。
10.8 webMUX
它實作了在一個複用的TCP連接配接上并行地傳輸封包。可以對以不同速度産生和消耗的獨立
封包流進行高效的分組,并将其複用到一條或少數幾條TCP連接配接上去。
10.9 二進制連接配接協定
HTTP-NG定義了一些“對象類型”,并為每種對象類型配置設定了一組方法。為每種對象類
型配置設定了一個URI,以便将對它的描述和它的方法宣傳出去。
二進制連接配接協定通過一條有狀态的連接配接承載了從用戶端發往伺服器的操作調用請求,以及
伺服器的應答。除了請求封包和應答封包外,這個協定還定義了幾種内部控制封包,用來
提高連接配接的效率和強壯性。
第三部分 識别、認證與安全
第十一章 用戶端識别與cookie機制
11.1 個性化接觸
HTTP最初是一個匿名、無狀态的請求/響應協定。伺服器處理來自用戶端的請求,然後向
用戶端回送一條響應。
比如電商網站:
個性化問候、有的放矢的推薦、管理資訊的存檔、記錄會話。
11.2 HTTP首部
From首部包含了使用者的E-mail位址,實際上通常由自動化的機器人或蜘蛛發送。
11.3 用戶端IP位址
通常HTTP首部不提供用戶端IP位址,但是WEB伺服器可以找到承載HTTP請求的TCP連接配接
另一端的IP位址。
Unix系統,函數調用getpeername就可以傳回發送端機器的用戶端ip位址
status = getpeername(tcp_connection_socket,…..)
但是ip僅能區分機器,而不能區分使用者。而且NAT的存在導緻一個ip後有許多用戶端。
HTTP代理和網關通常會打開一些新的,到伺服器的TCP連接配接。
11.4 使用者登入
為了使web站點的登入更加簡便,HTTP中包含了一種内建機制,可以用www-
Authenticate首部和Authorization首部向web站點傳送使用者相關資訊。
如果伺服器希望使用者登入,可以向浏覽器回送一條HTTP響應代碼401 Login Required。
然後浏覽器會顯示一個登入對話框,并用Authorization首部在下一條對伺服器的請求中
提供這些資訊。
隻要輸入了使用者名和密碼,浏覽器就重複原來的請求,這次會帶上使用者名和密碼。今後的
請求要使用使用者名和密碼時,浏覽器會自動将存儲下來的值發送出去,甚至站點沒有要求
發送時也會發送。
11.5 胖URL
有些web站點會為每個使用者生成特定版本的URL來追蹤使用者的身份。通常會對真正的URL
進行擴充,在URL路徑開始或結束的地方添加一些狀态資訊。使用者浏覽站點時,web服務
器會動态生成一些超鍊,繼續維護URL中的狀态資訊。
改動後包含了使用者狀态資訊的URL 稱為胖URL。如下例子:
可以通過胖URL 将web伺服器上若幹個獨立的HTTP事務捆綁成一個“會話”或“訪
問”。使用者首次通路這個web站點時,會生成一個唯一的ID,用伺服器可以識别的方式将
這個ID添加到URL中去,然後伺服器就會将用戶端重新導向這個胖URL。不論什麼時候,
隻要伺服器收到了對胖URL的請求,就可以去查找那個使用者ID相關的所有增量狀态(購物
車等),然後重寫所有的輸出超鍊,使其成為胖URL,以維護使用者的ID。
這個胖URL無法共享,因為包含了特定使用者的狀态資訊。為每個URL生成使用者特有版本就
意味着不再有可供公共通路的URL需要緩存了。而且會造成伺服器的額外負擔。
使用者跳轉到其他站點或請求一個特定URL時,就很容易在無意中“逃離”胖URL會話。導
緻丢失他的進展資訊,得重新開始。
除非使用者收藏了特定的胖URL,否則使用者退出時,所有資訊會丢失。
11.6 cookie
11.6.1 cookie的類型
籠統的分為兩類:會話cookie和持久cookie。
會話cookie是一種臨時cookie,它記錄了使用者通路站點時的設定和偏好。使用者退出浏
覽器時,會話cookie就被删除了。
持久cookie的生存時間更長一些,它們存儲在硬碟上,浏覽器退出,計算機重新開機時它
們已然存在。通常會用持久cookie維護某個使用者會周期性通路的站點的配置檔案和登
錄名會話cookie和持久cookie之間唯一的差別就是它們的過期時間。如果設定了
Discard參數,或者沒有設定Expires或Max-Age參數來說明擴充的過期時間,這個
cookie就是一個會話cookie。
11.6.2 cookie如何工作
使用者首次通路web站點時,web伺服器對使用者一無所知。伺服器希望這個使用者再次回
來,是以想給這個使用者設定一個cookie,這樣它就可以識别出這個使用者了。cookie中
包含了一個由名字=值(name=value)這樣的資訊構成的任意清單,并通過Set-
Cookie或Set-Cookie2 HTTP響應(擴充)首部将其添加到使用者身上。
cookie中可以包含任意資訊,但它們通常隻包含一個伺服器為了跟蹤而産生的獨特的
識别碼。浏覽器會記住從伺服器傳回的cookie内容,并将cookie集存儲在浏覽器的
cookie資料庫中。
11.6.3 cookie罐:用戶端的狀态
cookie的基本思想就是讓浏覽器積累一組伺服器特有的資訊,每次通路伺服器時都将
這些資訊提供給它。因為浏覽器要負責存儲cookie資訊,是以此系統被稱為用戶端側
狀态,這個cookie規範的正式名稱為HTTP狀态管理機制(HTTP state management
mechanism)。
1、網景的Navigator的cookie
存儲在一個名為cookies.txt的文本檔案中
文本檔案中每一行都代表一個cookie。有7個用tab鍵分隔的字段。
domain(域)—-cookie的域
allh—-是域中所有主機擷取cookie,還是隻有指定了名字的主機擷取
path—-域中與cookie相關的路徑字首
secure–是否隻有在使用SSL連接配接時才發送這個cookie
expiration–從格林尼治标準時間1970年1月1日00:00:00開始的cookie過期秒數
name—-cookie變量的名字
value—-cookie變量的值
2、微軟IE的cookie
IE将cookie存儲在高速緩存目錄下獨立的文本檔案中。可以通過浏覽這個目錄來檢視
cookie。
11.6.4 不同站點使用不同cookie
浏覽器通常隻向每個站點發送2-3個cookie,隻向伺服器發送伺服器産生的那些
cookie。很多WEB站點會與第三方廠商達成協定,由其來管理廣告。這些廣告做的像
web站點的一個組成部分,而且确實發送了持久cookie。使用者通路另一個由同一廣告
公司提供服務的站點,(由于域是比對的)浏覽器就會再次回送早先設定的持久
cookie。營銷公司可以将此技術與Referer首部結合,搜集使用者習慣。
1、cookie的域屬性
産生cookie的伺服器可以向Set-Cookie響應首部添加一個Domain屬性來控制哪些站
點可以看到這個cookie。
2、cookie的路徑屬性
cookie規範甚至允許使用者将cookie與部分web站點關聯起來。通過Path屬性實作。這
個屬性列出的URL路徑字首下所有cookie都是有效的。
Set-cookie: pref=compact; domain=”baidu.com”; path=/autos/
如果使用者通路www.baidu.com/autos/xxxx 就會帶上pref=compact cookie
11.6.5 cookie成分
現在使用的cookie規範有兩個不同的版本:0(Netscape cookies)和 1 (RFC
2965).
11.6.6 cookie版本0
有網景公司定義。版本0的cookie定義了set-cookie響應首部、cookie請求首部以及用
于控制cookie的字段。
1、版本0的set-cookie首部
2、版本0的cookie首部
用戶端發送請求時,會将所有與域、路徑和安全過濾器相比對的未過期cookie都發送
給這個站點。所有cookie都被組合到一個cookie首部中。
11.6.7 cookies 版本1(RFC 2965)
這個版本引入了Set-Cookie2首部和Cookie2首部,也能與版本0系統進行互操作。
主要改動:
@為每個cookie關聯解釋性文本
@允許在浏覽器退出時,不考慮過期時間,強制銷毀
@用相對秒數,而不是絕對日期來表示cookie的Max-Age
@通過URL端口号,而不僅是域和路徑來控制cookie的能力
@通過cookie首部回送域、端口和路徑過濾器(如果有)
@為實作互操作性使用的版本号
@在cookie首部從名字中區分出附加關鍵字的$字首
1、版本1的Set-Cookie2首部
2、版本1的Cookie首部
版本1的cookie會帶回與傳送的每個cookie相關的附加資訊,用來描述每個cookie途
徑的過濾器。
每個比對的cookie都必須包含來自相應set-cookie2首部的所有domain、port、path
屬性
3、版本1的cookie2首部和版本協商
cookie2請求首部負責在能夠了解不同cookie規範版本的用戶端和伺服器之間進行互操
作性的協商。cookie2首部告知伺服器,使用者Agent代了解析新形式的cookie,并提供
了所支援的cookie标準版本
如果伺服器了解新形式的cookie,就能識别出cookie2首部,并在響應首部發送set-
cookie2。如果用戶端從一個響應中同時擷取了set-cookie和set-cookie2首部,就會
忽略老的的set-cookie首部
如果用戶端即支援版本0又支援版本1的cookie,但從伺服器獲得版本0的set-cookie首
部,就該帶版本0的cookie首部發送cookie,而且還應該發送cookie2:
$version=“1”來告訴伺服器它是可以更新的。
11.6.8 cookie與會話跟蹤
可以用cookie在使用者與某個站點進行多項事務處理時對使用者進行跟蹤。
11.6.9 cookie與緩存
@如果無法緩存文檔,就要将其标示出來
文檔所有者最清楚文檔是否不可緩存。若不可緩存,需要顯式注明—-比如除了set-
cookie首部之外的文檔時可緩存的,就使用:Cache-Control: no-cache=“Set-
Cookie”。另一種更通用的做法是為可緩存文檔使用:Cache-Control: public,
這樣有助于節省帶寬。
@緩存set-cookie首部需要小心
若響應中有set-cookie首部,就可以對主體進行緩存。但需要注意對set-cookie的
緩存
有些緩存在将響應緩存起來之前會删除set-cookie首部,但這樣會引發一些問題。
強制緩存與伺服器重新驗證每條請求,并将傳回的所有set-cookie首部都合并到客
戶端的響應中去,可以改善此類情況。伺服器可以添加下面這個首部要求再驗證:
Cache-Control: must-revalidate, max-age=0
即便内容實際是可以緩存的,比較保守的緩存也可能會拒絕所有包含set-cookie首
部的響應。有些緩存允許緩存set-cookie圖檔,但不緩存文本模式。
@處理帶有cookie首部的請求
帶有cookie的請求到達,就是在提示得到的結果可能是私有的。一定要将私有内容
辨別為不可緩存的。
11.6.10 cookie、安全性和隐私
cookie是可以禁止的,而且可以通過日志分析或其他方式來實作大部分跟蹤記錄,所
有cookie自身并不是很大的安全隐患。
第十二章 基本認證機制
12.1 認證
認證就是要給出一些身份證明。
12.1.1 HTTP的質詢/響應認證架構
12.1.2 認證協定與首部
HTTP通過一組可定制的控制首部,為不同認證協定提供了一個可擴充架構。下表列出
的首部格式和内容會随着認證協定的不同而發生變化。認證協定也是在HTTP認證首部
中指定的。
HTTP定義了兩個官方的認證協定:基本認證和摘要認證。
12.1.3 安全域
WEB伺服器會将受保護的文檔組織成一個安全域(security realm)。每個安全域都可
以有不同的授權使用者集。
下面是一個假想的基本認證質詢,它指定了一個域:
HTTP/1.0 401 Unauthorized
WWW-Authenticate: Basic realm=“Corporate Financials”
域應該有一個描述性的字元名,幫助使用者了解應該使用哪個使用者名和密碼。
12.2 基本認證
基本認證中,伺服器可以拒絕一個事務,質詢用戶端,請使用者提供使用者名和密碼。伺服器
會傳回401狀态碼并指定安全域。浏覽器收到響應時會打開一個對話框,請使用者輸入這個
域的使用者名和密碼。然後将使用者名和密碼稍加擾碼,用Authorization首部回送給伺服器
12.2.1 基本認證執行個體
12.2.2 Base-64編碼
将一個8位位元組序列劃分為一些6位的塊,用每個6位的塊在一個特殊的由64個字元組
成的字母表中選擇一個字元。這個字母表包含大部分字母和數字。
12.2.3 代理認證
中間的代理也可以實作認證功能。可以在代理伺服器上對通路政策進行集中管理。代
理認證和伺服器認證的步驟相同,但是首部和狀态碼有所不同。
12.3 基本認證的安全缺陷
base-64編碼易解碼;
即使密碼難解碼,但是第三方仍可以捕獲到修改後的内容,并将修改過的使用者名密碼重放
給伺服器,獲得通路權限;
基本認證沒有提供任何針對代理和作為中間人的中間節點的防護措施,它們沒有修改認證
首部,但是卻修改了封包的其他部分,嚴重改變了事務的本質;
假冒伺服器很容易騙過基本認證。
第十三章 摘要認證
13.1 摘要認證的改進
永不以明文方式在網絡上發送密碼
可以防止惡意使用者捕獲并重放認證的握手過程
可以有選擇地防止對封包内容的篡改
防範其他幾種常見攻擊方式
13.1.1 用摘要保護密碼
用戶端會發送一個“指紋”或密碼的“摘要”,這是密碼的不可逆擾碼。用戶端和服
務器都知道密碼,是以伺服器可以驗證所提供的摘要是否與密碼比對。
13.1.2 單向摘要
摘要是一種單向函數,主要用于将無限的輸入值轉換為有限的輸出值,常見的摘要函
數MD5,會将任意長度位元組的序列轉換為一個128位的摘要。
MD5輸出的128摘要通常被寫成32個十六進制字元,每個字元表示4位。
13.1.3 用随機數防止重播攻擊
伺服器想用戶端發送一個稱為随機數的令牌。
13.1.4 摘要的握手機制
13.2 摘要的計算
13.2.1 摘要算法的輸入資料
摘要是根據下列三個元件計算:
由單向散列函數H(d)和摘要KD(s,d)組成的一對函數,其中s是密碼,d是資料
一個包含了安全資訊的資料塊,包括密碼,稱為A1
一個包含了請求封包中非保密屬性的資料塊,稱為A2
H 和 KD 處理兩塊資料A1,A2,産生摘要。
13.2.2 H(d)和 KD(s,d)
預設使用MD5算法
H(D)=MD5(D)
KD(S,D)=H(concatenate(S,D))
13.2.3 與安全性相關的資料A1
A1是密碼和受保護資訊的産物,包含有使用者名、密碼、保護域和随機數等内容。A1隻
涉及安全資訊,與底層封包無關。
RFC 2617定義了兩種計算A1的方式
MD5
為每條請求運作單向散列函數。A1是由冒号連接配接的 使用者名、域、密碼三元組
MD5-sess
隻在第一次WWW-Authenticate握手時運作一次散列函數,對使用者名、域、密碼進行
一次CPU密集型散列,并将其放在目前随機數和用戶端随機數(cnonce)的前面。
13.2.4 與封包有關的A2
A2表示的是域封包自身有關的資訊,比如URL,請求方法和封包實體的主體部分。A2
防止方法、資源或封包被篡改。A2會與H,KD,A1一起用于摘要的計算。
RFC 2617根據所選擇的保護品質(qop)、為A2定義了兩種政策:
1、隻包含HTTP請求方法和URL,當qop=“auth”時使用,是預設的
2、添加了主體部分,qop=“auth-int”時使用
13.2.5 摘要算法總述
13.2.6 摘要認證會話
用戶端響應對保護空間的WWW-Authenticate質詢時,會啟動一個此保護空間的認證
會話。
在用戶端收到另一條來自保護空間的任意一台伺服器的WWW-Authenticate質詢之
前,認證會話會一直持續。用戶端應該記住使用者名、密碼、随機數、随機數計數以及
一些與認證會話有關的隐晦值,以便将來在此保護空間中建構請求的Authorization首
部時使用。
随機數過期時,即便老的Authorization首部所包含的随機數不新鮮了,伺服器也可以
選擇接受其中的資訊。伺服器也可以傳回一個帶新随機數的401響應。讓用戶端重試此
請求,指定這個響應為stale=true,表示伺服器告知用戶端用新随機數重試,而不用輸
入使用者名和密碼。
13.2.7 預授權
普通認證方式中,事務結束之前,每個請求都要有一次請求/質詢的循環。
若用戶端事先知道下一個随機數是什麼,就可以取消這個請求/質詢循環。
三種獲得預先随機數的方式:
伺服器預先在Authentication-Info成功首部中發送下一個随機數
伺服器允許在一小段時間内使用同一個随機數
用戶端和伺服器使用同步的、可預測的随機數生成算法
1、預先生成下一個随機數
這種發送實際上破壞了對同一台伺服器的多條請求進行管道化的功能。因為在下一條
請求之前,一定要收到下一個随機數才行
2、受限的随機數重用機制
比如伺服器允許将某個随機數使用5此或使用10秒
這樣可能導緻重播攻擊。但是可以通過控制随機數生存周期達到平衡。或者通過其他
特性–增量計數器和IP位址測試。并不能完全消除安全隐患
3、同步生存随機數
13.2.8 随機數的選擇
13.2.9 對稱認證
通過提供用戶端随機值來實作對用戶端對伺服器的認證。隻要提供了qop指令,就要求
執行對稱認證。
13.3 增強保護品質
可以在三種摘要首部中提供qop字段:WWW-Authenticate、Authorization和
Authentication-Info。
通過qop字段,用戶端和伺服器可以對不同類型及品質的保護進行協商。比如,即便會嚴
重降低傳輸速度,有些事務也要檢查封包主體的完整性。
伺服器首先在WWW-Authenticate首部輸出由逗号分隔的qop選項清單,然後用戶端從
中選擇一個它支援且滿足需求的選項,并将其放在Authorization的qop字段中回送。
RFC 2617定義了兩種保護品質的初始值:表示認證的auth,帶有封包完整性保護的認證
auth-int。
13.3.1 封包完整性保護
若qop=“auth-int”,H(實體的主體部分)就是對實體主體部分,而不是封包主體
部分的散列。
對于發送者,要在應用任意傳輸編碼方式之前計算,對于接收者,則應去除所有編碼
之後計算。對于任何含有多個部分的内容類型來說,多個部分的邊界和每部分中嵌入
的首部都要包含在内。
13.3.2 摘要認證首部
13.4 應該考慮的實際問題
13.4.1 多重質詢
伺服器可以對某個資源發起多重質詢。比如既提供基本認證質詢,又提供摘要認證質
詢。用戶端面對多重質詢時,必須以它所能支援的最強的質詢機制來應答。
13.4.2 差錯處理
在摘要認證中,如果某個指令或其值使用不當,或者缺少某個必要指令,就應該使用
響應400 Bad Request。
如果請求的摘要不比對,就應該記錄一次登入失敗。
認證伺服器一定要確定URI指令指定的資源與請求行中指定的資源相同。如果不同,就
傳回400響應。這個字段包含的内容與請求URL中的内容時重複的,用來應對中間代理
可能對用戶端請求進行的修改。
13.4.3 保護空間
域值,與被通路伺服器的标準根URL結合在一起,定義了保護空間。
通過域可以将伺服器上的受保護資源劃分為一組保護空間,每個空間都有自己的認證
機制或授權資料庫。域值是一個字元串,通常由伺服器配置設定,可能會有認證方案特有
的附加語義。
保護空間确定了可以自動應用證書的區域。若之前某條請求已經被授權,在一段時間
内,該保護空間中所有其他請求都可以重用同一個證書。
對保護空間的具體計算取決于認證機制:
基本認證中,用戶端會假定請求URI中或其下的所有路徑都與目前的質詢處于同一個保
護空間内。用戶端可以預先送出對此空間中資源的認證,無需等待來自伺服器的另一
條質詢。
摘要認證中,質詢的WWW-Authenticate: domain字段對保護空間做了更精确的定
義。通常認為,domain清單中的所有URI和邏輯上處于這些字首之下的所有URI都位
于同一個保護空間中。
若沒有domain字段或該字段為空,質詢伺服器上的所有URI就都在保護空間内。
13.4.4 重寫URI
代理可以通過改變URI文法,而不改變所描述的實際資源的方式來重寫URI。
對主機名标準化或使用IP取代
可以用%轉義形式來取代嵌入的字元
若某類型的一些附加屬性不會影響從特定伺服器擷取資源,就可将其附加或插入到URI
中
13.4.5 緩存
共享的緩存收到包含Authorization首部的請求和轉接那條請求産生的響應時,除非響
應中提供了下列兩種Cache-Control指令之一,否則一定不能将那條響應作為對其他請
求的應答。
1、原始響應中Cache-Control有指令must-revalidate。 強制再驗證
2、包含指令public。
13.5 安全性考慮
13.5.1 首部篡改
為了提供一個簡單明了的防首部篡改系統,要麼進行端到端加密,要麼對首部進行數
字簽名。摘要認證的重點在于提供一種防篡改認證機制,但并不一定要将這種保護擴
展到資料上去。具有一定保護級别的首部隻有WWW-Authenticate和Authorization
13.5.2 重播攻擊
重播攻擊指有人将從某個事務中竊取的認證的證書用于另一個事務。
一種完全可避免重播攻擊的方式就是為每個事務都使用一個唯一的随機數。
13.5.3 多重認證機制
伺服器支援多重認證機制時,通常會在WWW-Authenticate首部提供選項。但是需要
讓用戶端去選擇可用認證方案中功能最強的。
13.5.4 詞典攻擊
密碼猜測
13.5.5 惡意代理攻擊和中間人攻擊
這種攻擊可以采用竊聽的形式,也可以删除提供的所有選項,用最弱的認證政策。
防止這些攻擊的唯一簡便方式是SSL
13.5.6 選擇明文攻擊
使用摘要認證的用戶端會用伺服器提供的随機數來生成響應。但如果中間有一個被入
侵的或惡意的代理在攔截流量,就可以很容易地為用戶端的響應計算提供随機數。使
用已知密鑰來計算響應可以簡化響應的密碼分析過程。這被稱為選擇明文攻擊
(chosen plaintext attack)。
預先計算的詞典攻擊
批量暴力型攻擊
13.5.7 存儲密碼
摘要認證機制将對比使用者的響應與伺服器内部存儲的内容。
與Unix機器中傳統的密碼檔案不同,如果摘要認證密碼檔案被入侵了,攻擊者就能馬
上使用域中的所有檔案,不需要再進行解碼了。
解決的方法:
就像密碼檔案中包含的是明文密碼一樣來保護它
確定域名在所有域中是唯一的。
第十四章 安全HTTP
14.1 保護HTTP的安全
HTTPS
使用HTTPS時,所有的HTTP請求和響應資料在發送到網絡之前,都要進行加密。
HTTPS在HTTP下面提供了一個傳輸級的密碼安全層。可以使用SSL,也可以使用其後繼
者—傳輸安全層(Transport Layer Security,TLS)。兩者類似,本書不太嚴格使用
SSL來表示SSL和TLS。
大部分困難的編碼及解碼工作都是在SSL庫中完成的,是以WEB用戶端和伺服器在使用安
全HTTP時無需過多的修改其協定處理邏輯。大多情況下,隻需要SSL的輸入\輸出調用取
代TCP的調用,再增加其他幾個調用來配置和管理安全資訊就行了。
14.2 數字加密
14.2.1 密碼編制的機制與技巧
密碼學是對封包進行編/解碼的機制與技巧。
14.2.2 密碼
密碼學基于一種名為密碼(cipher)的秘密代碼。密碼是一套編碼方案——一種特殊
的封包編碼方式和相應解碼方式的結合體。
14.2.3 密碼機
14.2.4 使用了密鑰的密碼
編碼算法和編碼機都可能會落入他人之手,是以大部分機器上有一些号盤,可以将其
設定為大量不同的值以改變密碼的工作方式。
這些密碼參數被稱為密鑰(key)。要在密碼機輸入正确的密鑰,解密過程才能正确進
行。
與金屬鑰匙或機械裝置中的号盤設定相比,數字密鑰隻是一些數字。這些數字密鑰值
是編/解碼算法的輸入。編碼算法就是一些函數,這些函數會讀取一塊資料,并根據算
法和密鑰值對其進行編/解碼。
14.3 對稱密鑰加密技術
在編碼時使用的密鑰值和解碼時一樣(E=D),這種的稱為對稱密鑰(symmetric-key),
統稱為密鑰k。
流行的對稱密鑰加密算法有:DES,Triple-DES,RC2,RC4
14.3.1 密鑰長度與枚舉攻擊
很多情況下,編/解碼算法是公開的,是以密鑰就是唯一保密的東西了。
好的加密算法會迫使攻擊者嘗試每個可能的密鑰,才能破解。用暴力去嘗試所有密鑰
值稱為枚舉攻擊(enumeration attack)。
可用密鑰值的數量取決于密鑰中的位數,以及可能的密鑰中有多少是有效的。就對稱
密鑰加密技術來說,通常所有的密鑰值都是有效的。但有些失部分有效,比如RSA,
有效密鑰必須以某種方式與質數相關,可能的密鑰值中隻有少量密鑰具備此特性。
14.3.2 建立共享密鑰
對稱密鑰加密的技術缺點之一就是發送者和接收者在互相對話之前,一定要有一個共
享的保密密鑰。
如果有N個節點,每個節點都要和其他所有N-1個節點進行安全對話,總共大概會有
N*N個密鑰,将變得很難管理。
14.4 公開密鑰加密技術
使用了兩個非對稱密鑰,一個用來對封包編碼,另一個用來對封包解碼。編碼密鑰是公開
的,但隻有主機才知道私有的解密密鑰。
将密鑰分隔開來可以讓所有人都能對封包進行編碼,但隻有其所有者才能對封包進行解
碼。
14.4.1 RSA
所有公開密鑰非對稱加密系統所面臨的共同挑戰是,要確定即便有人得到了下面的線
索也無法計算出私有密鑰:
##公開密鑰
##一小片攔截的封包
##一條封包與之相關的密文(對任意文本允許加密器就可以得到)
RSA算法就是這樣一個公開密鑰加密系統。破解它的難度相當于對一個極大的數進行
質因數分解的難度。
14.4.2 混合加密系統和會話密鑰
公開密鑰加密算法的計算可能會很慢,比較常見的是在兩個節點間通過公開密鑰加密
技術建立起安全通信,然後用安全通道産生并發送臨時的随機對稱密鑰,通過更快的
對稱加密技術對其餘的資料進行加密。
14.5 數字簽名
數字簽名是附加在封包上的特殊加密校驗碼。使用數字簽名有兩個好處:
1、簽名可以證明作者編寫了這條封包。隻有作者才會有最機密的私有密鑰。
2、簽名可以防止封包被篡改。
數字簽名通常是用非對稱公開密鑰技術産生的。
如下例子:
發送端–節點A将變長封包提取為定長的摘要。對摘要應用一個“簽名”函數,這個函數
會将使用者的私有密鑰作為參數 。一旦計算出簽名,節點A就将其附加在封包的末尾,并将
封包和簽名都發給B
接收端–如果節點B需要确定封包确實是A寫的,而且沒被篡改過,節點B就可以對簽名進
行檢查。B接收經私有密鑰擾碼的簽名,并應用了使用公開密鑰的反函數。如果拆包後的
摘要與節點B自己的摘要不比對,說明封包要麼被篡改了,要麼不是A的私有密鑰。
14.6 數字證書
數字證書中包含了由某個受信任組織擔保的使用者或公司的相關資訊。
14.6.1 證書的主要内容
對象的名稱(人、伺服器、組織等)
過期時間
證書釋出者
來自證書釋出者的數字簽名
數字證書通常還包括對象的公開密鑰、以及對象和所用簽名算法的描述性資訊。
14.6.2 X.509 v3證書
X.509 v3證書提供了一種标準的方式,将證書資訊規範至一些可解析字段中。
基于X.509 證書的簽名有好幾種,包括WEB伺服器證書、用戶端電子郵件證書、軟體
代碼證書和證書頒發機構證書
14.6.3 用證書對伺服器進行認證
通過HTTPS建立一個安全web事務之後,現代的浏覽器會自動擷取所連接配接伺服器的數
字證書,如果伺服器沒有證書,安全連接配接就會失敗。伺服器證書中包含很多字段,包
括:
web站點的名稱和主機名
web站點的公開密鑰
簽名頒發機構的名稱
來自簽名頒發機構的簽名
14.7 HTTPS——細節介紹
14.7.1 HTTPS概述
HTTPS就是在安全的傳輸層上發送的HTTP。HTTPS沒有将未加密的HTTP封包發送給
TCP,并進行傳輸,它在将HTTP封包發送給TCP之前,先發送給一個安全層,進行加
密。
14.7.2 HTTPS方案
在HTTPS協定中,URL的方案字首為https。請求一個用戶端對某web資源執行某事務
時,回去檢查URL的方案。
##若URL方案為http,用戶端就會打開一條到伺服器端口80(預設)的連接配接,并向其
發送老的HTTP指令。
##若是https方案,用戶端會打開到伺服器443端口的連接配接。然後與伺服器“握手”,
以二進制格式與伺服器交換一些SSL安全參數,附上加密的HTTP指令
SSL是個二進制協定,與HTTP完全不同,其流量承載在443端口。若到達80端口,大
部分web伺服器會将二進制的SSL流量,了解為錯誤的HTTP并關閉連接配接。
14.7.3 建立安全傳輸
用戶端首先打開一條到web伺服器端口443的連接配接。一旦建立了tcp連接配接,用戶端和服
務器就會初始化SSL層,對加密參數進行溝通,并交換密鑰。握手完成後,SSL初始化
就完成了,用戶端可以将請求封包發送給安全層了。在将這些封包發送給TCP之前,先
對其加密。
14.7.4 SSL握手
在發送已加密的HTTP封包之前,用戶端和伺服器要進行一次SSL握手,這個握手完成
以下工作:
#交換協定版本号
#選擇一個兩端都了解的密碼
#對兩端的身份進行認證
#生成臨時的會話密鑰,以便加密信道。
14.7.5 伺服器證書
SSL支援雙向認證,将伺服器證書承載回用戶端,将用戶端證書回送給伺服器。
伺服器證書是一個顯示了組織的名稱、位址、伺服器DNS域名以及其他資訊的X.509
v3 派生證書。
14.7.6 站點證書的有效性
有效性驗證步驟如下:
日期檢測——證書的起始和結束日期。
簽名頒發者可信度檢測——每個證書都是由某些證書頒發機構(CA)簽發的,它們負
責為伺服器擔保。有些證書會攜帶到受信CA的有效簽名路徑,浏覽器可能會選擇接受
所有此類證書。也就是說,如果某受信CA為“sam的簽名商店”簽發了一個證書,而
sam的簽名商店也簽發了一個站點的證書,浏覽器可能會将其作為從有效CA路徑導出
的證書而接受。
簽名檢測——一旦判定簽名授權是可信的,浏覽器就要對簽名使用簽名頒發機構的公
開密鑰,并将其與校驗碼進行比較,檢視證書的完整性。
站點身份檢測——為防止伺服器複制他人證書,或攔截其他人流量,大部分浏覽器都
會試着去驗證證書中的域名與它們所對話伺服器的域名是否比對。
14.7.7 虛拟主機與證書
有些流行的web伺服器程式隻支援一個真實,如果使用者請求的是虛拟主機名,與證書
名稱不嚴格比對,浏覽器就會告警。
為防止這個問題,在開始處理安全事務時,将所有使用者重定向到證書列出的官方主機
名。
14.8 HTTPS用戶端執行個體
14.8.1 OpenSSL
由一些志願者開發,目标是開發一個強壯而功能完備的商業級工具集,以實作SSL和
TLS協定以及一個全功能的通用加密庫。
14.8.2 簡單的HTTPS用戶端
14.8.3 執行OpenSSL用戶端
隻要完成了簽名4個部分,用戶端就有了一條打開的SSL連接配接。這樣它就可以查詢連接配接
的狀态,選擇參數,檢查伺服器證書了。
這個例子中,用戶端和伺服器對DES-CBC3-MD5批量加密密碼進行了溝通。
隻要建立起SSL信道,并且用戶端對站點證書無異議,就可以通過安全信道來發送
HTTP請求了。
14.9 通過代理以隧道形式傳輸安全流量
為了使HTTPS與代理配合工作,要進行幾處修改以告知代理連接配接到何處。一種常用技術就
是HTTPS SSL隧道協定。
使用HTTPS隧道協定,用戶端首先要告知代理,它想連接配接的安全主機和端口。這是在開始
加密之前以明文形式告知的。
HTTP通過新的名為CONNECT的擴充方法來發送明文形式的端點資訊。CONNECT方法
會告訴代理,打開一條到所期望主機和端口号的連接配接。
之後,直接在用戶端和伺服器之間以隧道形式傳輸資料。CONNECT方法就是一條單行的
文本指令,它提供了由冒号分隔的安全原始伺服器的主機名和端口号。
在請求中的空行之後,用戶端會等待來自代理的響應。代理會對請求進行評估,確定它是
有效的。如果一切正常,代理會建立一條到伺服器的連接配接。成功之後,就像用戶端發送
200 Connection Established響應
第四部分 實體、編碼和國際化
第十五章 實體和編碼
15.1 封包是箱子,實體是貨物
HTTP/1.1版定義了10個基本字型的實體首部字段:
Content-Type
實體中所承載對象的類型
Content-Length
所傳送實體主體的長度或大小
Content-Language
與所傳送對象最相配的人類語言
Content-Encoding
對象資料所做的任意變換(比如,壓縮)
Content-Location
一個備用位置,請求時可通過它來獲得對象
Content-Range
如果這是部分實體,這個首部來說明它是整體的哪個部分
Content-MD5
實體主體内容的校驗和
Last-Modified
所傳送内容在伺服器上建立或最後修改的日期時間
Expires
實體資料将要失效的日期時間
Allow
該資源允許的各種請求方法
ETag
這份文檔特定執行個體的唯一驗證碼。沒有正式定義為實體首部
Cache-Control
應該如何緩存文檔。同樣未正式定義為實體首部
實體主體
首部字段以一個空白的CRLF行結束,随後就是實體主體的原始内容。
15.2 Content-Length:實體的大小
這個大小是包含了所有内容編碼的,比如文本檔案進行了gzip壓縮,那麼大小就是壓縮後
的。
除非使用了分塊編碼,否則這個首部就是帶有實體主體的封包必須使用的。使用這個首部
是為了能夠檢測出伺服器崩潰而導緻的封包截尾,并對共享持久連接配接的多個封包進行正确
分段。
15.2.1 檢測截尾
HTTP早期版本采用關閉連接配接的方法來劃定封包的結束。但是,沒有Content-Length
的話,用戶端無法區分是否是封包結束時正常關閉連接配接。用戶端需要通過Content-
Length來檢測封包截尾。
15.2.2 錯誤的Content-Length
有些用戶端和伺服器以及代理包含了特别的算法,用來檢測和糾正與有缺陷伺服器的
互動過程。HTTP/1.1規定使用者Agent代理應該在接收接檢測到無效長度時通知客戶。
15.2.3 Content-Length與持久連接配接
Content-Length首部對于持久連接配接是必不可少的。但是在采用分塊編碼(chunked
encoding)時,使用持久連接配接可以沒有Content-Length首部。這種情況下,資料時
分為一系列的塊來發送的,每塊都有大小說明。哪怕伺服器在生成首部的時候不知道
整個實體的大小(通常因為是動态生成的),仍然可以使用分塊編碼傳輸若幹已知大
小的塊。
15.2.4 内容編碼
如果主體進行了内容編碼,則Content-Length首部就是編碼後的主體位元組長度。
15.2.5 确定實體主體長度的規則
①如果特定的HTTP封包類型中不允許帶有主體,就忽略Content-Length首部,它是
對(沒有實際發送出來的)主體進行計算的。這時,Content-Length首部是提示性
的,并不說明實際的主體長度。
例如HEAD響應,伺服器發送等價的GET請求中會出現的首部,但不要包括主體。
②如果封包中含有描述傳輸編碼的Transfer-Encoding首部,那實體就應由一個稱
為“零位元組塊”(zero-byte chunk)的特殊模式結束,除非封包已經因連接配接關閉而結
束。
③若封包中有Content-Length首部(且封包允許有實體主體)而沒有非恒等的
Transfer-Encoding首部字段,那麼Content-Length的值就是主體的長度。當上述兩
個首部同時存在時,就忽略Content-Length首部。
④若封包使用了multipart/byteranges(多部分/位元組範圍)媒體類型,且沒用
Content-Length首部指出實體主體的長度,那麼多部分封包中的每個部分都要說明它
自己的大小。
⑤如果上述規則都不比對,實體就在連接配接關閉時結束。
HTTP/1.1規範建議,對于帶有主體但沒有Content-Length首部的請求,伺服器如果
無法确定其封包長度,就該發送400 或 411 Length Required的響應,411表示服務
器要求收到正确的Content-Length首部。
15.3 實體摘要
伺服器使用Content-MD5首部發送對實體主體運作MD5算法的結果。隻有原始伺服器才
可以這麼做,中間代理和緩存不應該修改或添加這個首部。Content-MD5首部是在對内
容作了有所需要的編碼之後,還沒有做任何傳輸編碼之前,計算得出。用戶端需先進行傳
輸編碼的解碼,再計算所得的未進行傳輸編碼的實體主體的MD5。比如一份文檔經gzip
壓縮,然後采用分塊編碼發送,那麼就對整個gzip壓縮的主機進行MD5計算。
除了檢查完整性,MD5還可用來當做散清單的關鍵字來快速定位文檔。
作為對HTTP的擴充,建議增加新的Want-Digest首部,允許用戶端說明期望響應中使用
的摘要類型,并使用品質值來建議多種摘要并說明有限順序。
15.4 媒體類型和字元集
Content-Type的值是标準化的MIME類型,都在網際網路号碼配置設定機構(Internet Assigned
Numbers Authority,IANA)中注冊。MIME類型由一個主媒體類型後面跟一條斜線以及
一個子類型組成。
需注意,Content-Type首部說明的是原始實體主體的媒體類型,如果實體内容經過編碼的
話,說明的仍是編碼錢的實體主體類型。
15.4.1 文本的字元編碼
Content-Type首部支援可選的參數來進一步說明内容的類型。charset(字元集)參數
就是個例子。它說明把實體中比特轉換為文本檔案中的字元的方法。
Content-Type: text/html; charset=ios-8859-4
15.4.2 多部分媒體類型
mutipart電子郵件封包 中包含多個封包,它們合在一起作為單一的複雜封包發送。每一
部分獨立,有各自的描述其内容的集;不同部分之間用分界字元連接配接在一起。
HTTP也支援多部分主體。不過通常隻在兩種情況下:送出填寫好的表格、或是作為承載
若幹文檔片段的範圍響應。
15.4.3 多部分表格送出
當送出填寫的HTTP表格時,變長的文本字段和上傳的對象都作為多部分主體裡面獨立的
部分發送,這樣表格中就可以填寫各種不同類型和長度的值。
HTTP使用Content-Type:multipart/form-data 或 Content-Type:multipart/mixed
這樣的首部以及多部分主體來發送這種請求。例如:
Content-Type: multipart/form-data; boundary=[asdfghjk]
其中的boundary參數說明了分割主體中不同部分所用的字元串。
15.4.4 多部分範圍響應
HTTP對範圍請求的響應也可以是多部分的。Content-Type: multipart/byteranges首
部和帶有不同範圍的多部分主體。
15.5 内容編碼
15.5.1 内容編碼過程
①伺服器生成原始響應封包,其中有原始的Content-Type 和 Content-Length首部
②内容編碼伺服器(也可能就是原始伺服器的下行代理)建立編碼後的封包。編碼後的
封包有同樣的Content-Type但Content-Length可能不同(主體被壓縮)。内容編碼
伺服器在編碼後的封包增加Content-Encoding首部,這樣接收的應用程式就可以進
行解碼了。
③接收程式得到封包後,進行解碼,得到原始封包。
15.5.2 内容編碼類型
gzip、compress以及deflate編碼都是無損壓縮算法,這些算法中,gzip通常是效率最
高的。
15.5.3 Accept-Encoding首部
用戶端把自己支援的内容編碼方式清單放在請求的Accept-Encoding首部裡發送。若請
求中沒有該首部,伺服器就認為用戶端能夠接受任何編碼方式。
用戶端還可以給每種編碼附帶Q(品質)值來說明編碼的優先級。從0.0-1.0,大優。
15.6 傳輸編碼和分塊編碼
傳輸編碼也是作用在實體主體上的可逆變換,但使用它們是由于架構方面的原因,與内容的
格式無關。使用傳輸編碼是為了改變封包中的資料在網絡上傳輸的方式。
15.6.1 可靠傳輸
在HTTP中,隻有少數情況下,所傳輸的封包主體可能會引發問題。
@未知的尺寸
如果不先生存内容,某些網關應用程式和内容編碼器就無法确定封包主體的最終大
小。通常,這些伺服器希望在指定大小之前就開始傳輸資料。因為HTTP協定要求
Content=Length首部必須在資料之前,有些伺服器就使用傳輸編碼來發送資料,并
用特别的結束腳注表明資料結束。
@安全性
可以使用傳輸編碼來把封包内容擾亂,然後再傳輸。但是由于SSL的發展,很少使用
傳輸編碼來實作安全性了。
15.6.2 Transfer-Encoding首部
Transfer-Encoding首部用來告知接收方為了可靠的傳輸封包,已經對其進行了何種編碼
TE首部用在請求中,告知伺服器可以使用哪些傳輸編碼擴充。
傳輸編碼的值都是大小寫無關的。最新的HTTP規範隻定義了一種傳輸編碼——分塊編碼
TE首部也可以設定Q值,但是禁止将分塊編碼的Q值設定為0.0。
15.6.3 分塊編碼
分塊編碼把封包分割為若幹個大小已知的塊。塊之間緊挨着發送。
①分塊與持久連接配接
若用戶端和伺服器不是持久連接配接,用戶端就不需要知道它正在讀取的主體的長度,而
隻需要讀到伺服器關閉主體連接配接為止。
當使用持久連接配接,在伺服器寫主體之前,必須知道它的大小并在Content-Length首部
中發送。如果伺服器動态建立内容,就可能在發送之前無法知道主體的長度。分塊編
碼提供了解決方案,隻要允許伺服器把主體逐塊發送,說明每塊的大小就可以了。因
為主體是動态建立的,伺服器可以緩沖它的一部分,發送其大小和相應的塊,然後在
主體發送完之前重複這個過程。伺服器可以用大小為0的塊作為主體結束的信号,這樣
就可以繼續保持連接配接,為下一個響應做準備。
用戶端也可以發送分塊的資料給伺服器,但是并不知道伺服器是否接受,是以有可能
收到411 Length Required響應拒絕分塊請求。
②分塊封包的拖挂
若用戶端TE首部中說明它可以接受拖挂,就可以在分塊的封包最後加上拖挂。
拖挂中可以包含附帶的首部字段,它們的值在封包開始的時候可能是無法确定的。上
圖例子中的Content-MD5就是。封包首部中包含一個Trailer首部,列出了跟在分塊報
文之後的首部清單。
15.6.4 内容編碼與傳輸編碼的結合
15.6.5 傳輸編碼的規則
傳輸編碼集合中必須包括“分塊”,唯一例外是使用關閉連接配接來結束封包。
但使用分塊傳輸編碼時,它必須是最後一個作用到封包主體之上的。
分塊傳輸編碼不能多次作用到一個封包主體上。
如果伺服器收到無法了解的經過傳輸編碼的封包,應該用501 Unimplemented狀态碼回
複
15.7 随時間變化的執行個體
網站對象并不是靜态的。通用的URL會随着時間變化而指向對象的不同版本。
HTTP協定規定了稱為執行個體操控(instance manipulations)的一系列請求和響應操作,用
以操控對象的執行個體。兩個主要的執行個體操控方法就是:範圍請求和差異編碼。這兩種方法都要
求用戶端能夠标示它所擁有(如果有的話)的資源的特定副本,并在一定條件下請求新的實
例。
15.8 驗證碼和新鮮度
有條件的請求(conditional request),比如驗證緩存副本是否有效。這種請求要求客戶
端使用驗證碼(validator)來告知伺服器它目前擁有的版本号,并僅當它的目前副本不再
有效時才要求發送新的副本。
15.8.1 新鮮度
伺服器通過Expires和Cache-Control來告知用戶端将内容緩存多長時間。用戶端和服務
器為了能正常使用Expires首部,必須時鐘同步。
15.8.2 有條件的請求與驗證碼
有條件的請求是通過以”If-“開頭的有條件首部來實作。有條件的首部使得方法僅在條件
為真時才執行。若條件不滿足,伺服器就發回一個HTTP錯誤碼。
每個有條件的請求都通過特定的驗證碼來發揮作用。驗證碼是文檔執行個體的一個特殊屬
性,用來測試條件是否為真。從概念上說,可以把驗證碼看做檔案的序列号、版本号或
最後發生改變的日期。Last-Modified和ETag是HTTP使用的兩種主要驗證碼。
HTTP把驗證碼分為兩類:弱驗證碼和強驗證碼。弱驗證碼不一定能唯一辨別資源的一個
執行個體,而強驗證碼必須如此。弱驗證碼的一個例子是對象的大小位元組數。而資源内容的
加密校驗和(MD5)就是強驗證碼。
最後修改時間就被當做弱驗證碼。它的精度最大為1秒。ETag首部被當做強驗證碼。
有時候,用戶端和伺服器可能需要采用不那麼精确的實體标記驗證方法。例如,某服務
器可能想對一個很大、被廣泛緩存的文檔進行美化修飾,但不想在緩存伺服器再驗證時
産生很大的傳輸流量。這種情況下,伺服器可以在标記前面加上“W/”字首來廣播一
個“弱”實體标記。對于弱實體标記來說,隻有當關聯的實體在語義上發生了重大改變
時,标記才會變化。
15.9 範圍請求
通過範圍請求,HTTP用戶端可以通過請求曾擷取失敗的實體的一個範圍,來恢複下載下傳該實
體。但是有一個前提,就是從用戶端上一次請求該實體到這次發出範圍請求時間段内,對象
不曾改變。
上例中,用戶端請求的是文檔開頭4000位元組之後的部分。還可以用Range首部來請求多個
範圍。例如,用戶端同時連接配接到多個伺服器,為了加速下載下傳文檔而從不同伺服器下載下傳同一個
文檔的不同部分。伺服器可以通過在響應中包含Accept-Range首部的形式來向用戶端說明
可以接受的範圍請求。這個首部的值是計算範圍的機關,通常是以位元組計算的。
Range首部在流行的點到點(Peer-to-Peer,P2P)檔案共享用戶端軟體中得到廣泛應用。
注意範圍請求也屬于一類執行個體操控,是以針對特定的對象執行個體來交換資訊。也就是說,客戶
端的範圍請求僅當用戶端和伺服器擁有文檔的同一版本才有意義。
15.10 差異編碼
差異編碼通過交換對象改變的部分而不是完整對象來優化傳輸性能。(類似于增量更新),
它也是針對特定對象執行個體來交換資訊。
用戶端必須告訴伺服器它有頁面的哪個版本,願意接受頁面最新版的差異(delta),它懂
得哪些将差異應用于現有版本的算法。伺服器必須檢查它是否有這個頁面的用戶端現有版
本,計算用戶端現有版本與最新版之間的差異。然後伺服器必須計算差異,發送給用戶端,
告知用戶端所發送的是差異,并說明最新版頁面的新辨別(ETag)。
如果用戶端想告訴伺服器它願意接受該頁面的差異,隻要發送A-IM首部就可以了。A-IM是
Accept-Instance(接受執行個體操控)的縮寫。伺服器發送一個特殊的響應代碼——226 IM
Used,告知用戶端它正在發送的是所請求對象的執行個體操控,而不是完整的對象自身。
一個IM首部用于說明計算差異的算法。
新的ETag首部和Delta-Base首部說明用于計算差異的基線文檔的ETag。
執行個體操控、差異生成器和差異應用器
用戶端可以使用A-IM首部說明可以接受的一些執行個體操控的類型。伺服器在IM首部中說明使
用的是何種執行個體操控。
伺服器側的“差異生成器”根據基線文檔和該文檔的最新執行個體,用用戶端指明的算法計算差
異。用戶端側的“差異應用器”得到差異,将其應用于基線文檔,得到文檔的最新執行個體。
例如:采用Unix系統的diff-e指令産生差異。用戶端就可以用Unix系統中文本編輯器ed提
供的功能來應用差異,因為diff-e 産生一系列指令來把file1 轉化為 file2
diff-e算法是對檔案進行逐行比較,是以不适用二進制檔案。vcdiff算法更強大,且産生的
差異更小。
第十六章 國際化
16.1 HTTP對國際性内容的支援
伺服器通過HTTP協定的Content-Type首部中的charset參數和Content-Language首部告
知用戶端文檔的字母表和語言。
同時,用戶端發送Accept-Charset首部和Accept-Language首部,告知伺服器它了解哪些
字元集編碼算法和語言以及其中的優先順序。
16.2 字元集與HTTP
16.2.1 字元集是把字元轉換為二進制的編碼
HTTP字元集的值說明如何把實體内容的二進制碼轉換為特定字母表中的字元。每個字元
集标記都命名了一種把二進制碼轉換為字元的算法。
有些字元編碼(比如UTF-8,iso-2022-jp)更加複雜,它們是可變長編碼,也就是說每個
字元的位數都是可變的。這種類型的編碼允許使用額外的二進制位表示擁有大量字元的
字母表(比如漢語和日語),僅用較少的二進制位來表示标準的拉丁字元。
16.2.2 字元集和編碼如何工作
把二進制碼轉換為字元要經過兩個步驟:
①将二進制碼轉換成字元代碼,它表示了特定編碼字元集中某個編号的字元。
②字元代碼用于從編碼字元集中選擇特定的元素
16.2.3 字元集不對,字元就不對
16.2.4 标準化的MIME charset值
特定的字元編碼方案和特定的已編碼字元集組合成一個MIME字元集。
16.2.5 Content-Type首部和Charset首部以及META标志
伺服器可以通過charset參數把MIME字元集标記發送給用戶端。
如果沒有顯式列出字元集,接收方可能就要設法從文檔内容中推斷出字元集。對于HTML
内容來說,可以在描述charset的 标記中找到字元
集。
16.3 多語言字元編碼入門
16.3.1 字元集術語
①字元
字元是指字母、數字、标點、表意文字、符号或其他文本形式的書寫“原子”。
②字形
表述字元的筆畫圖案或唯一的圖形化形狀。若一個字元有多種寫法,就有多個字形。
③編碼後字元
配置設定給字元的唯一數字編号。
④代碼空間
計劃用于字元代碼值的整數範圍。
⑤代碼寬度
每個(固定大小的)字元代碼所用的位數。
⑥字元庫
特定的工作字元集(全體字元的一個子集)
⑦編碼後字元集
組成字元庫的已編碼字元集,并為每個字元配置設定代碼空間中的一個代碼。
⑧字元編碼方案
把數字化的字元代碼編碼成一系列二進制碼的算法。
16.3.2 字元
字元是書寫的最基本建構單元。
16.3.3 字形、連筆以及表示形式
16.3.4 編碼後字元集
編碼後字元集經常使用數組來實作,把整數映射到字元,通過代碼數值來索引,數組的
元素就是字元。
1、US-ASCII:所有字元集的始祖
American Standard Code for Information Interchange 美國标準資訊交換代碼。
代碼值隻是從0~127。
2、iso-8859
是US-ASCII的8位超集。為不同地區定制了不同字元集:
3、JIS X 0201
把ASCII擴充到日文半款片假名字元的一個極小化的字元集。Japanese Industrial
Standard——JIS
4、UCS
Universal Character Set,統一字元集。
16.3.5 字元編碼方案
①固定寬度
用固定數量的比特表示每個編碼後的字元。能夠被快速處理,但有可能浪費空間
②可變寬度(無模态)
對不同的字元代碼數字采用不同數量的比特。
③可變寬度(有模态)
有模态編碼使用特殊的“轉義”模式在不同的模态之間切換。例如,可以用有模态的
編碼在文本中使用多個互相有重疊的字元集。可以有效支援複雜的書寫系統。
16.4 語言标記與HTTP
英語的标記是en,德語是de,韓語是ko。巴西葡萄牙語是pt-BR,美式英語是en-US等等
16.4.1 Content-Language首部
描述實體的目标閱聽人語言。
16.4.2 Accept-Language首部
在該首部中可放入多個語言标記,從左到右的優先順序。
16.4.3 語言标記的類型
16.4.4 子标記
語言标記有一個或多個部分,用連字元分隔,稱為子标記。
16.4.5 大小寫
所有的标記不區分大小寫。習慣用小寫表示一般的語言,用大寫表示特定的國家。
16.4.6 IANA語言标記注冊
第一個和第二個語言子标記的值由各種标準文檔以及相關的維護組織定義。如果語言标
記由标準的國家和語言值組成,标記就不需要專門注冊。隻有那些無法用标準的國家和
語言值構成的語言标記才需要專門向IANA注冊。
16.4.7 第一個子标記——名字空間
第一個子标記通常是标準化的語言記号,選自ISO 639語言标準集合。不過也可以用字母
i來辨別在IANA中注冊的名字,或x表示私有的或擴充的名字。
16.4.8 第二個子标記——名字空間
第二個子标記通常是标準化的國家記号,選自ISO 2166中的國家代碼和地區标準集合。
其餘子标記——除了最長可以到8個字元之外,第三個和其後的子标記沒有特殊規則。
16.5 國際化的URI
轉義和反轉義
第十七章 内容協商與轉碼
17.1 内容協商技術
有三種方法可以決定伺服器上哪個頁面最适合用戶端:讓用戶端選擇、伺服器判定,或讓中
間代理來選。我們稱之為:用戶端驅動的協商、伺服器驅動的協商、透明協商。
17.2 用戶端驅動的協商
伺服器實際上有兩種方法為用戶端提供選項:一是發送回一個HTML文檔,裡面有到該頁面
的各種版本的連結和每個版本的描述資訊;二是回送300 Multiple Choices響應碼。客戶
端浏覽器收到這種響應時,前一種情況下,會顯示一個帶有連結的頁面;後一種情況下、可
能會彈出對話視窗,讓使用者做選擇。無論如何,決定是由用戶端的浏覽器使用者做出的。
除了增加延時并對每個頁面進行多次請求之外,還有一個缺點就是需要多個URL:公共頁面
一個,每種特殊頁面一個。
17.3 伺服器驅動的協商
有兩種機制可供HTTP伺服器評估發送什麼響應給用戶端比較合适。
①檢查内容協商首部集。伺服器可檢視用戶端發的Accept首部集。
②根據其他非内容協商首部進行變通。例如,根據用戶端的User-Agent首部來發響應。
17.3.1 内容協商首部集
需要注意這些與之前的實體首部非常類似,但是實體首部集像運輸标簽,它描述了把報
文從伺服器傳輸給用戶端的過程必須的各種封包主體屬性。而内容協商首部集是由客戶
端發送給伺服器用于交換偏好資訊的。
由于HTTP是無狀态協定,伺服器不會再不同的請求間追蹤用戶端的偏好,是以用戶端必
須在每個請求中發送偏好資訊。
17.3.2 内容協商首部中的品質值
Accept-Language: en;q=0.5, fr;q=0.0 , nl;q=1.0, tr;q=0.0
注意排列順序并不影響,隻關心q值。
當伺服器找到可比對的偏好情況,伺服器可以修改文檔,通過轉碼來比對用戶端的偏
好。
17.3.3 随其他首部集而變化
伺服器也可以根據其他首部集來比對響應,比如User-Agent首部,伺服器知道老版本的
浏覽器不支援JavaScript語言,這樣就不向其發送有JavaScript的頁面版本。
由于緩存需要盡量提供文檔中正确的”最佳“版本,HTTP協定定義了伺服器在響應中發
送的Vary首部。這個首部告知緩存(還有用戶端和所有下遊的代理)伺服器根據哪些首
部來決定發送響應的最佳版本。
17.3.4 Apache中的内容協商
将索引頁面檔案放在和站點相關的Apache伺服器的适當目錄下。兩種方式啟用内容協
商:
①在網站目錄中,為網站中每個有變體的URI建立一個type-map(類型映射)檔案。這
個type-map檔案列出了每個變體和其相關的内容協商首部集。
②啟用MultiViews指令。這樣會使Apache自動為目錄建立type-map檔案。
1、使用type-map檔案
Apache伺服器需要知道type-map檔案的命名規則,可在伺服器的配置檔案中設定
handler來說明type-map檔案的字尾名。
AddHandler type-map .var
2、使用MultiView
前提是必須在網站目錄下的access.conf檔案中的适當小結
(//)使用OPTION指令來啟用。
啟用之後,如果浏覽器請求了名為joes-hardware的資源,伺服器就會查找所有名字裡
含有此内容的檔案,并為它們建立type-map檔案。
17.3.5 伺服器端擴充
比如微軟的ASP Active Server Pages。
17.4 透明協商
17.4.1 進行緩存與備用候選
17.4.2 Vary首部
HTTP的Vary響應首部中列出了所有用戶端請求首部,伺服器可以用這些首部來選擇文檔
或産生定制内容。例如,若提供的文檔取決于User-Agent首部,Vary首部就必須包含
User-Agent首部。
新請求到達時,緩存會根據内容協商首部集來尋找最佳比對。但在把文檔提供給用戶端
之前,它必須檢查伺服器有沒有在已緩存響應中發送Vary首部。如果有,那新請求中那
些首部的值必須與舊的已緩存請求裡相應的首部相同。
17.5 轉碼
17.5.1 格式轉換
格式轉換可以由内容協商首部集來驅動,也可以由User-Agent首部來驅動。
17.5.2 資訊綜合
從文檔中提取關鍵的資訊片段稱為資訊綜合(information synthesis),這種操作的例
子包括根據小節标題生成文檔大綱,或者從頁面中删除廣告和商标。
根據内容關鍵字對頁面分類是更精細的技術,常用于web頁面分類系統,如門戶網站。
17.5.3 内容注入
前面兩類轉碼通常會減少文檔内容,但内容注入會增加文檔内容,比如自動廣告生成器
和使用者追蹤系統。
17.5.4 轉碼與靜态預生成的對比
轉碼的替代做法是在web伺服器上建立web頁面的不同副本。
第五部分 内容釋出與分發
第十八章 WEB主機托管
對内容資源的存儲、協調以及管理的職責統稱為WEB主機托管。
18.1 主機托管服務
18.2 虛拟主機托管
18.2.1 虛拟伺服器請求缺乏主機資訊
18.2.2 設法讓虛拟主機托管正常工作
4中技術:
①通過URL路徑進行主機托管
在URL中增添專門的路徑部分,以便伺服器判斷是哪個網站。
産生多餘的字首,而且描述首頁連結的常見約定:http://xxx.sss.com/index.html 就不
能用了。
②通過端口号進行主機托管
③通過IP位址進行主機托管
為不同的虛拟站點配置設定專門IP位址,把這些位址都綁定到一台單獨的機器上。這樣,
web伺服器可以通過IP位址來識别網站名。
伺服器可以通過查詢HTTP連接配接的目的ip位址,來判定用戶端的目标網站。
在計算機系統上能綁定的虛拟IP位址通常是由限制的。
IP位址是稀缺資源。有很多虛拟站點的托管者不一定能為被托管的網站擷取足夠多的IP。
想要通過複制伺服器來增加容量時,IP位址短缺的問題就更嚴重了。
④通過HOST首部進行主機托管
HTTP/1.0增強版和HTTP/1.1正式版定義了Host首部來攜帶網站名稱。
18.2.3 HTTP/1.1 的Host首部
1、文法與用法
Host = “Host” “:” host [ “:” port ]
注意:
若URL中包含IP,Host首部就應當包含同樣的位址。
若URL中包含主機名,Host首部必須包含同樣的名字。而且不應該包含這個主機名對應
的ip位址和包含這個主機名的其他别名。
若用戶端顯示使用代理,用戶端就必須把原始伺服器的名字和端口放在Host首部中。
HTTP/1.1 的web伺服器必須用400 狀态碼來響應所有缺少Host首部的HTTP/1.1請求報
文。
2、缺少Host首部
少量老式浏覽器不發送Host首部,這樣伺服器可能會把使用者導向某個預設頁面,也可能
傳回錯誤頁面提示客戶更新。
3、解釋Host首部
若在HTTP請求封包中URL是絕對的(包含方案和主機部分),就忽略Host首部的值。
若URL中沒有主機部分,而請求帶有Host首部,主機、端口就從host首部中取。
前兩步無法擷取有效主機,傳回400響應。
18.3 使網站更可靠
18.3.1 鏡像的伺服器叢集
鏡像的伺服器常常組成階層化的關系。某個伺服器可能充當“内容權威”——它含有原
始内容。這個伺服器稱為主原始伺服器(master origin server),從主原始伺服器接收
内容的鏡像伺服器稱為複制原始伺服器(replica origin server)。一種簡單的部署是用
網絡交換機把請求分發給伺服器。每個網站的ip位址就設定為交換機的ip位址。
分散的鏡像伺服器可以通過HTTP重定向和DNS重定向來把用戶端的請求導向特定的服務
器。
18.3.2 内容分發網絡
内容分發網絡(CDN)就是對特定内容進行分發的專門網絡。這個網絡的中間節點可以是
伺服器、反向代理或緩存。
18.3.3 CDN中的反向代理緩存
複制原始伺服器可以通過反向代理緩存來代替。反向代理緩存可以像鏡像伺服器一樣接
受伺服器請求。它們代表原始伺服器中的一個特定集合來接收伺服器請求。
反向代理和鏡像伺服器之間的差別在于反向代理通常是需求驅動的。它們不會儲存原始
伺服器的全部内容副本,它們隻儲存用戶端請求的那部分内容。内容在其告訴緩存中的
分布情況取決于它們收到的請求,原始伺服器不負責更新它們的内容。有些反向代理具
有“預取”特性,可在使用者請求之前就從伺服器上載入内容。
18.3.4 CDN中的代理緩存
與反向代理不同在于,傳統的代理緩存能收到發往任何WEB伺服器的請求。代理緩存的
内容一般都是按需驅動的,不能指望它是對原始伺服器内容的精确複制。按需驅動的代
理緩存可以部署在攔截環境中,2層或3層裝置可以攔截web流量并發送給代理緩存。
第十九章 釋出系統
19.1 FrontPage為支援釋出而做的伺服器擴充
FrontPage是微軟提供的一種通用web寫作和釋出工具包。
19.1.1 FrontPage伺服器擴充
這些伺服器端元件和web伺服器內建在一起,在網站和運作FrontPage的用戶端(以及
其他支援這些擴充的用戶端)之間提供了必要的轉接工作。
我們主要關注FrontPage用戶端和FPSE之間的釋出協定。
FrontPage的釋出協定在HTTP的POST請求之上實作了一個RPC(Remote Procedure
Call,遠端過程調用)層。它允許FrontPage用戶端向伺服器發送指令來更新網站上的文
檔、進行搜尋以及在多個web作者之間進行協作。
web伺服器看到以FPSE(在非IIS伺服器上就以一組CGI程式的方式實作)為接收位址的
POST請求,就對其進行相應的引導。隻要中間的防火牆和代理都配置為允許使用POST
方法,FrontPage就能與伺服器持續通信。
19.1.2 FrontPage術語表FrontPage
虛拟伺服器
在同一伺服器上運作的多個網站之一,每個都有唯一的域名和ip位址。支援虛拟服務
器的web伺服器稱為多路托管(multi-hosting)web伺服器。配置有多個ip位址的機
器稱為多宿主(multi-homed)伺服器。
根web
web伺服器預設的頂層内容目錄,或是在多路托管環境下,虛拟web伺服器的頂層内
容目錄。要通路根web,隻需指定伺服器的URL,每個伺服器隻能有一個根web。
子web
根web的已命名子目錄或另一個完全由FPSE擴充的子web。子web可以是完全獨立的
實體,能夠指定自己的管理和寫作權限。此外,子web還能提供方法(比如搜尋)的
作用範圍。
19.1.3 FrontPage的RPC協定
該協定建構在POST方法之上,它把RPC的方法及其相關的變量嵌入在POST請求的主體
中。
在開始處理之前,用戶端需要知道伺服器上目标程式(FPSE包中能夠執行這些POST請
求的相關部分)的位置和名稱。接下來它會發送一個特殊GET請求。
1、請求
POST請求的主體包含RPC指令,形式是method= 及任何需要的參數。
與CGI程式一樣,方法中的空格被編碼為“+”,所有其他非字母數字的字元被編碼
為%XX的格式。
某些元素的含義:
service_name
方法應該在該URL表示的網站上執行。必須是已有檔案夾或者已有檔案夾的下層檔案夾
listHiddenDocs
若為true,則顯示網站中隐藏的文檔。所謂隐藏就是指其URL的路徑部分以”_”開頭。
listExploreDocs
值為true,就列出任務清單。
2、響應
大多數RPC協定方法都有傳回值,大多常見的傳回值都用來表示方法成功 和各種錯誤。
有些方法還有第三種類别的傳回值,稱為“采樣傳回碼”。FrontPage會對這些代碼進
行适當的解釋,為使用者提供準确的回報。
19.1.4 FrontPage的安全模型
FPSE安全模型定義了3中使用者:管理者、作者以及浏覽者。所有權限都是累積的,就是
說所有的管理者都能編寫和浏覽FrontPage的網站。類似的,所有作者都有浏覽權限。
對于給定的由FPSE擴充的網站,管理者、作者、以及浏覽者的清單都要定義好,所有的
子web可以從根web繼承權限,也可以自定義。對于非IIS伺服器,所有的FPSE程式都要
儲存在标記為“可執行”的目錄中。
在IIS伺服器上,權限是通過給定根web目錄或子web的根目錄上的ACL來制定的。當IIS
收到請求,首先登入,并模拟使用者,接着發送請求到上述的三個DLL之一。收到請求的
DLL根據目标檔案夾上定義的ACL檢查所扮演使用者的證書。若通過,則請求的操作由擴充
DLL來執行,否則向用戶端發回“permission denied”封包。
19.2 WebDAV與協作寫作
WebDAV(web Distributed Authoring and Versioning,分布式寫作與版本管理)為
web釋出增添了新的功能——協作。
19.2.1 WebDAV的方法
WebDAV定義了一些新的HTTP方法并修改了其他一些HTTP方法的操作範圍。
PROPFIND——擷取資源的屬性。
PROPPATCH——在一個或多個資源上設定一個或多個屬性。
MKCOL——建立集合
COPY——從指定的源端把資源或者資源集合複制到指定的目的地。目的地可在另外一
台機器上。
MOVE——與COPY類似,但是是剪切。
LOCK——鎖定一個或多個資源。
UNLOCK——将之前的鎖定的資源解鎖。
WebDAV修改的HTTP方法有DELETE/PUT/OPTIONS.
19.2.2 WebDAV與XML
WebDAV的方法通常都需要在請求和響應中關聯大量的資訊。HTTP通常用封包首部來交
換這類資訊。然而,這有一定的局限性,包括難以有選擇地對請求中多個資源應用首部
資訊、不利于表示層次結構等。
借助XML解決這個問題:
@對那些描述資料處理方式的指令進行格式化的方法。
@在伺服器上對複雜的響應進行格式化的方法。
@交換與所處理的集合和資源有關的定制資訊的方法。
@承載資料自身的靈活工具
19.2.3 WebDAV首部集
DAV——用于了解伺服器的WebDAV能力。WebDAV支援的所有資源在響應OPTIONS
請求時都要含有此首部。
DAV = “DAV” “:” “1” [“,” “2”] [ “,” 1#extend ]
Depth——用于把WebDAV擴充到支援含有多級層次關系的資源組。類似于目錄深度。
用到Depth首部的方法有:LOCK/COPY/MOVE
Destionation——用來輔助COPY或MOVE方法識别目标URI。
If——定義的唯一一個狀态令牌是鎖定令牌。If首部定義了一組條件,如果這些條件都取
實踐中,最常見的需要滿足的條件是先獲得鎖。
Lock-Token——UNLOCK方法需要這個首部指定要删除的鎖。LOCK方法的響應中也有
Lock-Token首部,載有關于鎖定令牌的必須資訊。
Overwrite——用于COPY/MOVE方法,指定是否要覆寫目标。
Timeout——用戶端用這個請求首部指定要求鎖定的逾時值。
19.2.4 WebDAV的鎖定與防止覆寫
WebDAV支援兩種類型的鎖:
1—對資源或集合的獨占寫鎖
2—對資源或集合的共享寫鎖
獨占寫鎖保證隻有鎖的擁有者有寫權限。這種鎖完全消除了潛在的沖突。共享寫鎖允許
多個人在某個給定的檔案上工作。WebDAV通過PROPFIND方法提供了屬性發現機制,
可以判斷對鎖定的支援和所支援的鎖定的類型。
WebDAV中有兩個新方法支援鎖定機制:LOCK UNLOCK
為了實作鎖定,還需要有一種識别作者的機制。WebDAV采用的是摘要認證。
準許鎖定時,伺服器将域内唯一的令牌傳回給用戶端。與此相關的規範是
opaquelocktoken鎖定令牌URI方案。當用戶端随後要執行寫操作時,它連接配接到伺服器
并完成摘要認證步驟。一旦認證完成,WebDAV用戶端就發出帶有鎖定令牌的PUT請
求,這樣,隻有正确的使用者加上鎖定令牌才可以完成寫操作。
19.2.5 LOCK方法
WebDAV中的一個強大特性就是它能夠允許單個LOCK請求鎖定多個資源。WebDAV的
鎖定不要用戶端保持與伺服器的連接配接。
送出的XML以 元素作為基元素。在 結構中,有以下3中子元素:
元素充當着存儲鎖資訊的容器。嵌在其中的子元素有 ,它
持有請求發送來的資訊。此外 中含有以下子元素。
用稱為opaquelocktoken的URI方案唯一辨別的鎖。該令牌用于在将來的請求中辨別鎖
的所有權。
它是Depth首部的值的副本。
指明鎖的逾時時間。
1、opaquelocktoken方案
設計用來在所有時間内對所有資源提供唯一令牌的方案。為了確定唯一性,WebDAV規
範采用IS0-11578中描述的UUID機制。
在實際實作時,有一定的回旋餘地。伺服器可以選擇為每個LOCK請求生成一個UUID,
或者生成單個UUID并通過在結尾附加額外的字元來維護唯一性。如果采用後者,就必須
保證附加的擴充部分永遠不會重用。
2、XML元素
該元素提供了發現活躍的鎖的機制。如果有人試圖去給已經被鎖定檔案上鎖,他會收到
指明目前擁有者的XML元素 ,列出了所有未解除的鎖和響應的屬性。
3、鎖的重新整理和Timeout首部
為了重新整理鎖,用戶端需要重新送出鎖定請求,并把鎖定令牌放在If首部中。
除了接受伺服器給定的逾時時間,用戶端可以在Timeout首部中指定要求的逾時值。
伺服器沒有義務必須滿足這些選項。但是,用戶端必須在XML元素 中提供鎖
定過期的時間。無論如何,鎖定逾時隻是一個指導值,伺服器不一定受其限制。管理者
可以重設,某些異常時間也可能導緻伺服器重設鎖,用戶端應避免鎖定時間太長。
19.2.6 UNLOCK方法
用于解除資源上的鎖。
要使UNLOCK操作成功,WebDAV要滿足:已經成功完成了摘要認證,,要與在Lock-
Token首部中發送的鎖定令牌相比對。
若解鎖成功,會向用戶端發送204 No Content狀态碼。
19.2.7 屬性和中繼資料
屬性描述了資源的資訊,包括作者名字、修改日期、内容分級等等。HTML中的元标記的
确提供了把這種資訊嵌入在内容之中的機制,但很多中資源(二進制資料)都無法嵌入
中繼資料。
像WebDAV這樣的分布式協作系統對屬性的需求就更複雜了。比如文檔被編輯後,應該
更新這個屬性以反映新的作者。WebDAV專門把這種可動态修改的屬性稱為“活”屬
性。與之相對的是更長久的靜态屬性,比如Content-Type, “死”屬性。
19.2.8 PROPFIND方法
該方法用于擷取一個給定檔案或一組檔案(集合)的屬性。它支援3中類型的操作:
@請求所有屬性及其值
@請求一組屬性及其值
@請求所有屬性的名稱
請求原始指定了從PROPFIND方法傳回的屬性。下面這些清單總結了用于
PROPFIND請求的一些XML元素:
- 要求傳回所有屬性的名字和值。
- 指定要傳回屬性名字的集合
- 指定需要傳回值的屬性。例如: ……
《HTTP權威指南》學習筆記第一部分 HTTP:WEB的基礎第二部分 HTTP結構第三部分 識别、認證與安全第四部分 實體、編碼和國際化第五部分 内容釋出與分發 ——多重響應的容器
——辨別資源的URI。
——包含特定請求的HTTP狀态碼。
——将一個和 元素組織在一起。
19.2.9 PROPPACH方法
該方法為對指定資源設定或删除多個屬性提供了原子化機制。原子化機制可以保證要麼
所有請求都成功,要麼跟所有請求都沒發出一樣。
PRPPATCH方法的XML基元素是 。它作為一個容器使用,容納了需要
修改的屬性。
指定要設定的屬性值。含有一個或多個 子元素。若屬性已經存在,其值被覆寫。
指定要删除的屬性。
《HTTP權威指南》學習筆記第一部分 HTTP:WEB的基礎第二部分 HTTP結構第三部分 識别、認證與安全第四部分 實體、編碼和國際化第五部分 内容釋出與分發 《HTTP權威指南》學習筆記第一部分 HTTP:WEB的基礎第二部分 HTTP結構第三部分 識别、認證與安全第四部分 實體、編碼和國際化第五部分 内容釋出與分發 19.2.10 集合與名字空間管理
集合是指對預定義的層次結構中的資源進行的邏輯或實體上的分組。集合的一個典型例
子就是目錄。集合作為其他資源(也包括其他集合)的容器使用。類似于檔案系統中的
目錄一樣。
WebDAV使用了XML的名字空間機制。XML名字空間的分區在阻止所有名字空間沖突的
同時,還允許進行精确的結構控制。
WebDAV提供5中方法對名字空間進行操作。
19.2.11 MKCOL方法
該方法允許用戶端在伺服器上指定的URL處建立集合。
《HTTP權威指南》學習筆記第一部分 HTTP:WEB的基礎第二部分 HTTP結構第三部分 識别、認證與安全第四部分 實體、編碼和國際化第五部分 内容釋出與分發 假設集合已經存在,那麼請求會失敗,狀态碼是405 Method Not Allowed。
若沒有寫權限,狀态碼是403
若發出MKCOL /colA/colB,而colA不存在,狀态碼是409 Conflict。
19.2.12 DELETE方法
若要删除一個目錄,就要提供Depth首部。若沒有指定Depth首部,則該目錄的所有文
件和子目錄都被删除。響應中也有Content-Location首部,其值就是剛被删除的集合。
《HTTP權威指南》學習筆記第一部分 HTTP:WEB的基礎第二部分 HTTP結構第三部分 識别、認證與安全第四部分 實體、編碼和國際化第五部分 内容釋出與分發 删除集合時,若某個檔案被其他人鎖定,那麼集合自身也無法删除,伺服器會以207狀态
碼響應。
《HTTP權威指南》學習筆記第一部分 HTTP:WEB的基礎第二部分 HTTP結構第三部分 識别、認證與安全第四部分 實體、編碼和國際化第五部分 内容釋出與分發 19.2.13 COPY MOVE方法
COPY和MOVE方法都将請求URL作為源,HTTP的Destination首部的内容作為目标。
MOVE方法還需要把源URL複制到目的地,檢查新建立的URI的完整性,再把源删除。
《HTTP權威指南》學習筆記第一部分 HTTP:WEB的基礎第二部分 HTTP結構第三部分 識别、認證與安全第四部分 實體、編碼和國際化第五部分 内容釋出與分發 在對集合進行操作時,COPY和MOVE的行為受到Depth首部的影響。若Depth值為0,
方法就隻作用于資源本身。
對于MOVE方法,Depth值隻允許為無窮大。
1、Overwrite首部的效果
若設定該首部的值為T而且目标已存在,就在COPY或MOVE 之前對目标資源進行Depth
值為無窮大的DELETE操作。若設定為F,而目标資源存在,則操作失敗。
2、對屬性的COPY/MOVE
複制集合或元素時,預設會複制其所有屬性。但請求可以帶有可選的XML主體來提供額
外的操作資訊。
《HTTP權威指南》學習筆記第一部分 HTTP:WEB的基礎第二部分 HTTP結構第三部分 識别、認證與安全第四部分 實體、編碼和國際化第五部分 内容釋出與分發 3、被鎖定的資源與COPY/MOVE
資源被鎖定就禁止移動或複制到目标上。若在一個自己有鎖的現存集合中建立目标,所
複制或移動的資源就會被加到那個鎖中。
《HTTP權威指南》學習筆記第一部分 HTTP:WEB的基礎第二部分 HTTP結構第三部分 識别、認證與安全第四部分 實體、編碼和國際化第五部分 内容釋出與分發 《HTTP權威指南》學習筆記第一部分 HTTP:WEB的基礎第二部分 HTTP結構第三部分 識别、認證與安全第四部分 實體、編碼和國際化第五部分 内容釋出與分發 19.2.14 增強的HTTP/1.1方法
1、PUT方法
WebDAV修改了該方法以支援鎖定。
《HTTP權威指南》學習筆記第一部分 HTTP:WEB的基礎第二部分 HTTP結構第三部分 識别、認證與安全第四部分 實體、編碼和國際化第五部分 内容釋出與分發 為了支援鎖定,WebDAV在PUT請求中增加了If首部。
2、OPTIONS方法
用戶端可以用OPTIONS方法驗證WebDAV的能力。
《HTTP權威指南》學習筆記第一部分 HTTP:WEB的基礎第二部分 HTTP結構第三部分 識别、認證與安全第四部分 實體、編碼和國際化第五部分 内容釋出與分發 DAV首部攜帶了DAV遵從級别的資訊。有兩類遵從:
①要求伺服器遵從RFC2518每節中的所有MUST需求。若資源隻能達到第一類遵從,就
在DAV首部中發送1。
②滿足所有第一類的需求,并增加對LOCK方法的支援。除LOCK方法之外,第二類遵從
還要求支援Timeout和Lock-Token首部以及 和 這倆
元素。
DASL首部說明了在SEARCH方法中使用的查詢文法的類型。
第二十章 重定向與負載均衡
20.3 重定向協定概覽
①配置建立用戶端封包的浏覽器應用程式,使其将封包發送給代理
②NDS解析程式會選擇用于封包尋址的IP位址。對于不同實體地域,這個ip可能不同。
③web伺服器可以通過HTTP重定向将請求反彈給不同的web伺服器。
20.4 通用的重定向方法
20.4.1 HTTP重定向
伺服器将短的重定向封包發回給用戶端實作重定向。與其他形式重定向相比,優點之一
就是重定向伺服器知道用戶端的IP位址;理論上講,它可以做出更合理的選擇。
缺點:
@需要原始伺服器進行大量處理來判斷要重定向到哪台伺服器上去。
@增加了使用者延時,因為通路頁面需要進行兩次往返
@若重定向伺服器故障,站點就會癱瘓。
20.4.2 DNS重定向
DNS解析程式可能是用戶端自己的作業系統,可能是客戶是網絡中的一台DNS伺服器,
或者是一台遠距離的DNS伺服器。DNS允許将幾個IP位址關聯到一個域中,可以配置
DNS解析程式或對其進行程式設計,以傳回可變的IP位址。
1、DNS輪轉
在web伺服器叢集中平衡負載。這是一種單純的負載均衡政策,沒有考慮任何用戶端與
伺服器的相對位置,或伺服器目前的負載情況。
2、多個位址及輪轉位址的循環
大多數DNS用戶端隻會使用多位址其中的第一個位址。為了均衡負載,大多數DNS服務
器都會在每次完成查詢之後對位址進行輪轉。這種位址輪轉通常稱作DNS輪轉。
3、用來平衡負載的DNS輪轉
4、DNS緩存帶來的影響
由于DNS查找的結果可能被記住,并被各種應用程式、作業系統和一些簡易的子DNS服
務器重用。很多WEB浏覽器都會對DNS查找,然後一次次的使用相同的位址,以減少
DNS查找的開銷。是以,DNS輪轉通常不會平衡單個用戶端的負載。
5、其他基于DNS 的重定向算法
負載均衡算法——DNS伺服器會跟蹤伺服器的負載,将負載最輕的伺服器放在清單最前
面。
鄰接路由算法——DNS伺服器将使用者導向地理上最近的web伺服器。
故障屏蔽算法——DNS伺服器可以監視網絡的狀況,并将請求繞過有故障的地方。
通常,運作複雜伺服器跟蹤算法的DNS伺服器就是在内容提供者控制之下的一個權威服
務器。
10.4.3 任播尋址
在任播尋址中,幾個地理上分散的web伺服器擁有完全相同的IP位址,而且會通過骨幹
路由器的“最短路徑”路由功能将用戶端的請求發送給離它最近的伺服器。要使用這種
方法工作,每台伺服器都要向鄰近的骨幹路由器廣告,表明自己是一台路由器。
20.4.4 IP MAC轉發
四層交換機可以檢測出四層位址(ip 和 端口号),并由此來選擇路由。在一條四層交換
機上可将所有的目的端口為80的web流量都發送到某個代理上去。
因為MAC位址轉發隻是點對點的,是以伺服器或代理隻能位于離交換機一跳遠的地方。
20.4.5 ip位址轉發
在IP位址轉發中,交換機或其他四層裝置會檢測輸入分組中的ip位址,并通過修改目的ip
位址對分組進行相應的轉發。這種類型的轉發稱為NAT。
還有個問題就是對稱路由。
有兩種方式可以控制響應傳回的路徑:
①将分組的源ip位址改成交換機的ip位址。這種方式稱為完全NAT,其中的IP轉發裝置會
對目的IP位址和源IP位址都進行轉換。這樣的缺點是伺服器不知道用戶端的IP位址。
②若源IP位址仍然是用戶端的ip位址,就要確定沒有從伺服器到用戶端的直接路由(繞過
交換機的)。
20.4.6 網元控制協定
NECP允許網元(NE,路由器和交換機等負責轉發IP分組的裝置)與伺服器元素進行交
互。 NECP并未顯式提供對負載均衡的支援;它隻是為SE(伺服器元素)提供了一種發
送負載均衡資訊給NE的方式,這樣NE就可以在它認為合适的情況下進行負載均衡了。
NECP支援例外。SE可以決定它不能為某些特定的源IP位址提供服務,并将這些位址發送
給NE。然後NE可以将來自這些IP位址的請求轉發給原始伺服器。
20.5 代理的重定向方法
20.5.1 顯式浏覽器配置
有兩個缺點:
代理無法響應的情況下,也不會去聯系伺服器。
對網絡架構進行修改,并将這些修改通知給所有的終端使用者都是很困難的。
20.5.2 代理自動配置
通過代理自動配置協定(PAC)。必須配置浏覽器,為這個PAC檔案關聯一個特定的服
務器。這樣,浏覽器每次重新開機的時候都可以擷取這個PAC檔案了。
PAC檔案是個JavaScript檔案,其中必須定義函數:
function FindProxyForURL(url, host)
浏覽器要為請求的每條URL調用這個函數:
return_value = FindProxyForURL(url_of_request, host_in_url);
其傳回值是一個字元串,用來說明浏覽器應該到哪裡請求這個URL。傳回值可以是所關
聯代理名稱清單(比如, PROXY proxy1.domain.com)或是字元串“DIRECT”,這個字元
串說明浏覽器應該繞開所有的代理,直接連接配接原始伺服器。
20.5.3 web代理自動發現協定
1、PAC檔案自動發現
WPAD允許HTTP用戶端定位一個PAC檔案,,并使用這個PAC檔案找到适當的代理服務
器的名字。
WPAD協定發現了PAC檔案URL,這個URL也被稱為配置URL (CURL)。
2、WPAD算法
資源發現的技術:
DHCP
SLP(服務定位協定)
DNS知名主機名
DNS SRV記錄
DNS TXT記錄中提供的服務URL
這5個技術中,要求WPAD用戶端必須支援DHCP和DNS知名主機名技術。
用戶端會按順序使用上面的技術發送一系列資源發現請求。用戶端隻會嘗試它們所支援
的機制。隻要某次嘗試成功了,用戶端就會用得到的資訊來建構PAC CURL。
若從那個CURL上成功擷取PAC檔案,則過程結束。如果沒有,用戶端就從它在預定義的
資源發現請求系列裡中斷的地方開始恢複。若嘗試了所有的技術之後,仍未擷取到PAC
檔案,WPAD協定就失敗了,用戶端會配置為不使用代理。
用戶端首先會嘗試DHCP,然後是SLP.接着是DNS的機制。
用戶端會在DNS SRV/知名主機名和DNS TXT記錄等方法中循環多次。每次DNS查找都
會在QNAME前加上wpad,用以說明請求的資源類型。
3、用DHCP進行CURL發現
必須将CURL存儲在WPAD用戶端可以查詢的DHCP伺服器上。如果DHCP伺服器中配置
了這種資訊,就可以在DHCP可選代碼252中擷取CURL。
若WPAD用戶端已經在其初始化過程中執行了DHCP查詢,DHCP伺服器可能就已經提供
了那個值。若無法通過用戶端OS API獲得這個值,用戶端就向DHCP伺服器發送一條
DHCPINFORM封包擷取這個值。
可選代碼252是STRING類型,可以是任意長度。包含了一個指向PAC檔案的URL。
4、DNS A記錄查找
必須将合适代理伺服器的IP位址存儲在WPAD用戶端可以查詢的DNS伺服器上。WPAD
用戶端會向DNS伺服器發送一個A記錄查詢,以擷取CURL。成功查詢到的結果中會包含
代理伺服器的IP位址。
5、擷取PAC檔案
隻要建立了CURL,WPAD用戶端通常會向CURL發送一條GET請求。同時,必須發送一些
帶有适當CFILE格式資訊的Accept首部。這些CFILE格式都是它們所能處理的。
6、何時執行WPAD
下列兩種情況
①web用戶端啟動的時候
②隻要有來自網絡棧的通知,就說明用戶端主機的IP位址變了
用戶端還必須根據HTTP的過期時間,為之前下載下傳的PAC檔案的過期時間嘗試一個發現周
期。PAC檔案過期時,用戶端遵循過期時間,重新運作WPAD過程是很重要的。
7、WPAD欺騙
IE5實作允許在用戶端不幹預,自動檢測代理設定。第三級域名可能是不可信的。
8、逾時
每個階段限制在10秒内是比較合理的。
20.6 緩存重定向方法
WCCP重定向
Cisco系統公司開發的WCCP可以是路由器将web流量重定向到代理緩存中去。WCCP負責
路由器和緩存伺服器之間的通信,這樣路由器就可以對緩存進行驗證,在緩存之間進行負載
均衡,并将特定的流量發給特定的緩存。
1、WCCP重定向如何工作
@啟動包含了一些支援WCCP的路由器和緩存的網絡,它們之間可以互相通信。
@一組路由器及其目标緩存構成一個WCCP服務組。服務組的配置說明了要将何種流量發往
何處、流量是如何發送以及如何在服務組的緩存之間進行負載均衡。
@若服務組配置為重定向HTTP流量,服務組中的路由器就會将HTTP請求發送給服務組中的
緩存。
@HTTP請求抵達服務組中的路由器時,路由器會(根據對請求IP的散列或掩碼/值的配對策
略)選擇服務組中的某個緩存為請求提供服務。
@路由器向緩存發送請求分組,可以用緩存的IP位址來封裝分組,也可以通過IP MAC轉發
實作。
@若緩存無法為請求提供服務,就将分組傳回給路由器進行普通轉發。
@服務組中成員互相交換心跳。
2、WCCP2封包
3、封包元件
每條WCCP2封包都由一個首部和一些元件構成。首部資訊包含封包類型、WCCP版本和報
文長度(不包括首部的長度)。
每個元件都以一個描述元件類型和長度的4位元組首部開始。元件長度不包括元件首部的長
度。
4、服務組
5、GRE分組封裝
支援WCCP的路由器會用伺服器的IP位址将HTTP分組封裝起來,将其重定向到特定的服務
器上去。分組封裝中還包含了IP首部的proto字段,用來說明通用路由器封裝(GRE).proto
字段的存在告訴接收代理,它有一個封裝的分組。
6、WCCP負載均衡
WCCP可以在幾個接收伺服器之間進行負載均衡。若某特定接收伺服器停止發送心跳,
WCCP路由器就會将請求流量直接發到網際網路上,再收到心跳,再次向節點發送。
20.7 網際網路緩存協定
ICP允許緩存在其兄弟緩存中查找命中内容。ICP是一個對象發現協定。它會同時詢問附近
多個緩存,看看它們的緩存中是否有特定的URL。附近緩存如果有,就傳回一個簡短的封包
HIT,若沒有,就傳回MISS。然後,緩存就可以打開一條到擁有此對象的鄰居緩存的HTTP
連接配接了。
ICP封包是一個以網絡位元組序表示的32位封裝結構,這樣更便于解析。可以由UDP承載報
文,但是UDP并不可靠,是以使用ICP的程式要具有逾時功能,以檢測丢失的資料報。
1、Opcode–操作碼
8位二進制值,用以描述ICP封包的含義。基本的opcode包括ICP_OP_QUERY請求封包和
ICP_OP_HIT/ICP_OP_MISS響應封包。
2、版本
8位的版本号。
3、封包長度
以位元組為機關的ICP封包總長。因為隻有16位,是以ICP封包長度不能超過16383位元組。
URL通常都小于16KB。
4、請求編号
用請求編号來記錄多個同時發起的請求和響應。ICP應答封包必須與觸發應答的ICP請求報
文數相同。
5、選項
32位的選項字段是個包含了若幹标記的位矢量,這些标記可用來修改ICP的行為。ICPv2定
義了兩個标記,ICP_FLAG_HIT_OBJ 用來啟動或禁止在ICP響應中傳回文檔資料。
ICP_FLAG_SRC_RTT 标記請求由兄弟緩存測量的、到原始伺服器環回時間的估計值。
6、可選資料
ICPv2使用了可選資料的低16位來裝載從兄弟緩存到原始伺服器的可選環回時間的估計值
7、發送端主機位址
承載了封包發送端32位IP位址的著名字段,實際中并未使用。
8、淨荷
淨荷内容的變化取決于封包的類型。對ICP_OP_QUERY來說,淨荷是一個4位元組的原始請求
端主機位址,後面跟着一個由NUL結尾的URL。對ICP_OP_HIT_OBJ 來說,淨荷是一個由
NUL結尾URL,後面跟着一個16位的對象長度,接着是對象資料。
20.8 緩存陣列路由協定
CARP是微軟和網景提出的一個标準,通過這個協定來管理一組代理伺服器。
CARP是ICP的一個替代品。
通過ICP協定連接配接起來的每個代理伺服器都是将内容進行了備援鏡像的獨立緩存伺服器,這
就說明在不同的代理伺服器之間複制web對象條目是可行的。而用CARP連接配接起來的一組服
務器會被當做一個大型伺服器,其中每個元件伺服器都隻包含全部緩存文檔的一部分。
但CARP的缺點就是,如果某個代理伺服器不可用了,就要重新修改散清單以反映這種變
化,而且必須重新配置現存代理伺服器上的内容。
CARP重定向需要完成:
1、儲存一個參與CARP的代理伺服器清單。周期性地查詢這些代理伺服器,看它們是否活
躍。
2、為每個代理伺服器計算一個散列函數。散列函數的傳回值要考慮此代理所能處理的負載
量。
3、定義一個獨立的散列函數,這個函數會根據所請求的web對象的URL傳回一個數字。
4、将URL散列函數的結果代入代理伺服器的散列函數,得到一個數字陣列。這些數字中的
最大值決定了要為這個URL使用的代理伺服器。
上述4個任務,可以有浏覽器、插件或中間伺服器執行。
為每個代理伺服器叢集建立一個表,表中列出了叢集中所有伺服器。表中的每個條目都應該
包含全局參數的相關的資訊,比如,負載因子、生存時間、倒計數值和應該以和頻率查詢成
員之内的全局參數。可以通過TPC接口對此表進行遠端維護。隻要表中的字段被RPC修改
了,就可以使其對下遊的用戶端和代理可見、或将其釋出給它們。這項釋出工作是在HTTP
中進行的,這樣,所有的用戶端或代理伺服器都可以在不引入另一種代理間協定的基礎上消
化表格資訊了。用戶端和代理伺服器隻用了一個知名的URL 來擷取這張表。
20.9 超文本緩存協定
ICP協定中,在向兄弟緩存查詢資源是否存在時,隻允許緩存發送URL。HTCP允許兄弟緩
存之間通過URL和所有的請求及響應首部來互相查詢文檔是否存在。而且HTCP允許兄弟緩
存監視或請求在對方的緩存中添加或删除所選中的文檔,并修改對方已緩存文檔的緩存策
略。
首部——Header部分包含32位的封包長度,8位的主要協定版本和8位的次要協定版本。報
文長度包含所有首部、資料和認證部分的長度。
資料——Data部分包含了HTCP封包,結構如圖20-5所示,資料元件如表20-6所示。
20.9.1 HTCP認證
認證部分是可選的。結構如圖所示:
20.9.2 設定緩存政策
SET封包允許緩存請求對已緩存文檔的緩存政策進行修改。
第二十一章 日志記錄與使用情況跟蹤
21.1 記錄内容
通常隻記錄事務的基本資訊就可以了:
HTTP方法;
用戶端和伺服器的HTTP版本;
所請求資源的URL;
響應的HTTP狀态碼;
請求和響應封包的尺寸;
事務開始時的時間戳;
Referer首部和User-Agent首部的值。
21.2 日志格式
21.2.1 常見日志格式
最常見的日志格式就是常用日志格式。最初由NCSA定義。
注意,remotehost字段可以是主機名也可以是IP位址。
21.2.2 組合日志格式
在常用日志格式上增加了兩個字段:User-Agent和Referer。
21.2.3 網景擴充日志格式
擴充了常用日志格式,以支援與代理和web緩存這樣的HTTP應用程式相關的字段。
21.2.4 網景擴充2日志格式
21.2.5 Squid代理日志格式
Squid代理緩存源于早期的一個web代理緩存項目。是一個開源項目,有很多工具可以用
來輔助管理Squid應用程式。
21.3 命中率測量
原始伺服器通常處于計費的目的保留詳細的日志記錄。
但是緩存伺服器位于用戶端和伺服器之間,處理了很多請求。這樣,伺服器就會有日志檔案
遺漏。是以,内容提供者會對其最重要的頁面進行緩存清除,有意将這些内容設定為無法緩
存。
代理緩存會自己保留日志,是以可以通過命中率測量協定來讓緩存周期性的向原始伺服器彙
報緩存通路的統計資料。
21.3.1 概述
命中率測量協定定義了一種HTTP擴充,提供一些基本功能,緩存和伺服器可以實作這些
功能來共享通路資訊,規範已緩存資源的可使用次數。
21.3.2 Meter首部
通過Meter首部,緩存和伺服器在互相間傳輸與用法和報告有關的指令。這與Cache-
Control首部很類似。