Web 服务器/http 协议如何处理版本控制和压缩?

Web 服务器/http 协议如何处理版本控制和压缩?

当客户端浏览器向 Web 服务器请求文件时,我知道会执行某种检查,因为 Web 浏览器可能已缓存了提供网页所需的文件。因此,如果缓存中存在文件,则不会发送任何文件。但如果服务器上的文件自浏览器缓存文件以来已发生更改,则无论如何都会发送并更新该文件。

然后,如果您在服务器上启用了类似 gzip 的压缩功能,则提供给客户端的文件必须在途中进行 gzip 压缩,这需要一定量的服务器端处理。

但是如何管理呢?在我看来,合理的方法是,Web 服务器也应该有一个缓存,其中包含在一定时间范围内请求的所有文件的最新版本,因此是这些文件的压缩版本,这样就不必在每次请求文件时进行压缩。

另外,文件最终是如何请求的?浏览器每次在 HTML 代码中遇到文件并且特定文件未存储在本地缓存中时,是否都会请求文件,还是会将所有需要的文件加起来并同时请求整个文件?

但这只是从编程的角度进行猜测,而且我并不真正了解。

如果在 Web 服务器系统之间答案有很大差异,我主要对 Apache 感兴趣,但也会感谢其他答案。

答案1

您可以在HTTP 规范,但要点如下:当浏览器需要请求文件时,它首先会检查其本地缓存。主要有三种可能性:

  1. 浏览器拥有该文件的本地(缓存)版本,该文件被标记为将在某个时间过期,而这个时间是未来的时间。在这种情况下,浏览器可以选择直接使用缓存版本,也可以向服务器发送请求以查看该文件是否已更改。如果浏览器发送请求,它将包含一个If-Modified-Since标头,其中包含上次访问该文件的时间。
  2. 浏览器缓存了该文件的某个版本,但该版本已经过期。在这种情况下,浏览器肯定会向服务器发送请求,查看是否有新版本,并且该请求(通常)会包含一个If-Modified-Since标头,其中包含上次访问该文件的时间。
  3. 浏览器根本没有缓存文件,在这种情况下它会发送没有If-Modified-Since标头的请求。

当请求到达服务器时,基本上会发生以下几件事。如果请求不是包含If-Modified-Since标头,服务器将继续使用 HTTP 200(OK)响应代码返回文件。(或者它会发送 404 文件未找到、403 禁止访问或其他任何适当的代码)但如果请求做过包含If-Modified-Since标头,服务器知道它只需要返回文件,如果文件自标头中包含的时间以来被修改过。现在,如果文件自该时间以来被修改过,那么服务器将返回文件,代码为 200、403、404 等等。但如果文件有不是自指定时间以来已被修改 - 请记住,这意味着浏览器的缓存版本仍然是最新的 - 服务器可以使用 304(未修改)代码进行响应,并忽略文件本身的内容。这可以节省一些网络流量。

现在,假设服务器将以文件的完整内容进行响应,有几种方法可以实现这一点,具体取决于服务器的编写和/或配置方式。显然,每次收到请求时,它都可以从磁盘读取文件(如果是动态页面,则运行程序来生成文件)并将其发送回去,但如您所知,这样做效率不高。如果浏览器在其请求Accept-Encoding: gzip中指定,服务器可以做的一件事就是发送回文件的 gzip 版本。服务器保留 gzip 文件的缓存版本确实很有意义,Apache(可能还有大多数其他服务器)可以配置为这样做。当服务器准备发送回 gzip 响应时,它会检查 gzip 缓存版本的修改时间与原始文件的修改时间,如果原始文件已更新,它将再次对其运行 gzip 并用新版本替换缓存中的旧版本。

如果经常请求文件,有时服务器也可以将文件缓存在 RAM 中。我认为 Apache 可以配置为这样做,但我不确定。(您现在可能已经猜到了,对于 Apache 来说,一切都与配置有关。)

关于您关于如何请求文件的问题,浏览器实际上每次请求一个文件。每个 HTML 页面、CSS 文件、Javascript 文件、图像文件等都对应一个单独的 HTTP 请求。类似这样的工具Wireshark如果您感兴趣的话,实际上可以向您显示往返于您计算机的各个 HTTP 请求和响应。但为了节省资源,TCP/IP 连接通常会在整个请求集中保持打开状态。例如,如果您有一个包含 3 张图片和一个 CSS 样式表的网页,您可能会得到如下序列:

  • 浏览器打开连接
  • 服务器确认连接
  • 浏览器请求 HTML 页面
  • 服务器发送 HTML 页面
  • 浏览器请求 CSS 样式表
  • 服务器发送 CSS 样式表
  • 浏览器请求图片 1
  • 服务器发送图像 1
  • 浏览器请求图片2
  • 服务器发送图像2
  • Connection: close浏览器请求带有标头的图像 3
  • 服务器发送图像 3
  • 服务器关闭连接

任一端都可以发送标Connection: close头来指定在该请求完成后应关闭 TCP/IP 连接。

希望这能解答您的大部分疑问,但 HTTP 规范是一份巨大的文档,我忽略了许多细节。实际上,我发现阅读它相当有趣,因此建议您去看一下(不过,我可能有点奇怪)。

相关内容