javascript欄目的介紹搞定伺服器。
前言
伺服器是指:為了降低伺服器端的存取頻率,減少通訊數量,前置將取得的資料資訊保存下來,當再次需要的時候,就使用所保存的資料。
儲存對使用者體驗和通訊成本都會造成很大的影響,所以要注意去靈活使用儲存機制。
#伺服器的工作原理
#HTTP
伺服器是一個以時間為維度的伺服器。
瀏覽器在第一次請求中伺服器了回應,而後續的請求可以從快取中取出第一次請求的回應。從而達到:減少時延並且還能降低頻寬消耗,因為可能壓根就沒有發出請求,所以網路的吞吐量也下降了。
工作原理
瀏覽器發出第一次請求,伺服器回傳回應。如果得到回應中有資訊告訴瀏覽器可以快取此回應。那麼瀏覽器就把這個回應伺服器到瀏覽器伺服器中
#如果後續再發出請求時,瀏覽器會先判斷伺服器是否過期。如果沒有過期,瀏覽器壓根就不會向伺服器發出請求,而是直接從伺服器中提取結果。
例如:訪問考古金網站
從##Size可以看出,
磁碟快取是從硬碟中提取的儲存資訊。
例如:選擇上面圖中的其中一份快取文件,copy
請求url
在curl
中展示
首先加-I
取得原始要求,請查看etag
或last-modified
頭部。
因為瀏覽器快取過期之後,請求就會帶著這些頭部一起傳送給伺服器,讓伺服器判斷是否還能用。
針對etag
頭部,加上一個if-none-match
頭部帶上etag
的值詢問伺服器。當然也可以針對last-modified
頭部,加上一個if-modified-since
頭部詢問。
回傳的是304。304的好處就是不攜帶包體,也就是說content-length
為0,這樣就節省了大量的頻寬。
共享快取
瀏覽器快取是私有緩存,只提供給一個使用者使用的。
而共享快取是放在伺服器上的,可以提供多個使用者使用。比如說某個比較熱點的視訊等熱點資源就會放在代理代理伺服器的快取中,以減低來源伺服器的壓力,提升網路效率。
怎麼分辨這個資源是代理伺服器的快取還是來源伺服器發送的呢?
仍然使用掘金的例子
從圖中看出這個請求的Response Headers
中的age
頭部,單位是秒。
說明這個快取是共享快取返回的,age
說明了它在共享快取存在的時間,圖中是327784,也就是在共享快取中存在了327784秒。
共享快取也有過期的時候,下面來看看共享快取的工作原理。
如圖:
1、當client1
發起請求時,Cache
也就是代理伺服器(共享快取),轉送這條請求給來源伺服器。來源伺服器回傳回應,並在Cache-Control
頭部中設定可以快取100秒。接著在Cache
中就會開啟一個計時器Age
,將回應帶上Age:0
頭部回傳給client1
。
2、過了10秒後,client2
發送相同的請求,Cache
中的快取還沒過期,就帶著Age:10
頭部傳回快取中的回應給client2
。
3、過了100秒後,client3
發送同樣的請求,這時Cache
中的快取已經過期了,就像前面說到那樣用條件請求頭部If-None-Match
帶上快取的指紋發給來源伺服器。當來源服務認為此快取還能用,就回傳304狀態碼給Cache
。 Cache
就重新計時,從快取中找出回應帶上Age:0
頭部回傳給Client3
。
快取機制
HTTP
協定中存在相關的快取機制,在API
中也可以直接使用這些機制來管理快取。 HTTP
的快取機制在RFC7234
中進行了詳細的定義,分為:過期模型(Expiration Model)
和驗證模型(Validation Model)
兩類
- 過期模型是指預先決定回應資料的保存期限,當到達期限後就會再次存取伺服器端來重新取得所需的資料
- 驗證模型是指會輪詢目前保存的快取資料是否為最新數據,並且只在伺服器端進行資料更新時,才會重新取得資料。
在HTTP
中,快取處於可用的狀態時稱為fresh
(新鮮)狀態,而處於不可用的狀態時稱為stale
(不新鮮)狀態。
過期模型
過期模型可以透過伺服器的回應訊息包含何時過期的資訊來實現。 HTTP1.1
中定義了兩種實作方法:一個方法是用Cache-Control
來回應訊息首部,另一個方法就是用Expires
回應訊息首部。
// 1 Expires: Fri, 01 Oct 2020 00:00:00 GMT // 2 Cache-Control: max-age=3600复制代码
Expires
首部從HTTP1.0
就已經存在了,它是用絕對時間來表示到期,並使用RFC1123
中定義的時間格式來描述。 Cache-Control
則是HTTP1.1
中定義的表示從目前時間開始所經過的秒數。
这两个首部该使用哪个,则是由返回的数据的性质决定的。对于一开始就知道在某个特定的日期会更新的数据,比如天气预报这种每天在相同时间进行更新的数据,可以使用Expires
首部来指定执行更新操作的时间。对于今后不会使用更新的数据或静态数据等,可以通过指定一个未来非常遥远的日期,使得获取的缓存数据始终保存下去。但根据HTTP1.1
的规定,不允许设置超过1年以上的时间,因此未来非常遥远的时间最多也只能是1年后的日期了。
Expires: Fri, 01 Oct 2021 00:00:00 GMT复制代码
而对于不是定期更新,但如果更新频率在某种程度上是一定的,或者虽然更新频率不低但不希望频繁访问服务器端,对于这种情况可以使用Cache-Control
首部。
如果Expires
和Cache-Control
首部同时使用时,Cache-Control
首部优先判断。
上面Cache-Control
示例中使用到了max-age
关键字,max-age
计算会使用名为Date
的首部。该首部用来显示服务器端生成响应信息的时间信息。从该时间开始计算,当经过的时间超过max-age
值时,就可以认为缓存已到期。
Date: Expires: Fri, 30 Sep 2020 00:00:00 GMT复制代码
Date
首部表示服务器端生成响应信息的时间信息。根据HTTP
协议的规定,除了几个特殊的情况之外,所有的HTTP
消息都要加上Date
首部。
Date
首部的时间信息必须使用名为HTTP
时间的格式来描述。在计算缓存时间时,会用到该首部的时间信息,这时就可以使用Date
首部信息来完成时间的同步操作,做到即便客户端擅自修改日期等配置信息。
验证模型
与到期模型只根据所接收的响应信息来决定缓存的保存时间相对,验证模型采用了询问服务器的方式来判断当前时间所保存的缓存是否有效。
验证模型在检查缓存的过程中会不时地去访问网络。在执行验证模型时,需要应用程序服务器支持附带条件地请求。附带条件地请求是指前端向服务器端发送地“如果现在保存地信息有更新,请给我更新后地信息”。在整个处理的过程中,前端会发送同“过去某个时间点所获得的数据”有关的信息,随后只有在服务器端的数据发生更新时,服务器端才会返回更新的数据,不然就只会返回304(Not Modified)
状态码来告知前端当前服务器端没有更新的数据。
要进行附带条件的请求,就必须向服务器端传达“前端当前保存的信息的状态”,为此需要用到最后更新日期或实体标签(Entity Tag)
作为指标。顾名思义,最后更新日期表示当前数据最后一次更新的日期:而实体标签则是表示某个特定资源版本的标识符,十一串表示指纹印(Finger Print)
的字符串。例如响应数据的MD5散列值等,整个字符串会随着消息内容的变化而变化。这些信息会在服务器端生成,并被包含在响应信息的首部发送给前端,前端会将其缓存一同保存下来,用于附带条件的请求。
最后更新日期和实体标签会被分别填充到Last-Modified
和ETag
响应消息首部返回给前端
Last-Modified: Fri, 01 Oct 2021 00:00:00 GMT ETag: 'ff568sdf4545687fadf4dsa545e4f5s4f5se45'复制代码
前端使用最后更新日期执行附带条件的请求时,会用到Modified-Since
首部。在使用实体标签时,会用到If-None-Match
首部
GET /v1/user/1 If-Modified-Since: Fri, 01 Oct 2021 00:00:00 GMT GET /v1/user/1 If-None-Match: 'ff568sdf4545687fadf4dsa545e4f5s4f5se45'复制代码
服务器端会检查前端发送过来的信息和当前信息,如果没有发生更新则返回304状态码。如果有更新,则会同应答普通请求一样,在返回200状态码的同时将更新内容一并返回给前端,这时也会带上新的最后更新日期和实体标签。当服务器返回304状态码时,响应消息为空,从而节约了传输的数据量。
在HTTP
协议中,ETag
有强验证与弱验证两个概念。
执行强验证的
ETag
ETag: 'ffsd5f46s12wef13we2f13dsd21fsd32f1'
执行弱验证的
ETag
ETag: W/'ffsd5f46s12wef13we2f13dsd21fsd32f1'
强验证是指服务器端同客户端的数据不能有一个字节的差别,必须完全一样;而弱验证是指即使数据不完全一样,只要从资源意义的角度来看没有发生变化,就可以视为相同的数据。例如广告信息,虽然每次访问时这些广告的内容都会有所改变,但它们依然是相同的资源,这种情况下便可以使用弱验证。
啟發式過期
HTTP1.1
裡提到了當伺服器端沒有給出明確的過期時間時,客戶端可以決定大約需要將快取資料保存多久。這時客戶端就要根據伺服器端的更新頻率、具體狀況等信息,自行決定快取的過期時間,這個方法稱為啟發式過期。
例如前端透過觀察Last-Modified
,如果發現最後一次更新是在1年前,那就意味著再將快取資料保存一段時間也不會有什麼問題;如果發現到目前為止造訪的結果是1天只有1次更新,那就意味著將快取保存半天的時間或許可行。像這樣,前端能透過獨立判斷來減少造訪次數。
雖然API
是否允許使用啟發式過期的方法取決於API的特性,但由於服務端對快取的更新和控制理解最為深刻,因此伺服器端透過Cache -Control
、Expires
等準確無誤地向前端傳回「儲存快取資料多久」的訊息,對於互動雙方而言都是比較理想的做法。但如果不傳回,伺服器端就需要透過Last-Modified
等首部資訊來告知前端
#使用Vary
指定快取單位
在實施快取時可能還需要同時指定Vary
首部。在實作快取時,Vary
用來指定除URI
外使用哪個請求首部項目來決定唯一的資料。使用Vary
是因為即使URI
相同,所獲得的資料有時也會因請求首部內容的不同而改變。只有vary
頭部指定的頭部必須與請求中的頭部相符才能使用快取。
vary
的定義:
- "*": 表示一定符合失敗
- 1個或多個
field- name
:指定的頭部必須與請求中的頭部相符才能使用快取
如圖所示:
1、 當Client1
攜帶Accept-Encoding:*
頭部的GET
要求傳送給server
。 server
回傳的是gzip
編碼的回應,以及vary:Content-Encoding
頭部,表示著編碼方式一樣的時候才能使用快取。
2、當Client2
攜帶Accept-Encoding:br
頭部的GET
請求發送給server
,這時請求的是br
編碼。所以Cache
不能使用緩存,因為不符合vary
的中的值,只能轉送請求給來源伺服器server
。
3、當Client3
攜帶Accept-Encoding:br
頭部的GET
請求發送給server
,這時Cache
有br
編碼的緩存,能匹配vary
頭部的值,所以能使用緩存返回。
一般而言,Vary
首部用於HTTP經由代理伺服器進行互動的場景,特別是當代理伺服器擁有快取功能時。但有時服務端無法得知前端的存取是否經由代理伺服器,這種情況下就需要用到伺服器驅動的內容協商機制,Vary
首部也就成了必選項。
Cache-Control
Cache-Control
頭部取值範圍非常複雜。
Cache-Control
的定義是:
- 必選的
token
值 - 可選的「= ”,加上引號的值或1個或多個十進制的數字也就是指定的秒數
Cache-Control
既可以在請求中使用,也可以在響應是使用。而且相同的值在請求和回應中的意義是不一樣的。
Cache-Control
值有三種用法:
- 1、直接使用
token
- 2、
token
值'=' 十進位數字 - 3、
token
值'=' 對應的頭/ 直接使用token
值
- max-age@2: 告訴伺服器,客戶端不會接收
Age
超出max-age
秒的快取 ##max-stale@ 2: 告訴伺服器,即使快取不再新鮮,但過期秒數沒有超過 - max-stale
時,客戶端仍打算使用。若
max-stale後面沒有值,表示無論過期多久,客戶端都可使用。
min-fresh@2: 告訴伺服器, - Age
至少經過
min-fresh秒後快取才可使用
no-cache@1 : 告訴伺服器,不能直接使用已有快取作為回應返回,除非帶著快取條件到上游伺服器得到304狀態碼才可使用現有快取。 - no-store@1: 告訴各代理伺服器,不要對該要求的回應快取
- no-transform@1: 告訴代理伺服器不要修改訊息包體的內容
- only-if-cached@1: 告訴伺服器只能回傳快取的回應,否則若沒有快取則回傳504錯誤碼
Cache-Control的取值及其意義:
- max-age@2: 告訴客戶端快取
- Age
超出
max-age秒後則快取過期
s-maxage@2:與 - max-age
類似,但僅針對共享緩存,且優先權高於
max-age與
expires must-revaildate@1: 告訴客戶端一旦快取過期,必須向伺服器驗證後才可使用 - proxy-revalidate@1: 與
- must-revaildate
類似,但它只對代理伺服器的共享快取有效
no-cache@3: 1.告訴客戶端不能直接使用快取的回應,使用前必須在來源伺服器驗證得到304返回碼。 2.如果 - no-cache
後指定頭部,則若客戶端的後續請求及回應中不含有這些頭部則可直接使用快取
no-store@1: 告訴所有下游伺服器但不能對回應進行快取 - no-transform: 告訴代理伺服器不能修改訊息包體的內容
- public@1: 表示無論私有快取或共享緩存,皆可將該回應快取
- private@3: 1、表示該回應不能被代理伺服器作用共享快取使用。 2.若
- priate
後面指定頭部,則告訴代理伺服器不能快取指定的頭部,可以快取其他頭部
##相關免費學習推薦:javascript(影片)#
以上是一文搞定'緩存”的詳細內容。更多資訊請關注PHP中文網其他相關文章!

JavaScript字符串替換方法詳解及常見問題解答 本文將探討兩種在JavaScript中替換字符串字符的方法:在JavaScript代碼內部替換和在網頁HTML內部替換。 在JavaScript代碼內部替換字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 該方法僅替換第一個匹配項。要替換所有匹配項,需使用正則表達式並添加全局標誌g: str = str.replace(/fi

本教程向您展示瞭如何將自定義的Google搜索API集成到您的博客或網站中,提供了比標準WordPress主題搜索功能更精緻的搜索體驗。 令人驚訝的是簡單!您將能夠將搜索限制為Y

本文系列在2017年中期進行了最新信息和新示例。 在此JSON示例中,我們將研究如何使用JSON格式將簡單值存儲在文件中。 使用鍵值對符號,我們可以存儲任何類型的

因此,在這裡,您準備好了解所有稱為Ajax的東西。但是,到底是什麼? AJAX一詞是指用於創建動態,交互式Web內容的一系列寬鬆的技術。 Ajax一詞,最初由Jesse J創造

利用輕鬆的網頁佈局:8 ESTISSEL插件jQuery大大簡化了網頁佈局。 本文重點介紹了簡化該過程的八個功能強大的JQuery插件,對於手動網站創建特別有用

核心要點 JavaScript 中的 this 通常指代“擁有”該方法的對象,但具體取決於函數的調用方式。 沒有當前對象時,this 指代全局對象。在 Web 瀏覽器中,它由 window 表示。 調用函數時,this 保持全局對象;但調用對象構造函數或其任何方法時,this 指代對象的實例。 可以使用 call()、apply() 和 bind() 等方法更改 this 的上下文。這些方法使用給定的 this 值和參數調用函數。 JavaScript 是一門優秀的編程語言。幾年前,這句話可

jQuery是一個很棒的JavaScript框架。但是,與任何圖書館一樣,有時有必要在引擎蓋下發現發生了什麼。也許是因為您正在追踪一個錯誤,或者只是對jQuery如何實現特定UI感到好奇

該帖子編寫了有用的作弊表,參考指南,快速食譜以及用於Android,BlackBerry和iPhone應用程序開發的代碼片段。 沒有開發人員應該沒有他們! 觸摸手勢參考指南(PDF)是Desig的寶貴資源


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

WebStorm Mac版
好用的JavaScript開發工具

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

禪工作室 13.0.1
強大的PHP整合開發環境