<menu id="46sq2"></menu>
  • <input id="46sq2"><tt id="46sq2"></tt></input>
    <nav id="46sq2"></nav>
    <menu id="46sq2"></menu>

    通过HTTP Header控制缓存

    我们经常通过缓存技术来加快网站的访问速度,从而提升用户体验。HTTP协议中也规定了一些和缓存相关的Header,来允许浏览器或共享高速缓存缓存资源。这些Header包括:

    • Last-Modified 和 If-Modified-Since
    • ETag 和 If-None-Match
    • Expires
    • Cache-Control
      以上Header又可以分成两种类型:

    • 协商缓存:浏览器发送验证到服务器,由服务器决定是否从缓存中读取,如 1 和 2 。
    • 强缓存:浏览器验证缓存的有效性,然后决定是否从缓存中读取数据,如 3 和 4 。
      本文将会分别介绍这四种配置的作用以及可能产生的影响。

    1、Last-Modified 和 If-Modified-Since
    Last-Modified:服务器在响应请求时,告知浏览器资源的最后修改时间。

    If-Modified-Since:浏览器再次发送请求时,会通过此Header通知服务器在上次请求时所得到的资源最后修改时间。服务器会将If-Modified-Since与被请求资源的最后修改时间进行比对。若资源的最后修改时间晚于If-Modified-Since,表示资源已被改动,则响最新的资源,返回200状态码;若资源的最后修改时间早于或等于If-Modified-Since,表示浏览器端的资源已经是最新版本,响应304状态码,通知浏览器继续使用缓存中的资源。

    2、ETag 和 If-None-Match
    ETag:服务器分配给资源的唯一标识符,资源被修改后,ETag也会随之发生变化。

    If-None-Match:浏览器再次发送请求时,会通过此Header通知服务器已缓存资源的ETag。服务器会将If-None-Match与被请求资源的最新ETag进行比对。若不相同,表示资源已被改动,则响应最新的资源,返回200状态码;若值相同,则直接响应304状态码,通知浏览器继续使用缓存中的资源。

    3、Expires
    服务器可以通过此Header向浏览器传递一个具体的时间(格林威治格式,例如:Thu, 19 Jul 2018 07:43:05 GMT) ,来明确地宣告资源的有效期。在资源过期之前,浏览器不再发送请求,而是直接从缓存中读取数据。只有当资源过期之后,浏览器才会再次向服务器请求该资源。

    4、Cache-Control
    服务器使用此Header来向客户端建议缓存策略,它有一下几个可选值:

    max-age=秒:告知浏览器缓存的有效时长,在该时间内浏览器将直接从缓存中读取数据。

    s-maxage=秒:作用同max-age,但是只对共享高速缓存(如CDN)有效,对浏览器无效。

    no-cache:告知浏览器不要直接使用缓存,而是必须向服务器发送请求。

    no-store:告知浏览器不要缓存本次请求和响应的任何信息。

    public:宣告任何缓存媒介都可以缓存该响应。

    private:宣告该响应只允许个体客户端(如浏览器)去缓存,而不允许共享高速缓存(如CDN)去缓存。

    在上面的介绍中我们了解到浏览器会根据max-age设置的时间进行缓存。而通过研究发现CDN也会识别源站响应头中Cache-Control属性,根据max-age设置的时间进行缓存,但是,如果源站同时设置了s-maxage和max-age,那么CDN会优先采用s-maxage。

    下面通过图例来展示一下这些可选值的效果。

    首先了解一下浏览器是怎样根据max-age进行缓存的:
    通过HTTP Header控制缓存

    从上图不难发现,服务器在Header中返回了Cache-Control: max-age=100后,浏览器成功缓存100秒,该时间段内的请求都从直接以本地缓存来响应。

    那么,服务器在Header中返回Cache-Control:s-maxage=100时,又会对浏览器产生什么样的影响呢?

    通过HTTP Header控制缓存

    如上图所示,浏览器没有采取任何缓存策略,这是因为s-maxage面向的是共享高速缓。

    上面这两个例子很容易理解,在现实世界中,为了加快网站响应速度,我们可能会在浏览器和服务器之间引入CDN服务。浏览器的请求会先到达CDN,然后CDN判断是从缓存中读取数据还是回源到服务器。接下来,让我们看看max-age和s-maxage会对CDN的缓存策略带来哪些影响。
    通过HTTP Header控制缓存

    可以看出CDN也会利用max-age来缓存,所以在100秒内强制刷新浏览器时,CDN会直接用缓存来响应。
    如果服务器使用了s-maxage又会如何呢?
    通过HTTP Header控制缓存

    不难发现CDN对max-age和s-maxage采取了同样的缓存策略,但浏览器并不会根据s-maxage来进行缓存。

    CDN供应商的特殊规则

    我们分别测试了阿里云和腾讯云的CDN对Cache-Control的支持情况,发现他们都有一些独特的规则。

    阿里云CDN可以在控制台里设置Cache-Control,该设置会覆盖源服务器的Cache-Control。

    腾讯云CDN虽然没有再控制台提供覆盖Cache-Control的功能,但其规则却一点也不简单,在使用的时候一定要特别注意:

    • 服务器和CDN均不对缓存进行配置时,CDN会采用默认的缓存机制(静态文件缓存30天,动态请求不缓存);
    • CDN配置缓存机制(但并未开启高级缓存配置)且服务器设置Cache-Control: s-maxage=200,max-age=100时,CDN会按照其控制台设置的规则进行缓存,浏览器则按照max-age进行缓存;
    • 服务器不设置Cache-Control时,CDN会自动在响应的Header中添加Cache-Control: max-age=600,这就会让浏览器将该资源缓存600秒;
    • 服务器设置为禁用缓存时,CDN和浏览器均不进行缓存;
    • 服务器设置Cache-Control: s-maxage=200,max-age=100并开启CDN的高级缓存配置时,CDN会从s-maxage和控制台中设置的缓存时间中选择最小值来作为缓存时间,而浏览器则始终使用max-age;
    • 服务器设置Cache-Control:max-age=100并开启CDN的高级缓存配置时,CDN会从max-age和控制台中设置的缓存时间中选择最小值来作为缓存时间,不影响浏览器的缓存策略。

    组合使用
    如果同时设置了这些Header,浏览器和高速共享缓存会按照下面的优先级进行缓存:
    Cache-Control > Expires > ETag > Last-Modified
    也就是说,Cache-Control不仅是强缓存,而且拥有最高的优先级,我们可以为不经常发生变化的资源应用该Header来提升响应时间。

    在Ada中使用缓存
    Ada提供了UI脚手架和API脚手架,这两类脚手架的服务器端入口文件分别为index.server.js和index.js,我们只需要在入口文件的请求处理函数中为响应添加适当的Header,即可通知客户端进行响应的缓存,比如:

    • // 设置CDN缓存300秒,浏览器缓存200秒
    • ctx.response.headers.set(‘Cache-Control‘, public,s-maxage=300,max-age=200)
    • 在为请求添加缓存Header之前,应该先为其制定适当的缓存策略,需要考虑该URL是否适合缓存(数据是否特定于用户)以及需要缓存的时长等等。

    总结通过使用这些HTTP Header,我们可以主动影响浏览器甚至CDN的缓存策略,从而减少请求数量,提升网页性能,减轻服务器压力。Ada的灵活机制能让我们为不同的URL设置不同的缓存策略,能够更有针对性地进行主动缓存。

    相关文章
    相关标签/搜索
    管家婆精选四消期期准 m.w0zgh930.icu 天峨县| 都安| 安平县| 定兴县| 东兰县| 景谷| 辰溪县| 南宫市| 新巴尔虎左旗| 拉萨市| 常德市| 望奎县| 桃源县| 当阳市| 汝阳县| 名山县| 固镇县| 屏边| 泊头市| 白玉县| 宜春市| 彭水| 阳山县| 安泽县| 敦煌市| 贺兰县| 天津市| 梨树县| 文成县| 砚山县| 潜江市| 肇东市| 伽师县| 邹平县| 宁城县| 田林县| 烟台市| 乌苏市| 杭州市| 忻城县| 阳朔县| 任丘市| 汉沽区| 都江堰市| 大洼县| 和田县| 仁寿县| 鄱阳县| 武定县| 巴彦县| 井研县| 丹阳市| 旺苍县| 景洪市| 深州市| 锡林郭勒盟| 长汀县| 突泉县| 察隅县| 沐川县| 鄂尔多斯市| 神池县| 沙坪坝区| 阳新县| 乌鲁木齐县| 邵阳县| 项城市| 聂荣县| 江孜县| 冷水江市| 陈巴尔虎旗| 绥阳县| 阳谷县| 睢宁县| 桃园县| 安义县| 呈贡县| 齐齐哈尔市| 海晏县| 姜堰市| 河池市| 盐源县| 蒲城县| 临洮县| 泾源县| 会宁县| 泗阳县| 宁晋县| 彝良县| 乐安县| 天祝| 丁青县| 鱼台县| 阿尔山市| 望都县| 抚松县| 华蓥市| 和田县| 和静县| 鸡西市| 长子县| 舟曲县| 姚安县| 娄底市| 霍山县| 育儿| 三都| 沙河市| 云浮市| 无锡市| 琼结县| 安丘市| 正宁县| 察哈| 长乐市| 蓬莱市| 梅河口市| 扎囊县| 全州县| 炎陵县| 长宁县| 即墨市| 喀喇沁旗| 烟台市| 康定县| 东乌| 泸西县| 西和县| 临清市| 南雄市| 本溪| 岱山县| 宝清县| 武邑县| 泾川县| 新乡县| 麦盖提县| 浠水县| 栾城县| 依安县| 当雄县| 铜山县| 南雄市| 石家庄市| 潞城市| 启东市| 阳朔县| 翼城县| 徐汇区| 宜兴市| 南投县| 乌鲁木齐市| 衡水市| 江口县| 蚌埠市| 绥芬河市| 商南县| 安乡县| 乡宁县| 长兴县| 平远县| 贵阳市| 华蓥市| 宜章县| 霍山县| 平塘县| 九龙坡区| 卓资县| 资讯| 鲁甸县| 湘潭市| 正安县| 大港区| 浠水县| 壤塘县| 青海省| 天气| 广东省| 姜堰市| 汤原县| 新巴尔虎右旗| 焉耆| 威宁| 武川县| 花莲市| 巴青县| 凤阳县| 广灵县| 河池市| 文水县| 独山县| 西藏| 酒泉市| 大庆市| 佳木斯市| 石家庄市| 久治县| 长兴县| 黑山县| 大城县| 靖远县| 内乡县| 嫩江县| 江安县| 怀来县| 平山县| 湖南省| 珠海市| 陆川县| 卫辉市| 延庆县| 镇原县| 仁怀市| 沂水县| 阿克| 天镇县| 慈利县| 昌黎县| 漯河市| 建水县| 青冈县| 德安县| 嵩明县| 洛扎县| 龙州县| 洪江市| 莒南县| 怀宁县| 泰宁县| 江源县| 庆阳市| 平果县| 鹤岗市| 青神县| 康平县| 永福县| 青河县| 壶关县| 文成县| 荥阳市| 金门县| 利辛县| 徐州市| 通化县| 山阴县| 大化| 克什克腾旗| 建阳市| 东乡族自治县| 洛隆县| 福州市| 金平| 拉萨市| 绥滨县| 古蔺县| 天祝| 会昌县| 钟山县| 龙山县| 京山县| 绿春县| 延长县| 新化县| 沙河市| 自治县| 五指山市| 庆元县| 嘉黎县| 伊春市| 墨竹工卡县| 栾川县| 宣武区| 涟水县| 田东县| 清远市| 福清市| 泌阳县| 宜城市| 清流县| 高淳县| 岚皋县| 驻马店市| 金秀| 顺平县| 凤山县| 富宁县| 内丘县| 南陵县| 綦江县| 彰化县| 河西区| 吉木萨尔县| 南皮县| 棋牌| 阳江市| 兴安盟| 凭祥市| 登封市| 呼伦贝尔市| 临夏市| 南丰县| 页游| 白朗县| 孙吴县| 陆丰市| 广水市| 莱西市| 百色市| 奉节县| 新乡市| 大英县| 永福县| 扬中市| 五台县| 洪雅县| 江陵县| 杭锦后旗| 镇远县| 吕梁市| 泰顺县| 衡东县| 南漳县| 三门县| 开江县| 平阳县| 蒙自县| 华亭县| 寿光市| 唐河县| 霞浦县| 深圳市| 万载县| 汉沽区| 牙克石市| 威海市| 苍南县| 盐源县| 通榆县| 博爱县| 广安市| 林芝县| 临潭县| 栾城县| 普陀区| 湖口县| 龙游县| 沛县| 奇台县| 天等县| 平潭县| 阜新| 南阳市| 阿合奇县| 嘉禾县| 北川| 彩票| 武邑县| 灌南县| 南通市| 扶绥县| 玉溪市| 呼图壁县| 香港| 五指山市| 隆安县| 益阳市| 砀山县| 彭阳县| 潜江市| 宣化县| 光山县| 尖扎县| 霍林郭勒市| 三原县| 灵寿县| 徐州市| 顺昌县| 台州市| 海盐县| 调兵山市| 和龙市| 讷河市| 秀山| 贺州市| 彭泽县| 原平市| 泾源县| 三明市| 绥德县| 洪泽县| 三门峡市| 邻水| 临桂县| 安宁市| 华亭县| 拉萨市| 叶城县| 塘沽区| 南投县| 丹巴县| 鄱阳县| 吉林市| 山阳县| 临朐县| 富阳市| 高台县| 岢岚县| 长汀县| 华阴市| 靖宇县| 柘城县| 淳化县| 普兰县| 昭苏县| 房产| 康马县| 蓝山县| 上蔡县| 汤原县| 杂多县| 佛山市| 呼伦贝尔市| 长治县| 昆明市| 紫金县| 乐亭县| 陆河县| 轮台县| 武宁县| 焦作市| 海南省| 峡江县| 桦甸市| 东方市| 晴隆县| 定安县| 墨竹工卡县| 长阳| 拉萨市| 佛坪县| 菏泽市| 北京市| 方正县| 华坪县| 九台市| 吉首市| 都江堰市| 锡林郭勒盟| 陆川县| 开远市| 琼结县| 南江县| 绩溪县| 平泉县| 石家庄市| 葫芦岛市| 衡水市| 岐山县| 九台市| 清水县| 河南省| 朝阳区| 博湖县| 太湖县| 汉源县| 承德市| 牡丹江市| 津市市| 长海县| 宁阳县| 淮南市| 蒙山县| 宜都市| 夏邑县| 太仆寺旗| 读书| 湘乡市| 沛县| 乐都县| 竹溪县| 固镇县| 梁河县| 杭锦后旗| 安阳市| 澄城县| 泽州县| 上杭县| 常德市| 韩城市| 金昌市| 卢龙县| 清涧县| 玉林市| 安徽省| 叶城县| 全州县| 江山市| 台南县| 远安县| 迁西县| 原阳县| 红河县| 崇礼县| 漳州市| 南丰县| 全州县| 衡南县| 建始县| 蓝山县| 扬中市| 石楼县| 紫阳县| 巴东县| 陈巴尔虎旗| 花莲县| 兰考县| 永昌县| 无为县| 凤凰县| 博野县| 分宜县| 北海市| 岚皋县| 双辽市| 尚志市| 泰顺县| 林口县| 通河县| 交城县| 张掖市| 雅安市| 昌乐县| 颍上县| 苗栗县| 自治县| 阜宁县| 水城县| 张家口市| 新兴县| 大英县| 永德县| 甘泉县| 鄯善县| 元氏县| 黄大仙区| 长白| 会东县| 贵州省| 荣昌县| 巴南区| 和林格尔县| 延吉市| 日土县| 曲阜市| 鹿泉市| 南丹县| 红桥区| 厦门市| 扶沟县| 永平县| 宣化县| 平度市| 万州区| 马关县| 道真| 鹤庆县| 余干县| 铁力市| 新竹市| 扶绥县| 太仓市| 云林县| 凤凰县| 彭阳县| 太湖县| 炉霍县| 万全县| 石城县| 平原县| 金堂县| 昭觉县| 临洮县| 松潘县| 衡东县| 蕉岭县| 获嘉县| 桐乡市| 城市| 会宁县| 边坝县| 肥城市| 道真| 锦州市| 古蔺县| 怀仁县| 海阳市| 赫章县| 历史| 鄂伦春自治旗| 绥江县| 青神县| 新蔡县| 廉江市| 龙州县| 会东县| 加查县| 正阳县| 石楼县| 惠来县| 苍南县| 古交市| 安岳县| 明水县| 晴隆县| 朔州市| http://qavbeg.fit http://www.jwhmaq.fit http://m.hpmzbp.fit http://ojxvrfit http://www.wvoarp.fit http://wap.boqwhy.fit http://www.dmwgxf.fit http://olruqg.fit http://www.hjdyni.fit http://www.weepqx.fit http://m.ighbxt.fit http://www.ykthio.fit http://m.ztzkqa.fit http://www.wozfox.fit http://m.ocetuv.fit http://m.jokyle.fit http://m.ymsmjy.fit http://www.dcokok.fit