当网页包含单个CSS文件和图像时,为什么浏览器和服务器会通过这种传统的耗时途径浪费时间:
- 浏览器发送对该网页的初始GET请求,并等待服务器响应。
- 浏览器向css文件发送另一个GET请求,并等待服务器响应。
- 浏览器向图像文件发送另一个GET请求,然后等待服务器响应。
相反,他们何时可以使用这条简短,直接,省时的路线?
- 浏览器向网页发送GET请求。
- Web服务器以(index.html后跟style.css和image.jpg)响应
当网页包含单个CSS文件和图像时,为什么浏览器和服务器会通过这种传统的耗时途径浪费时间:
相反,他们何时可以使用这条简短,直接,省时的路线?
Answers:
简短的答案是“因为HTTP不是为此设计的”。
Tim Berners-Lee并未设计一种有效且可扩展的网络协议。他的一个设计目标是简单。(我在大学的网络课程的教授说,他应该把工作交给专业人士。)您概述的问题只是HTTP协议的众多问题之一。原始形式:
后来对该协议进行了修订,以解决许多这些问题:
GET /foo.html HTTP/1.1
Connection: keep-alive
在这一点上,HTTP已经尽可能地使用了,而没有破坏向后兼容性。
您不是第一个建议应将页面及其所有资源推送给客户端的人。实际上,Google设计了一种可以做到这一点的协议,称为SPDY。
今天,Chrome和Firefox都可以使用SPDY而不是HTTP来支持它。在SPDY网站上,与HTTP相比,它的主要功能是:
- SPDY允许客户端和服务器压缩请求和响应标头,当针对多个请求反复发送相似的标头(例如cookie)时,可以减少带宽使用。
- SPDY允许通过单个连接进行多个同时多路复用的请求,从而节省了客户端和服务器之间的往返行程,并防止了低优先级的资源阻止较高优先级的请求。
- SPDY允许服务器将知道客户端所需的资源(例如JavaScript和CSS文件)主动推送到客户端,而无需等待客户端请求它们,从而允许服务器有效利用未利用的带宽。
如果您想使用SPDY为支持该浏览器的网站提供服务,则可以这样做。例如,Apache具有mod_spdy。
SPDY已成为具有服务器推送技术的HTTP版本2的基础。
您的Web浏览器直到从服务器下载包含这些资源链接的网页(HTML)时,才知道其他资源。
您可能想知道,为什么服务器在最初请求网页期间不只是解析自己的HTML并将所有其他资源发送到Web浏览器?这是因为资源可能分散在多个服务器上,并且Web浏览器可能不需要所有这些资源,因为它已经缓存了其中一些资源,或者可能不支持它们。
Web浏览器维护资源缓存,因此不必从承载它们的服务器上一遍又一遍地下载相同的资源。当浏览网站上都使用相同jQuery库的不同页面时,您不想每次都只是第一次下载该库。
因此,当Web浏览器从服务器获取网页时,它将检查缓存中尚不具有的链接资源,然后对这些资源进行其他HTTP请求。非常简单,非常灵活且可扩展。
Web浏览器通常可以并行发出两个HTTP请求。这与AJAX不同-它们都是加载网页的异步方法-异步文件加载和异步内容加载。使用keep-alive,我们可以使用一个连接发出多个请求,而通过流水线,我们可以发出多个请求而不必等待响应。这两种技术都非常快,因为大多数开销通常来自打开/关闭TCP连接:
网页历史记录...
网页从纯文本电子邮件开始,围绕这个想法设计了计算机系统,从而形成了某种免费的交流平台。Web服务器在当时仍然是专有的。后来,以其他MIME类型的形式,例如图像,样式,脚本等,在“电子邮件规范”中添加了更多层。毕竟,MIME代表多用途Internet 邮件扩展。迟早我们有了本质上就是多媒体电子邮件通信,标准化的Web服务器和网页的工具。
HTTP要求在类似电子邮件的消息上下文中传输数据,尽管该数据通常实际上并不是电子邮件。
随着这种技术的发展,它需要允许开发人员逐步整合新功能,而又不会破坏现有软件。例如,当将新的MIME类型添加到规范中(例如JPEG)时,Web服务器和Web浏览器将需要一些时间来实现它。您不只是突然将JPEG强制加入规范中并开始将其发送到所有Web浏览器,还允许Web浏览器请求其支持的资源,这使每个人都满意并且技术不断进步。屏幕阅读器是否需要网页上的所有JPEG?可能不是。如果您的设备不支持Javascript,是否应该强迫您下载一堆Javascript文件?可能不是。Googlebot是否需要下载所有Javascript文件才能正确索引您的网站?不。
资料来源:我已经开发了基于事件的Web服务器,例如Node.js。它称为Rapid Server。
参考文献:
进一步阅读:
https://
发送可验证但不保密的大型公共分发文件的替代方案的想法是什么:在URL中包含合法回复标头的某些部分的哈希,这反过来又可以包括数据有效载荷的签名或散列,浏览器是否已针对标头验证收到的数据?这样的设计不仅可以节省一些SSL握手步骤,而且更重要的是可以缓存代理。通过SSL链接获取URL,然后可以从任何地方馈送数据。
因为他们不知道这些资源是什么。网页所需的资产已编码为HTML。只有在解析器确定了那些资产之后,用户代理才能请求y。
此外,一旦知道了这些资产,就需要单独提供它们,以便可以提供适当的头(即内容类型),以便用户代理知道如何处理它。
<head>
元素以寻找RSS替代链接来找到它-客户端可以发送它感兴趣的是什么,但随后它需要知道可用的东西,然后我们又回到了起点
因为在您的示例中,Web服务器将始终发送CSS和图像,而不管客户端是否已经拥有CSS和图像,从而极大地浪费了带宽(从而使连接速度变慢,而不是通过减少延迟来加快连接速度,这大概是您的意图)。请注意,正是由于这个原因,CSS,JavaScript和图像文件通常以很长的过期时间发送(因为当您需要更改它们时,只需更改文件名以强制新副本,该副本将再次被缓存很长时间)。
现在,您可以尝试通过说“ 确定,但客户端可以表明它已经具有某些资源,因此服务器不会再发送它 ” 来解决带宽浪费问题。就像是:
GET /index.html HTTP/1.1
Host: www.example.com
If-None-Match: "686897696a7c876b7e"
Connection: Keep-Alive
GET /style.css HTTP/1.1
Host: www.example.com
If-None-Match: "70b26618ce2c246c71"
GET /image.png HTTP/1.1
Host: www.example.com
If-None-Match: "16d5b7c2e50e571a46"
然后仅通过一个TCP连接(使用在持久连接上使用HTTP流水线)发送未更改的文件。你猜怎么着?这是怎么了已经工作的(你也可以使用IF-Modified-Since的,而不是如果-无-匹配)。
但是,如果您真的想通过浪费大量带宽(如您的原始请求)来减少延迟,今天就可以在设计网站时使用标准的HTTP / 1.1来做到这一点。大多数人不这样做的原因是因为他们认为这样做不值得。
为此,您不需要在单独的文件中包含CSS或JavaScript,您可以使用<style>
和<script>
标记将它们包含在主HTML文件中(您甚至可能不需要手动进行操作,您的模板引擎就可以自动进行操作) 。您甚至可以使用数据URI将图像包含在HTML文件中,如下所示:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot" />
当然,base64编码会稍微增加带宽使用量,但是如果您不关心带宽浪费,那应该不是问题。
现在,如果您真的很在意,您甚至可以使您的Web脚本足够聪明,以同时兼顾两个方面:在首次请求(用户没有cookie的情况下)中,发送嵌入在单个HTML中的所有内容(CSS,JavaScript,图像)文件,如上所述,为文件的外部副本添加一个链接rel =“ prefetch”标签,并添加一个cookie。如果用户已经有一个cookie(例如,他曾访问过),然后送他只是一个普通的HTML <img src="example.jpg">
,<link rel="stylesheet" type="text/css" href="style.css">
等等。
因此,第一次访问时,浏览器将只请求一个HTML文件并获取并显示所有内容。然后,它将(在空闲时)预加载指定的外部CSS,JS,图像。下次用户访问时,浏览器将请求并仅获取更改的资源(可能只是新的HTML)。
即使您在网站上单击了数百次,额外的CSS + JS + images数据也只会发送两次。比您提出的解决方案建议的要好数百倍。它永远不会(不是第一次,也没有对今后一段时期)使用超过一个延迟增加往返。
现在,如果这听起来工作量太大,并且您不想使用其他协议(例如SPDY),则已经有适用于Apache的mod_pagespeed之类的模块,可以自动为您完成某些工作(合并多个CSS / JS文件)合并成一个,自动内嵌小型CSS并将其最小化,在等待原件加载,惰性加载图像等时制作小型占位符内嵌图像,而无需修改网页的一行。
HTTP2基于SPDY,完全可以满足您的建议:
在较高级别,HTTP / 2:
- 是二进制的,而不是文本的
- 完全多路复用,而不是有序和阻塞
- 因此可以使用一个连接进行并行处理
- 使用头压缩来减少开销
- 允许服务器主动将响应“推送”到客户端缓存
关于HTTP 2常见问题的更多信息
因为它不假设这些东西实际上是必需的。
该协议没有为任何特定类型的文件或用户代理定义任何特殊处理。它不知道HTML文件和PNG图像之间的区别。为了执行您要执行的操作,Web服务器将必须识别文件类型,将其解析以找出正在引用的其他文件,然后根据您打算做什么来确定实际需要的其他文件。文件。这有三个大问题。
第一个问题是,没有标准,可靠的方法来识别服务器端的文件类型。HTTP通过Content-Type机制进行管理,但这对服务器无济于事,服务器必须自行弄清这些内容(部分原因是它知道要放入Content-Type中的内容)。文件扩展名得到了广泛支持,但易碎且容易上当,有时出于恶意目的。文件系统元数据不那么脆弱,但是大多数系统并不很好地支持它,因此服务器甚至不需要打扰。file
如果您愿意增加内容嗅探(如某些浏览器和Unix 命令尝试的那样),则内容嗅探可能会很健壮,但是健壮的嗅探过于昂贵,无法在服务器端实际使用,廉价的嗅探还不够健壮。
第二个问题是,在计算上,解析文件是昂贵的。这有点关系到第一个,因为如果要稳健地嗅探内容,则需要以多种不同的潜在方式解析文件,但是在确定文件类型之后它也适用,因为您需要弄清楚引用是什么。当您一次只处理几个文件时(例如浏览器),这并不是很糟糕,但是Web服务器必须一次处理成百上千个请求。这加起来,并且如果它走得太远,它实际上会使事情减慢的速度超过多个请求的速度。如果您曾经访问过来自Slashdot或类似网站的链接,却发现服务器由于使用率过高而极度缓慢,那么您已经看到了这一原理。
第三个问题是服务器无法知道您打算如何处理该文件。浏览器可能需要在HTML中引用文件,但可能不需要,这取决于执行文件的确切上下文。那将足够复杂,但是Web不仅仅是浏览器,还有更多:蜘蛛,提要聚合器和页面抓取混搭之间,有许多类型的用户代理不需要HTML中引用的文件:只关心HTML本身。将这些其他文件发送到此类用户代理只会浪费带宽。
最重要的是,弄清楚服务器端的这些依赖关系比它值得的麻烦更多。因此,他们让客户确定需要什么。