通过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设置不同的缓存策略,能够更有针对性地进行主动缓存。

        相关文章
        相关标签/搜索
        香港马会免费资枓大全香港开奖结果_香港马会2019开奖结果_2019 最快开奖记录结果_小鱼儿玄机2站开奖 开奖结果 茶陵县| 繁峙县| 安庆市| 汽车| 剑河县| 柘城县| SHOW| 凌源市| 济宁市| 当涂县| 冷水江市| 读书| 囊谦县| 南郑县| 宜君县| 嘉荫县| 墨竹工卡县| 府谷县| 宁国市| 新和县| 轮台县| 江西省| 武宣县| 武胜县| 增城市| 建瓯市| 外汇| 正镶白旗| 东源县| 萝北县| 英超| 丰顺县| 辰溪县| 房山区| 资讯| 读书| 温泉县| 绍兴市| 仁化县| 聂拉木县| 盘山县| 新化县| 巴南区| 长沙市| 衡水市| 亚东县| 息烽县| 和田市| 神农架林区| 八宿县| 神木县| 东兰县| 水城县| 双桥区| 阳山县| 武夷山市| 锡林郭勒盟| 汉沽区| 北流市| 容城县| 汕头市| 堆龙德庆县| 盱眙县| 越西县| 天镇县| 观塘区| 洛浦县| 福安市| 阜南县| 昆山市| 遵义县| 屏东县| 葫芦岛市| 新兴县| 叙永县| 孝感市| 阿拉尔市| 长乐市| 津市市| 镇原县| 枣强县| 容城县| 阿勒泰市| 景泰县| 永定县| 墨脱县| 宣威市| 盐山县| 绥中县| 横峰县| 叙永县| 峨山| 铁岭市| 丹巴县| 游戏| 冕宁县| 陵川县| 新田县| 盘山县| 松滋市| 瓮安县| 红河县| 尉犁县| 托克逊县| 长汀县| 凤阳县| 辉南县| 凌海市| 越西县| 建德市| 大理市| 兴安盟| 乳山市| 新干县| 营口市| 平山县| 阜平县| 兰坪| 手游| 织金县| 廉江市| 平阳县| 甘德县| 永安市| 遵义县| 武清区| 高尔夫| 龙海市| 普兰店市| 海南省| 长汀县| 浮山县| 托里县| 天台县| 班戈县| 安远县| 若尔盖县| 无为县| 勐海县| 海宁市| 长葛市| 贵定县| 壶关县| 庆云县| 洮南市| 龙江县| 吉隆县| 龙门县| 金门县| 睢宁县| 雅安市| 板桥市| 杭锦后旗| 定西市| 天祝| 泰安市| 虹口区| 延庆县| 米脂县| 松溪县| 台北县| 莱阳市| 景宁| 南华县| 洛宁县| 澳门| 易门县| 石柱| 仙居县| 双流县| 琼海市| 山阳县| 武宣县| 柞水县| 诏安县| 澎湖县| 灵宝市| 深水埗区| 岢岚县| 颍上县| 嘉义县| 温宿县| 临西县| 和静县| 隆林| 辉县市| 化州市| 沂水县| 永修县| 屯门区| 泰州市| 边坝县| 白城市| 梅州市| 南溪县| 青阳县| 金山区| 湖口县| 天峨县| 宜都市| 多伦县| 万盛区| 威信县| 岳西县| 武定县| 静安区| 呼图壁县| 礼泉县| 嘉义县| 本溪市| 新泰市| 嘉黎县| 河北区| 吉木乃县| 南皮县| 吉木萨尔县| 龙里县| 许昌市| 安平县| 应城市| 兴仁县| 沙河市| 台安县| 襄城县| 景东| 博白县| 防城港市| 新巴尔虎右旗| 镇原县| 改则县| 沙洋县| 广德县| 伊通| 米脂县| 彩票| 汉阴县| 云林县| 泊头市| 嘉定区| 阿拉善右旗| 高要市| 茶陵县| 理塘县| 永泰县| 东辽县| 达拉特旗| 驻马店市| 鸡泽县| 武陟县| 阿勒泰市| 东港市| 四会市| 五家渠市| 虞城县| 筠连县| 宁明县| 拉孜县| 邵阳市| 伊川县| 绥滨县| 和政县| 开平市| 柯坪县| 尤溪县| 丽江市| 读书| 宜春市| 巩义市| 额济纳旗| 玉林市| 盐源县| 名山县| 横山县| 潜江市| 建昌县| 巴里| 榆中县| 驻马店市| 盐亭县| 岳普湖县| 合山市| 仲巴县| 石嘴山市| 马关县| 齐齐哈尔市| 临泉县| 本溪市| 陈巴尔虎旗| 盐城市| 昆明市| 黎川县| 渭源县| 封丘县| 湾仔区| 祁东县| 连云港市| 威海市| 黄冈市| 桑植县| 二连浩特市| 抚松县| 内丘县| 清镇市| 温州市| 南宫市| 祁东县| 河西区| 清远市| 东城区| 吴桥县| 南阳市| 安顺市| 万州区| 湖南省| 奎屯市| 汶川县| 讷河市| 武冈市| 行唐县| 临邑县| 内丘县| 许昌县| 贺兰县| 湖北省| 尼玛县| 关岭| 韶关市| 荔浦县| 綦江县| 南雄市| 崇仁县| 五常市| 沁水县| 吉木萨尔县| 江川县| 赣州市| 历史| 特克斯县| 香港| 讷河市| 莱西市| 炉霍县| 赤峰市| 含山县| 陕西省| 敦煌市| 信宜市| 五台县| 册亨县| 安乡县| 奈曼旗| 梧州市| 吕梁市| 怀化市| 成安县| 彭泽县| 凤阳县| 富阳市| 郴州市| 寿光市| 盐边县| 临沭县| 浮梁县| 泽普县| 璧山县| 偏关县| 滨州市| 塘沽区| 乐都县| 锡林郭勒盟| 小金县| 鄯善县| 渭源县| 斗六市| 金昌市| 平南县| 邳州市| 昌都县| 菏泽市| 青海省| 武宁县| 习水县| 孟村| 江口县| 北川| 昭通市| 北流市| 夹江县| 金堂县| 黄山市| 拜泉县| 宣武区| 自贡市| 涿鹿县| 册亨县| 尚志市| 咸宁市| 伽师县| 沁源县| 左权县| 广德县| 双桥区| 祁连县| 白城市| 东辽县| 壶关县| 越西县| 芜湖县| 杭锦后旗| 六枝特区| 通榆县| 霍城县| 繁昌县| 合山市| 长沙市| 京山县| 临高县| 石嘴山市| 石泉县| 成安县| 樟树市| 灵丘县| 天柱县| 金溪县| 泊头市| 许昌市| 温泉县| 吴江市| 安化县| 杂多县| 南涧| 宁城县| 宁安市| 百色市| 色达县| 辽宁省| 霍州市| 成都市| 永泰县| 错那县| 湘阴县| 运城市| 新昌县| 韩城市| 陈巴尔虎旗| 景泰县| 海林市| 海阳市| 远安县| 福清市| 镶黄旗| 太原市| 安国市| 叶城县| 普格县| 三河市| 监利县| 丰原市| 高州市| 扶风县| 宁陕县| 塔城市| 瓦房店市| 齐齐哈尔市| 望城县| 湖北省| 平舆县| 原平市| 宜兰县| 宁远县| 突泉县| 淮滨县| 石泉县| 公主岭市| 万安县| 马边| 昌邑市| 福泉市| 宁陕县| 贺兰县| 新晃| 衡山县| 阿拉善右旗| 兴和县| 琼结县| 柳江县| 奉化市| 纳雍县| 台安县| 沁阳市| 平昌县| 若尔盖县| 贵阳市| 澎湖县| 曲周县| 嘉峪关市| 斗六市| 甘肃省| 罗平县| 莱芜市| 宁河县| 昌都县| 奉化市| 清涧县| 丹阳市| 九寨沟县| 威信县| 石嘴山市| 怀安县| 宁化县| 青阳县| 敦化市| 克山县| 图们市| 林甸县| 新源县| 鹤峰县| 宜兰县| 宣汉县| 大石桥市| 犍为县| 高邑县| 延津县| 毕节市| 南康市| 乳山市| 岢岚县| 临夏市| 阿克苏市| 高青县| 通化县| 红原县| 淮北市| 岑巩县| 锡林郭勒盟| 阿拉尔市| 瑞昌市| 康马县| 囊谦县| 大厂| 维西| 鄂州市| 尚志市| 郎溪县| 齐齐哈尔市| 静乐县| 新闻| 湘西| 哈尔滨市| 晋宁县| 邢台县| 南乐县| 多伦县| 江北区| 基隆市| 临安市| 垣曲县| 德保县| 遵义市| 合山市| 宣城市| 商都县| 海兴县| 敖汉旗| 纳雍县| 淅川县| 安泽县| 大同县| 鲁甸县| 瑞金市| 龙口市| 涿鹿县| 潞西市| 遂川县| 安陆市| 喀喇| 若羌县| 民勤县| 甘德县| 台山市| 梨树县| 赫章县| 上虞市| 格尔木市| 秭归县| 泽州县| 那坡县| 友谊县| 郁南县| 吉木萨尔县| 济源市| 天等县| 理塘县| 黄梅县| 宁津县| 十堰市| 颍上县| 法库县| 内丘县| 曲松县| 平果县| 通河县| 河池市| 都兰县| 抚松县| 岗巴县| 霍山县| 华宁县| 中卫市| 定边县| 同仁县| 大厂| 大足县| 宁明县| 望谟县| http://wap.jx1870codev.fun http://3g.jx1870districtv.fun http://wap.jx1870dreazv.fun http://m.jx1870answerv.fun http://www.jx1870creazv.fun http://m.jx1870cancelv.fun http://3g.jx1870bottozv.fun http://m.jx1870blackv.fun http://3g.jx1870codev.fun http://www.jx1870displayv.fun http://m.jx1870branchv.fun http://jx1870advantagev.fun http://wap.jx1870casev.fun http://m.jx1870downloadv.fun http://jx1870associatev.fun http://m.jx1870catalogv.fun http://m.jx1870contrastv.fun http://3g.jx1870dishv.fun