[翻译]Dropbox Web 服务启用 HTTP/2:经验和观察

Haowei Yuan | 2016年5月11日

最近,为了启用 HTTP/2,我们 Dropbox 的流量团队升级了前端的 Nginx 服务器。本文将分享我们迁移到 HTTP/2 的过程中的体验和新发现。整个过程较为顺利,但还是有发现一些坑,也许对大家有帮助。 继续阅读[翻译]Dropbox Web 服务启用 HTTP/2:经验和观察

HTTP/2 十分钟速知

升级到 HTTP/2 后,那些针对HTTP/1.x 的优化手段需要如何变化?

答:总结来说,除了多域名增加并行 TCP 连接数不再适用以外,启用 HTTP/2 几乎不用考虑太多。

首先,由于 HTTP/2 是复用了一个 TCP 连接进行多次传输,所以适用于 HTTP/1.x 的多域名增加并发 TCP 连接数的策略已经不再适用了。不仅如此,如果你的 CDN 和主站不是指向同一 IP 且共用同一个 https 证书的话,HTTP/2 就不会在同一个 TCP 连接中也完成来自 CDN 的资源的传递,而是会为 CDN 徒增一个额外的 TCP 连接。

继续阅读HTTP/2 十分钟速知

200 OK (from cache) 与 304 Not Modified

为什么有的缓存是 200 OK (from cache),有的缓存是 304 Not Modified 呢?很简单,看运维是否移除了 Entity Tag。移除了,就总是 200 OK (from cache)。没有移除,就两者交替出现。

最近在做百度云观测的 nginx 配置优化。从知乎上看到这个问题:“阿里云存储如何让浏览器始终以200 (from cache)缓存图片?”,提问者强调 200 OK (from cache) 和 304 Not Modified 的区别,有感而发。

其实, 200 OK (from cache)  是浏览器没有跟服务器确认,直接用了浏览器缓存;而 304 Not Modified 是浏览器和服务器多确认了一次缓存有效性,再用的缓存。

它们都是在设置了缓存的情况下触发的。

那么,两者触发的时机有什么区别呢?200 OK (from cache) 是直接点击链接访问,输入网址按回车访问也能触发;而 304 Not Modified 是刷新页面时触发,或是设置了长缓存、但 Entity Tags 没有移除时触发。这是经过查阅资料得出的结论。博主实际测试了一下,结论与之相符:

直接访问有缓存的网站都触发 200 OK (from cache)
图1 – 直接访问有缓存的网站都触发 200 OK (from cache)
刷新浏览器会触发 304 Not Modified
图2 – 刷新浏览器则会触发 304 Not Modified
同一域名下,没有 Entity Tag 的资源直接访问,是 200 OK (from cache) 的结果
图3 – 同一域名下,没有 Entity Tag 的资源直接访问,是 200 OK (from cache) 的结果
同一域名下,有 Entity Tag ,直接访问就会触发 304 Not Modified
图4 – 同一域名下,有 Entity Tag ,直接访问就会触发 304 Not Modified

现在一般都会设置长时间的缓存,正确设置方式参考这两篇笔记:

参考文献

后记

搜索了一下,发现这个问题,在网络上并还没有定论,也没发现有人去实测。

想想也对,现在网络那么快,304 Not Modified 还是 200 OK (from cache),如果不是较真地追求速度,可能大家都觉得区别不大,从而也就没发现这个问题了。

博主截图的域名是某著名 IT 公司的 CDN(已反馈)。可见犯这个错误的运维 GG 还真不少呢!

本文并不是说影响浏览器缓存只有 ETag 这一个因素的意思,请大家不要误解。只是就“为什么我加了缓存,有的却是 304 Not Modified, 而不是 200 OK(from cache)”这件事给出一个一针见血的原因和解答。本文也发在了 div.io 上,详细的 ETag 补充知识可以看 @hefangshi 补充的评论

《图解HTTP》读书笔记 – 第2章 简单的 HTTP 协议

HTTP 规定,请求由客户端发出。

客户端发出请求报文,服务器发出响应报文,如下图:

HTTP 请求具体示例 - 客户端发出 HTTP 报文,服务器端也响应一份报文
HTTP 请求具体示例 – 客户端发出 HTTP 报文,服务器端也响应一份报文

HTTP 请求报文中,使用不同的方法(Method)可以用以告知服务器意图。例如 GET 是获取, PUT 是上传,DELETE 是删除,OPTIONS 是询问支持的方法, TRACE 是追踪路径等。具体可以看下图中的表格:

HTTP/1.0 和 HTTP/1.1 支持的方法HTTP/1.0 和 HTTP/1.1 支持的方法
HTTP/1.0 和 HTTP/1.1 支持的方法

HTTP 协议是不保存状态的协议,如下图所示:

HTTP 协议自身不具备保存之前发送过的请求或响应的功能
HTTP 协议自身不具备保存之前发送过的请求或响应的功能

HTTP 协议是不保存状态的协议,因此引入了 Cookie 技术。服务器端可以往客户端浏览器写 Cookie,客户端会自动在每次请求时都往服务器发这个 Cookie

最初的 HTTP 协议是每进行一次 HTTP 通信就要断开一次 TCP 连接。由于 TCP 协议的(三次握手等)保证可靠性的机制,很多时间浪费在连接和断开上了。

这个问题的解决方案是持久连接(HTTP Persistent Connections,也称为 HTTP keep-alive 或 HTTP connecttion reuse)的方法。其特点是,只要任意一端没有明确提出断开连接,则保持 TCP 连接状态。HTTP/1.1 中,所有的连接默认都是持久连接,但在 HTTP/1.0 内未标准化。现在的服务器端基本都是 HTTP/1.1 了。除了服务器端,客户端也需要支持持久连接。

持久连接还使得管线化(pipelining)方式发送成为可能。从前发送一个请求需等待并收到响应,才能发送下一个请求。管线化出现后,不用等待响应便可发送下一个请求。

还是上图说明持久连接和管线化,如下:

早期的HTTP协议中,每次都要断开TCP连接
早期的HTTP协议中,每次都要断开TCP连接
早期的HTTP协议中,每次都要断开TCP连接。增加通信量的开销。
早期的HTTP协议中,每次都要断开TCP连接。增加通信量的开销。
持久连接旨在建立1次TCP连接后进行多次请求和响应的交互
持久连接旨在建立1次TCP连接后进行多次请求和响应的交互
管线化连接不用等待响应,直接发送下一个请求。效率大大提升。
管线化连接不用等待响应,直接发送下一个请求。效率大大提升。