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

    相关文章
    相关标签/搜索
    九龙心水175252马资料六合彩开奖结果493333王中王免费中特2020最快开奖历史记录本港台开奖现场直播今天开奖结果 化德县| 资讯| 彰化市| 长兴县| 黑龙江省| 临沧市| 施甸县| 新绛县| 开平市| 湘潭市| 万州区| 全椒县| 高碑店市| 庆云县| 霍邱县| 新巴尔虎左旗| 湘乡市| 木兰县| 岳池县| 永和县| 邵阳市| 聂荣县| 静安区| 万全县| 手机| 肇州县| 崇文区| 西青区| 监利县| 建德市| 桃江县| 台北市| 缙云县| 巫山县| 阿拉善右旗| 崇左市| 吉隆县| 雷山县| 曲水县| 沙洋县| 牡丹江市| 安徽省| 连云港市| 新建县| 麻栗坡县| 京山县| 搜索| 清远市| 措勤县| 塘沽区| 永兴县| 万山特区| 枞阳县| 沾化县| 温州市| 德惠市| 衡东县| 普兰店市| 文成县| 顺义区| 永顺县| 太湖县| 普兰店市| 朝阳县| 灵宝市| 商南县| 五河县| 保德县| 三都| 铁岭县| 黔南| 光山县| 金坛市| 临潭县| 荆门市| 东乌| 贵南县| 定远县| 普格县| 宽甸| 卢氏县| 桂林市| 和田市| 海城市| 乐平市| 肇庆市| 寿光市| 和龙市| 新河县| 冕宁县| 汝南县| 克拉玛依市| 乌什县| 万荣县| 明光市| 许昌市| 封丘县| 罗平县| 大同市| 林口县| 博野县| 叶城县| 吐鲁番市| 七台河市| 康平县| 平昌县| 石家庄市| 寻甸| 琼海市| 新竹市| 兴化市| 浦东新区| 伊宁县| 香港| 静乐县| 时尚| 怀安县| 成都市| 固始县| 江都市| 金昌市| 梧州市| 丹凤县| 方城县| 西吉县| 吉安县| 英山县| 巴东县| 苍梧县| 百色市| 渝中区| 普兰县| 正阳县| 鄂伦春自治旗| 紫金县| 崇礼县| 基隆市| 绥棱县| 怀宁县| 汉寿县| 石河子市| 临西县| 仙桃市| 广安市| 海晏县| 和顺县| 扶风县| 正安县| 孝昌县| 分宜县| 基隆市| 遂平县| 葫芦岛市| 南充市| 葫芦岛市| 唐海县| 友谊县| 开封市| 青龙| 临沂市| 监利县| 泌阳县| 浦城县| 襄垣县| 额敏县| 黄冈市| 镇赉县| 连南| 六枝特区| 揭阳市| 林芝县| 桐乡市| 广东省| 塔城市| 康平县| 云浮市| 铜川市| 景泰县| 寿阳县| 泽库县| 湖南省| 军事| 阿合奇县| 石楼县| 梁河县| 通河县| 大理市| 塘沽区| 滁州市| 丹寨县| 长阳| 吉安县| 蒲江县| 天等县| 吉安县| 绥棱县| 太原市| 五原县| 白朗县| 左权县| 沅陵县| 武安市| 灯塔市| 高州市| 泾阳县| 敦化市| 石门县| 赤水市| 延长县| 屏东县| 旺苍县| 南靖县| 都匀市| 万盛区| 宿州市| 留坝县| 永济市| 禄丰县| 古田县| 邢台县| 响水县| 浦江县| 海盐县| 响水县| 海门市| 大洼县| 西乌珠穆沁旗| 马边| 乡宁县| 长宁县| 建昌县| 邛崃市| 泗阳县| 收藏| 洪洞县| 石狮市| 内黄县| 罗定市| 株洲市| 普安县| 电白县| 昌吉市| 临潭县| 稻城县| 太康县| 定远县| 江孜县| 湖南省| 南宫市| 清丰县| 绵竹市| 蓬安县| 葵青区| 阜新| 钟祥市| 电白县| 柘城县| 宾阳县| 栾川县| 海原县| 夹江县| 巴林右旗| 通许县| 东丽区| 武冈市| 香河县| 广昌县| 南充市| 柳河县| 农安县| 汶川县| 商洛市| 桂平市| 芦山县| 长乐市| 定襄县| 喀什市| 龙川县| 鄱阳县| 水富县| 迁西县| 焦作市| 高陵县| 吴桥县| 拜泉县| 永宁县| 原平市| 阿拉善右旗| 乾安县| 晋城| 鹤山市| 秭归县| 南陵县| 皮山县| 四会市| 壶关县| 德兴市| 萨嘎县| 沽源县| 南陵县| 衡阳市| 乌审旗| 富阳市| 平原县| 海盐县| 长海县| 黑山县| 滨海县| 宁蒗| 武义县| 和龙市| 庄浪县| 湘潭县| 舟曲县| 松江区| 汕头市| 手机| 富宁县| 英超| 梁平县| 夹江县| 漳浦县| 泰安市| 滕州市| 南陵县| 乳源| 瑞安市| 涿鹿县| 玉林市| 汪清县| 堆龙德庆县| 武胜县| 宁安市| 怀化市| 兰州市| 阿拉尔市| 秦安县| 玉龙| 泰安市| 厦门市| 凌源市| 安国市| 绍兴市| 隆子县| 贵阳市| 高要市| 如东县| 贡觉县| 曲周县| 洱源县| 德令哈市| 德格县| 大关县| 英吉沙县| 广元市| 梁河县| 满城县| 靖宇县| 灌阳县| 五大连池市| 神木县| 绍兴市| 正宁县| 射阳县| 茶陵县| 宿松县| 双桥区| 伊金霍洛旗| 页游| 隆林| 宁河县| 麻城市| 青川县| 县级市| 叙永县| 济宁市| 灌阳县| 聂拉木县| 怀仁县| 库伦旗| 南江县| 米易县| 乐昌市| 石门县| 红安县| 霍林郭勒市| 武乡县| 共和县| 泰州市| 荥经县| 南漳县| 巴彦县| 合川市| 建水县| 乌什县| 南投市| 贵德县| 精河县| 岳池县| 罗定市| 响水县| 广宗县| 油尖旺区| 大竹县| 岚皋县| 登封市| 西吉县| 当阳市| 黄龙县| 霍林郭勒市| 湛江市| 平乐县| 延长县| 蒲江县| 兴宁市| 高州市| 衡阳县| 肇庆市| 巴南区| 周口市| 沛县| 酉阳| 卫辉市| 克拉玛依市| 灵山县| 潞城市| 洪湖市| 观塘区| 凤城市| 宝山区| 泰顺县| 云梦县| 隆回县| 大姚县| 贡嘎县| 弥渡县| 海南省| 濮阳县| 于都县| 河北省| 定结县| 大洼县| 吉木乃县| 枞阳县| 西畴县| 高平市| 永丰县| 井研县| 辉南县| 高青县| 武冈市| 汕尾市| 扶沟县| 松江区| 黄浦区| 大同县| 赤城县| 门头沟区| 定结县| 分宜县| 福贡县| 东阳市| 芷江| 西城区| 苏州市| 遂平县| 北碚区| 扶风县| 耿马| 石阡县| 湄潭县| 北碚区| 许昌市| 江源县| 富民县| 清新县| 德安县| 屯门区| 台前县| 永宁县| 祁门县| 弥渡县| 馆陶县| 固始县| 邛崃市| 台南市| 峨边| 会宁县| 廊坊市| 斗六市| 西贡区| 宝鸡市| 远安县| 磐石市| 山西省| 郁南县| 鸡西市| 华蓥市| 河津市| 洪雅县| 于都县| 陆良县| 华池县| 延边| 两当县| 平顺县| 阿荣旗| 历史| 弥勒县| 陇川县| 临高县| 柳州市| 丰县| 江安县| 江源县| 巫山县| 怀来县| 汝城县| 邢台县| 密山市| 吉安市| 延津县| 昌平区| 克山县| 崇明县| 如皋市| 定南县| 益阳市| 冕宁县| 凤冈县| 南阳市| 东宁县| 读书| 黎川县| 凤山市| 林州市| 济南市| 新余市| 元朗区| 永安市| 兴仁县| 敖汉旗| 鄂尔多斯市| 焦作市| 九江市| 通许县| 龙岩市| 兖州市| 井冈山市| 苏尼特左旗| 葵青区| 开封县| 宁晋县| 米泉市| 北流市| 枣强县| 邵阳县| 天峻县| 福建省| 台江县| 交口县| 丹江口市| 平塘县| 聂荣县| 五华县| 台山市| 婺源县| 阿城市| 神池县| 宜兰县| 临邑县| 承德市| 清远市| 崇文区| 博爱县| 共和县| 龙岩市| 榆中县| 阿尔山市| 永泰县| 沅陵县| 荥经县| 保德县| 侯马市| 沁水县| 富锦市| 连南| 溆浦县| 舒兰市| 喀喇| 太仓市| 丹凤县| 梅河口市| 卓尼县| 政和县| 荣昌县| 红桥区| 徐汇区| 兖州市| 台东市| 同江市| 台州市| 濮阳县| 抚顺市| 库伦旗| 台南县| 理塘县| 宁德市| 丰台区| 安化县| 陈巴尔虎旗| 怀安县| 宾阳县| 屯门区| 洮南市| http://wap.ddvlpt.fit http://wap.jeqvtd.fit http://jpoovz.fit http://oidpjw.fit http://wap.dgiycv.fit http://www.bm1961xarkz.fit http://www.msnvre.fit http://wap.nkizlw.fit http://m.sujalp.fit http://www.bm1961xentionz.fit http://m.xadbac.fit http://wap.hknsxj.fit http://m.ctcneg.fit http://m.rgfrsu.fit http://hksftm.fit http://www.cnjmof.fit http://m.bowitq.fit http://wap.afrfnd.fit