HTTP緩存的基本目的就是使應用執行的更快,更易擴展,可是HTTP緩存一般只適用於idempotent request(能夠理解爲查詢請求,也就是不更新服務端數據的請求),這也就致使了在HTTP的世界裏,通常都是對Get請求作緩存,Post請求不多有緩存。html
然而,咱們有的時候也會遇到一些idempotent request並不能經過Get來實現的時候,例如,搜索API一般會須要不少的參數,尤爲是那些擁有不少屬性的產品,而這些屬性都必須經過參數來傳遞。問題來了,若是請求攜帶的參數超過了GET請求的限制長度怎麼辦,下面有一些回答:算法
當須要很是多的參數的時候,你可能須要從新評估一些接口的設計,減小一些參數來知足Get的限制。緩存
規範中並無強制性限制,因此咱們不該該責備http規範,可是http客戶端和服務器會有限制,例若有的支持最大的上限爲8k,有的爲2k服務器
看到這些,咱們發現上面這些回答都不是很滿意,他們並無給出實質的解決方案。ide
HTTP 緩存基礎工具
在看其餘內容以前,讓咱們來快速看一些http緩存的機制。post
HTTP緩存涉及到客戶端、代理和服務器。這篇文章咱們將討論的主要是代理服務器,位於客戶端和服務器之間。一般狀況下,反向代理部署在服務器附近,正向代理一般離客戶端比較近。下圖展現了基本的拓撲結構,正向代理的高速緩存命中節省帶寬,並減小往返時間和延遲,反向代理的高速緩存命中下降服務器的負載。.net
HTTP的協議規範容許知足下列條件中其一的以緩存來響應。設計
緩存的響應與原始服務器的響應是一致的,簡而言之就是說代理能夠保證緩存的響應和服務器的響應之間的語義等價。代理
到客戶端的響應的新鮮度是能夠接受的
到客戶端的響應的新鮮度不可接受,可是附加了合適的警告。
協議中還有更多的關於請求響應頭和控制的規範,能夠參看:http://tools.ietf.org/html/rfc2616
一個典型的代理服務器緩存idempotent request。該代理獲取請求,檢查頭信息,而後發送到服務器,收到服務器的響應後,檢查,若是是可緩存的,則將這個響應以URL爲key(會攜帶一部分頭信息)以響應爲內容緩存起來。這種辦法對已Get請求頗有效,由於反覆調用相同的URL將會有相同的響應。代理能夠利用idempotent request來緩存get請求。可是對於不是idempotent request的post請求來說,不能使用URL和頭信息來做爲key進行緩存,由於響應多是不一樣的,相同的URL可是獲得了不一樣的結果。
POST內容摘要
解決辦法是將POST的內容(附帶一部分頭信息),作一個摘要,將摘要附在URL後面,使用這個來做爲緩存的key。換句話說,緩存主鍵被修改成包括URL以及一些請求體,後續的擁有相同的請求體的請求將會命中緩存。在實踐的過程當中我添加了一些頭腦保證緩存的惟一性。一般的,雖然咱們沒有一個標準的推薦算法,若是你使用md5的話,你能夠加上Content-MD5做爲一個頭
如今的問題就是該區分idempotent request的post請求和非idempotent request的post請求了。這裏有幾種方法能夠處理這個問題
在代理中配置URL的匹配模式,代理若是匹配到非idempotent request請求就不緩存。
在頭中添加context-aware以區分不一樣的請求
基於緩存邏輯的一些命名約定,例如API的名稱以set、add、delete等開頭的就不被緩存。
處理非idempotent request請求
下面咱們來解決非idempotent request的問題
當出現下面的任何一種狀況的時候,將請求發給原服務器
若是URL在「DO NOT CACHE」列表中
若是摘要不匹配
過了緩存的有效時間
任何收到須要從新驗證的請求的時候
附加可能已是過期的內容的警告,以知足規範
容許用戶經過客戶端的工具關閉代理來直接訪問原服務器。
咱們使用定製的緩存POST請求的key的方式使用Apache Traffic Server實現了這個解決方案。
優點
這個解決方案提供了下面的好處
加快了重複請求的效率,減小了代理到原服務器之間的往返
一個用戶的請求不只能夠用做緩存該用戶的後續請求,其餘用戶也可共享
節省了代理和原服務器之間的帶寬
這裏有一個請求API響應時間的對比,
無緩存延時:188ms
有緩存延時:90ms
這個解決方案的變種能夠用在正向代理和反向代理,甚至二者都用
緩存握手
爲了從該解決方案的最大價值,在這個解決方案中,咱們在客戶端和服務器端部署了正向代理和反向代理。客戶端發送請求到正向代理,代理服務器在高速緩存沒有命中的狀況下發送請求的摘要到反向代理。反響代理在緩存中查找,若是找到則將請求返回,所不一樣的一點是,咱們從正向代理到反向代理並不發送完整的請求。服務器向反向代理髮送完整的響應,而反向代理只向正向代理髮送響應的摘要。因爲反向代理和服務器之間通常是出於同一個局域網中,延遲較小,而正向代理和客戶端之間的延遲也比較小,當大量的重複請求發送的時候就可以體會着這種解決方案的優點了
總結
HTTP的緩存不只能夠用於Get請求,經過對Post體的摘要、處理非idempotent request請求和區別idempotent request和非idempotent request請求,能夠實現對Post的緩存。固然爲了進一步提升效率,可使用緩存握手的方式,在互聯網上只發送摘要,在客戶端和正向代理以及反向代理和服務端之間的局域網類發送完整的消息體。