Web开发须知的浏览器内幕 缓存与存储篇(2)

简介: 本文禁止转载,由UC浏览器内部出品。3. HTTP Cache综述HTTP Cache是完全按照IETF规范实现的,最新的RFC规范地址是 https://tools.ietf.org/html/rfc7234。

本文禁止转载,由UC浏览器内部出品。

3. HTTP Cache

综述

HTTP Cache是完全按照IETF规范实现的,最新的RFC规范地址是
https://tools.ietf.org/html/rfc7234。它的作用就是保存可缓存的响应以备重新使用,在下次请求时可减少响应时间和网络带宽。只有GET和HEAD method会缓存。

浏览器的优化

浏览器是过滤了部分没有意义进行缓存的响应头才保存到磁盘,例如Connection(keep-alive)、www-authenticate等。这能减少耗时较多的磁盘IO时间。另外Cookie也不会保存在HTTP Cache,而是存到专门的Cookie Storage。

新的规范允许先使用后验证(stale-while-revalidate)https://tools.ietf.org/html/rfc5861

在隐身模式下,不存在磁盘读写的HTTP Cache。
http://www.chromium.org/user-experience/incognito
但是某些浏览器厂商可能做优化,在临时文件夹中读写,退出或重启即删。

容量

容量是以整体计算的,不区分Domain。

Android WebView是20MB。iOS WebView也可能是20MB(根据https://github.com/gnustep/base/blob/master/Source/NSURLCache.m,不确定GNUstep是否也是Apple的源码)。

PC上的Chromium是以80MB为基准结合磁盘可用空间来考虑的,最大是320MB。算法是:

// js伪代码
if (可用空间 < 100MB)
  容量 = 80%的可用空间  // < 80MB
else if (可用空间 < 800MB)
  容量 = 80MB
else if (可用空间 < 2000MB)  // 约2GB
  容量 = 10%的可用空间  // < 200MB
else if (可用空间 < 20000MB)  // 约20GB
  容量 = 200MB
else  // >= 20000MB
  容量 = Math.min(1%的可用空间, 320MB)  // 200MB <= 容量 <= 320MB

其它基于Chromium开发的浏览器可能会修改这个算法,特别是移动浏览器会扩大那个常量值,以更高容量来提高资源复用数(嗯,不是复用率)。

淘汰

淘汰算法是一般是LRU,但在一些场景会结合文件大小、时间因素等做进一步优化。Cache的管理模块会记录总的缓存大小,每次创建新的缓存时会判断是否缓存是否超出容量限制,满了就会按LRU淘汰一定比例的缓存。

浏览器需要对缓存的文件进行索引,如果这个索引损坏,浏览器会删除所有的缓存。用户也可以通过设置界面来删除。此外,第三方程序也会做清理。

Revalidation

用户点击刷新按钮,会强制走revalidate流程,其它的情况都按照规范来执行。

RFC规范不只是为服务器和浏览器设计的,还考虑了网络中的各种节点,比如代理服务器、CDN服务器、智能路由等。

Chromium肯定是严格遵守RFC规范的,但第三方浏览器通常会破坏这些规范来获得一定的性能提升。比如更宽松的缓存条件。

Chromium代码参考:http_response_headers.cc : RequiresValidation

后端优化

后端需要在响应中添加Cache-Control来利用浏览器缓存。

  • Expires不要超过一年。
  • 稳定的文件应该加上max-age。max-age不要大于2^31,以免大于int32而变成负数。
  • Some HTTP/1.0 caches might not implement Cache-Control.对HTTP 1.0可以使用Pragma

没有任何与过期相关的指令的话,是由client端决定是否缓存的。Chromium有缓存,但再次请求的时候并不会走Revalidate流程,还是会得到200 OK。

因为HTTP Cache以URL为key,所以不想用以前的缓存,则可以更换URL,例如加不同的query、改文件名(如加上MD5或版本号)等。URL是忽略锚点的。

要做性能优化的同学,可以在协议文档里淘金。鉴于网上也有不少文章,这里不做整理了。

4. Cookie Storage

综述

因为Cookie是在多个请求头中复用数据的,所以需要从响应头中抽取出来另外保存。而且Cookie有自己的生命周期管理语法,就有独立的模块来管理。Cookie数据同时保存在内存和磁盘。

容量

容量是规范里就有建议最小值的。最新规范是RFC6265,它引用两个比较旧的规范RFC2965RFC2109

其中最老的规范RFC2109的6.3.1节中就有说明:

拒绝服务攻击
   浏览器应该按照host或域名设置Cookie的数量和数据大小上限。
Denial of Service Attacks
   User agents may choose to set an upper bound on the number of cookies
   to be stored from a given host or domain name or on the size of the
   cookie information.  Otherwise a malicious server could attempt to
   flood a user agent with many cookies, or large cookies, on successive
   responses, which would force out cookies the user agent had received
   from other servers.  However, the minima specified above should still
   be supported.

Chromium的实现是:
- 每个Cookie的最大长度为4096 bytes。大于这个长度的Cookie将不被处理,即不会保存。
- 每个域的最大数量是180个
- 总体的个数是3300个

这里有各个浏览器的Cookie限制列表:http://browsercookielimits.squawky.net/

内存缓存

从容量可知,所有Cookie占用的最大内存为3300*4K ≈ 13M。这点内存在手机上也是支撑得了的,所以Chromium会把硬盘上的全部Cookie数据都读到内存,每次发送请求都是在内存中查找,所以速度很快。在收到响应,需要创建或更新Cookie时,Chromium才会去写硬盘。而这个写操作是在非网络线程中完成的,避免慢速的文件IO占用网络线程的时间。

内存中的组织是以eTLD+1为key放在multimap里。

Chromium用SQLite存放cookie。在PC上是对value加密的。在iOS不加密,因为它的沙箱机制足够完善了,除非越狱。

Chromium把增删改表示为操作,向数据库发指令,而不是全部写一次。它是在后台线程flush。每30秒或满512次操作就直接Flush。

参考
http://www.quantum-step.com/download/sources/mystep/Foundation/Sources/NSHTTPCookieStorage.m
Apple是用了系统的NSHTTPCookieStorage。是全写的。

(注:本节的描述经过简化,非真实完整的实现)

淘汰

每次创建或更新Cookie就会进行垃圾回收的判断。有下列的规则:
1. 先淘汰过期的。即超出Max-Age指定时间。
2. 如果超出容量,则会按LRU规则(这里的used是指accessed)淘汰掉300个Cookie。
3. 如果最近30天内有访问过,即使超出容量也不会淘汰掉。

下面是Chromium源码中的部分注释供参考。

// Any cookies accessed more recently than kSafeFromGlobalPurgeDays will not
// be evicted by global garbage collection, even if we have more than
// kMaxCookies.  This does not affect domain garbage collection.
const int CookieMonster::kSafeFromGlobalPurgeDays = 30;


const size_t CookieMonster::kPurgeCookies = 300;

const size_t CookieMonster::kDomainCookiesQuotaLow = 30;
const size_t CookieMonster::kDomainCookiesQuotaMedium = 50;
const size_t CookieMonster::kDomainCookiesQuotaHigh =
    kDomainMaxCookies - kDomainPurgeCookies - kDomainCookiesQuotaLow -
    kDomainCookiesQuotaMedium;

开发建议

  • 浏览器可能会被用户设置成禁用Cookie。当确实需要Cookie而发现获取不了时,请做好一定的提示,提升用户体验。
  • 设好max-age,不要让冗余的cookie加入到请求头里,可加速连网过程。
  • 因为都在内存,Cookie操作的时耗较少,但太大的cookie会在连网阶段造成较高的延时。还是乖乖地加上Expire吧。
目录
相关文章
|
2月前
|
存储 缓存 NoSQL
【Azure Redis 缓存】关于Azure Cache for Redis 服务在传输和存储键值对(Key/Value)的加密问题
【Azure Redis 缓存】关于Azure Cache for Redis 服务在传输和存储键值对(Key/Value)的加密问题
|
1天前
|
存储 Web App开发 移动开发
HTML5 Web 存储详解
HTML5 Web存储提供了两种客户端数据存储机制:**Local Storage**和**Session Storage**。Local Storage用于长期存储数据,即使关闭浏览器数据也依然存在,适用于保存用户偏好设置等信息。Session Storage则在标签或窗口关闭时清除数据,适合存储临时信息。两者均提供了简单的API进行数据的存取操作,但需要注意的是,Web存储并非加密存储,不应存放敏感信息。现代浏览器普遍支持Web存储,合理利用这两种存储方式可提升Web应用的用户体验。
|
3月前
|
JavaScript 前端开发 开发工具
TypeScript的介绍,let age:number = xxx,可以直接看出数据类型,Type由微软开发,可以在任何浏览器和系统中运行,比较适合大型项目,TypeScript的安装
TypeScript的介绍,let age:number = xxx,可以直接看出数据类型,Type由微软开发,可以在任何浏览器和系统中运行,比较适合大型项目,TypeScript的安装
|
8天前
|
机器学习/深度学习 缓存 NoSQL
深度学习在图像识别中的应用与挑战后端开发中的数据缓存策略
本文深入探讨了深度学习技术在图像识别领域的应用,包括卷积神经网络(CNN)的原理、常见模型如ResNet和VGG的介绍,以及这些模型在实际应用中的表现。同时,文章也讨论了数据增强、模型集成等改进性能的方法,并指出了当前面临的计算资源需求高、数据隐私等挑战。通过综合分析,本文旨在为深度学习在图像识别中的进一步研究和应用提供参考。 本文探讨了后端开发中数据缓存的重要性和实现方法,通过具体案例解析Redis在实际应用中的使用。首先介绍了缓存的基本概念及其在后端系统性能优化中的作用;接着详细讲解了Redis的常见数据类型和应用场景;最后通过一个实际项目展示了如何在Django框架中集成Redis,
消息中间件 缓存 监控
81 0
|
2月前
|
Web App开发 JSON 安全
【跨域难题终结者】:一键解锁Chrome浏览器神秘设置,彻底告别开发阶段的跨域烦恼!
【8月更文挑战第20天】跨域是前端开发常遇难题,尤其在前后端分离项目中。浏览器因安全考量会阻止不同源间的请求。本文对比CORS、JSONP、代理服务器等解法,并介绍开发阶段通过调整Chrome设置来临时禁用跨域限制的方法,提供启动Chrome及使用`fetch`API示例,适合快速测试。但请注意这不适用于生产环境,存在一定安全风险。
195 1
|
2月前
|
缓存 前端开发 Linux
哇塞!NPM 缓存竟成开发拦路虎?快来掌握清空秘籍,开启前端开发逆袭之旅!
【8月更文挑战第20天】NPM是前端开发中管理依赖的关键工具。有时需清空其缓存以解决版本不一致或包损坏等问题,确保使用最新依赖。可通过命令`npm cache clean --force`强制清空全部缓存,或手动删除各系统下的缓存文件夹。注意清空缓存可能延长后续安装时间,建议事先备份依赖或确保可重新安装。正确管理缓存有助于提升开发效率。
39 1
|
2月前
|
Web App开发 前端开发 JavaScript
手摸手教你,从0到1开发一个Chrome浏览器插件
开发 Chrome 插件既有趣又具成就感。本教程将引导你从零开始,逐步创建一个简单的 Chrome 插件。首先了解 Chrome 插件是可增强浏览器功能的小程序。以一个基础示例开始,你将学习如何设置开发环境,包括安装 Chrome 和准备文本编辑器,并掌握 HTML、CSS 和 JavaScript 的基础知识。接着,我们将构建插件的基本结构,涉及 `manifest.json` 配置文件、`background.js` 后台脚本、`popup.html` 用户界面以及 `style.css` 样式表。
186 8
|
2月前
|
存储 缓存 JavaScript
深入理解后端开发中的缓存机制
【8月更文挑战第31天】本文将通过一个实际的后端开发案例,介绍如何有效地使用缓存来提高应用性能。我们将从基础概念开始,逐步深入到缓存策略的实施,最后通过代码示例展示如何在Node.js环境中实现一个简单的缓存系统。无论你是缓存新手还是希望优化现有系统的开发者,这篇文章都将为你提供实用的指导和启示。
|
2月前
|
存储 缓存 NoSQL
【性能飙升的秘密】FastAPI应用如何借助缓存技术实现极速响应?揭秘高效Web开发的制胜法宝!
【8月更文挑战第31天】FastAPI是一个高性能Web框架,利用Starlette和Pydantic实现高效API构建。本文介绍如何通过缓存提升FastAPI应用性能,包括使用`starlette-cache[redis]`实现Redis缓存,以及缓存一致性和缓存策略的注意事项。通过具体示例展示了缓存的配置与应用,帮助开发者构建更高效的Web应用。
63 0
下一篇
无影云桌面