经典问题:浏览器输入URL后经历了什么

380 阅读12分钟
原文链接: mp.weixin.qq.com

当前浏览器不支持播放音乐或语音,请在微信或其他浏览器中播放 Solo Clean Bandit - Solo

大概流程总结1、DNS解析2、TCP连接3、发送HTTP请求4、服务器处理请求并返回HTTP报文5、浏览器解析渲染页面6、连接结束

1.在浏览器中输入URL

一切都从这里开始:

2.浏览器查找域名的IP地址

 

导航的第一步是确定访问域的IP地址。DNS查找过程如下:

  • 浏览器缓存 -浏览器缓存DNS记录一段时间。有趣的是,操作系统不会告诉浏览器每个DNS记录的生存时间,因此浏览器会将它们缓存一段固定的时间(因浏览器而异,2到30分钟)。

  • 操作系统缓存 - 如果浏览器缓存不包含所需的记录,浏览器将进行系统调用(Windows中的gethostbyname)。操作系统有自己的缓存。

  • 路由器缓存 - 请求继续到您的路由器,路由器通常有自己的DNS缓存。

  • ISP DNS缓存 - 检查的下一个位置是缓存ISP的DNS服务器。有了缓存,很自然。

  • 递归搜索 - 您的ISP的DNS服务器开始递归搜索,从根名称服务器,通过.com顶级名称服务器,到Facebook的名称服务器。通常,DNS服务器将在缓存中具有.com名称服务器的名称,因此不需要命中根名称服务器。

以下是递归DNS搜索的示意图:

 

关于DNS的一个令人担忧的事情是像wikipedia.org或facebook.com这样的整个域似乎映射到单个IP地址。幸运的是,有一些方法可以缓解瓶颈:

  • 循环DNS是一种解决方案,其中DNS查找返回多个IP地址,而不仅仅是一个。例如,facebook.com实际上映射到四个IP地址。

  • 负载均衡器是侦听特定IP地址并将请求转发到其他服务器的硬件。主要站点通常使用昂贵的高性能负载平衡器。

  • 地理DNS通过将域名映射到不同的IP地址来提高可扩展性,具体取决于客户端的地理位置。这非常适合托管静态内容,以便不同的服务器不必更新共享状态。

  • Anycast是一种路由技术,其中单个IP地址映射到多个物理服务器。不幸的是,任播不适合TCP,在这种情况下很少使用。

大多数DNS服务器本身使用任播来实现DNS查找的高可用性和低延迟。

3.浏览器向Web服务器发送HTTP请求

您可以非常肯定Facebook的主页不会从浏览器缓存中提供,因为动态页面会很快或立即过期(到期日期设置为过去)。

因此,浏览器会将此请求发送到Facebook服务器:

获取http://facebook.com/ HTTP / 1.1接受:application / x-ms-application,image / jpeg,application / xaml + xml,[...] User-Agent:Mozilla / 4.0(兼容; MSIE 8.0; Windows NT 6.1; WOW64; [...]Accept-Encoding:gzip,deflate连接:保持活力主持人:facebook.comCookie:datr = 1265876274- [...] ; 区域设置= EN_US; lsd = WW [...] ; c_user = 2101 [...]

GET请求命名要获取的URL  “http://facebook.com/”。浏览器标识自身(User-Agent 标头),并说明它将接受哪些类型的响应(AcceptAccept-Encoding标头)。该连接 头要求服务器以保持TCP连接开放的进一步请求。

该请求还包含浏览器为此域提供的cookie。您可能已经知道,Cookie是键值对,用于跟踪不同页面请求之间的网站状态。因此,cookie存储登录用户的名称,服务器分配给用户的密码,用户的一些设置等。这些cookie将存储在客户端的文本文件中,并发送到每个请求的服务器。

有许多工具可以让您查看原始HTTP请求和相应的响应。我最喜欢查看原始HTTP流量的工具是提琴手,但还有许多其他工具(例如,FireBug)这些工具在优化网站时非常有用。

除了GET请求之外,您可能熟悉的另一类请求是POST请求,通常用于提交表单。GET请求通过URL发送其参数(例如:http://robozzle.com/puzzle.aspx ?id = 85)。POST请求在请求正文中,在标题下发送其参数。

URL“http://facebook.com/”中的尾部斜杠非常重要。在这种情况下,浏览器可以安全地添加斜杠。对于http://example.com/folderOrFile形式的URL,浏览器无法自动添加斜杠,因为不清楚folderOrFile是文件夹还是文件。在这种情况下,浏览器将访问没有斜杠的URL,服务器将使用重定向进行响应,从而导致不必要的往返。

4. facebook服务器以永久重定向进行响应

这是Facebook服务器发送回浏览器请求的响应:

HTTP / 1.1 301永久移动缓存控制:私有,无存储,无缓存,必须重新验证,后检查= 0,
      前检查= 0到期日:周一,2000年1月1日00:00:00 GMT地点:http://www.facebook.com/P3P:CP =“DSP LAW”Pragma:没有缓存Set-Cookie:made_write_conn =已删除; expires = Thu,12-Feb-2009 05:09:50 GMT;
      路径= /; 域= .facebook.com; 仅HttpContent-Type:text / html; 字符集= utf-8的X-Cnection:关闭日期:星期五,2010年2月12日05:09:51 GMT内容长度:0

服务器响应301 Moved Permanently响应,告诉浏览器转到“http://www.facebook.com/”而不是“http://facebook.com/”。

服务器坚持重定向而不是立即响应用户想要查看的网页有一些有趣的原因。

一个原因与搜索引擎排名有关。请参阅,如果同一页面有两个网址,例如http://www.igoro.com/和 http://igoro.com/,搜索引擎可能会将它们视为两个不同的网站,每个网站都有较少的传入链接和因此排名较低。搜索引擎理解永久重定向(301),并将来自两个源的传入链接组合成单个排名。

此外,相同内容的多个URL不支持缓存。当一段内容具有多个名称时,它可能会在缓存中多次出现。

5.浏览器遵循重定向

浏览器现在知道“http://www.facebook.com/”是要去的正确的URL,因此它发出另一个GET请求:

获取http://www.facebook.com/ HTTP / 1.1接受:application / x-ms-application,image / jpeg,application / xaml + xml,[...]接受语言:en-US用户代理:Mozilla / 4.0(兼容; MSIE 8.0; Windows NT 6.1; WOW64; [...]Accept-Encoding:gzip,deflate连接:保持活力Cookie:lsd = XW [...] ; c_user = 21 [...] ; x-referer = [...] 主持人:www.facebook.com

标头的含义与第一个请求的含义相同。

6.服务器“处理”请求

服务器将接收GET请求,处理它并发回响应。

这似乎是一项简单的任务,但实际上这里发生了许多有趣的事情 - 即使是在像我的博客这样的简单网站上,更不用说在像facebook这样的大规模可扩展的网站上了。

  • Web服务器软件Web服务器软件(例如,IIS或Apache)接收HTTP请求并决定应该执行哪个请求处理程序来处理此请求。请求处理程序是一个程序(在ASP.NET,PHP,Ruby,...中),它读取请求并为响应生成HTML。

    在最简单的情况下,请求处理程序可以存储在文件层次结构中,其结构镜像URL结构,因此例如http://example.com/folder1/page1.aspx URL将映射到文件/ httpdocs / folder1 / page1的.aspx。还可以配置Web服务器软件,以便将URL手动映射到请求处理程序,因此page1.aspx的公共URL可以是http://example.com/folder1/page1。

  • 请求处理程序请求处理程序读取请求,其参数和cookie。它将读取并可能更新存储在服务器上的一些数据。然后,请求处理程序将生成HTML响应。

每个动态网站面临的一个有趣难点是如何存储数据。较小的站点通常会有一个SQL数据库来存储其数据,但存储大量数据和/或有许多访问者的站点必须找到一种方法来跨多台计算机拆分数据库。解决方案包括分片(基于主键在多个数据库中拆分表),复制和使用具有弱化一致性语义的简化数据库。

保持数据更新便宜的一种技术是将一些工作推迟到批处理作业。例如,Facebook必须及时更新新闻源,但支持“你可能知道的人”功能的数据可能只需要每晚更新(我的猜测,我实际上并不知道他们如何实现这一功能)。批处理作业更新导致一些不太重要的数据过时,但可以使数据更新更快更简单。

7.服务器发回HTML响应

以下是服务器生成并发回的响应:

HTTP / 1.1 200好的缓存控制:私有,无存储,无缓存,必须重新验证,后检查= 0,
    前检查= 0到期日:周一,2000年1月1日00:00:00 GMTP3P:CP =“DSP LAW”Pragma:没有缓存内容编码:gzipContent-Type:text / html; 字符集= utf-8的X-Cnection:关闭Transfer-Encoding:chunked日期:2010年2月12日星期五09:05:55 GMT2B3 Tn的@ [...]

整个响应是36 kB,其中大部分是在我修剪的结尾处的字节blob中。

内容编码头告诉该响应体用gzip算法压缩的浏览器。解压缩blob后,您将看到您期望的HTML:

<!DOCTYPE html PUBLIC“ -  // W3C // DTD XHTML 1.0 Strict // EN”   
      “http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”><html xmlns =“http://www.w3.org/1999/xhtml”xml:lang =“en” 
      lang =“en”id =“facebook”class =“no_js”><HEAD><meta http-equiv =“Content-type”content =“text / html; charset = utf-8”/><meta http-equiv =“Content-language”content =“en”/>...

除了压缩之外,标头还指定是否以及如何缓存页面,要设置的任何cookie(此响应中没有),隐私信息等。

请注意将Content-Type设置text / html 的标头。标题指示浏览器将响应内容呈现为HTML,而不是将其作为文件下载。浏览器将使用标头来决定如何解释响应,但也会考虑其他因素,例如URL的扩展名。

8.浏览器开始呈现HTML

甚至在浏览器收到整个HTML文档之前,它就开始渲染网站:

 

9.浏览器发送对嵌入HTML的对象的请求

当浏览器呈现HTML时,它会注意到需要获取其他URL的标记。浏览器将发送GET请求以检索每个文件。

以下是我访问facebook.com时检索到的一些网址:

  • 图片http://static.ak.fbcdn.net/rsrc.php/z12E0/hash/8q2anwu7.gif  http://static.ak.fbcdn.net/rsrc.php/zBS5C/hash/7hwy7at6.gif 

  • CSS样式表http://static.ak.fbcdn.net/rsrc.php/z448Z/hash/2plh8s4n.css  http://static.ak.fbcdn.net/rsrc.php/zANE1/hash/cvtutcee.css 

  • JavaScript文件http://static.ak.fbcdn.net/rsrc.php/zEMOA/hash/c8yzb6ub.js http://static.ak.fbcdn.net/rsrc.php/z6R9L/hash/cq2lgbs8.js 

这些URL中的每一个都将经历与HTML页面类似的过程。因此,浏览器将在DNS中查找域名,向URL发送请求,遵循重定向等。

但是,静态文件(与动态页面不同)允许浏览器缓存它们。某些文件可以从缓存中提供,而根本不联系服务器。浏览器知道缓存特定文件的时间长度,因为返回文件的响应包含Expires头。此外,每个响应还可能包含一个类似版本号的ETag标头 - 如果浏览器看到它已经拥有的文件版本的ETag,它可以立即停止传输。

你能猜出URL中的“fbcdn.net”代表什么吗?一个安全的赌注是它意味着“Facebook内容交付网络”。Facebook使用内容分发网络(CDN)来分发静态内容 - 图像,样式表和JavaScript文件。因此,这些文件将被复制到全球的许多机器上。

静态内容通常代表站点的大部分带宽,并且可以通过CDN轻松复制。通常,站点将使用第三方CDN提供商,而不是自己运行CND。例如,Facebook的静态文件由最大的CDN提供商Akamai托管。

作为演示,当您尝试ping static.ak.fbcdn.net时,您将收到来自akamai.net服务器的响应。另外,有趣的是,如果您多次ping URL,可能会收到来自不同服务器的响应,这表明在幕后发生的负载平衡。

10.浏览器发送进一步的异步(AJAX)请求

本着Web 2.0的精神,即使在呈现页面之后,客户端仍继续与服务器通信。

例如,Facebook聊天将继续更新您登录的朋友列表。要更新已登录朋友的列表,浏览器中执行的JavaScript必须向服务器发送异步请求。异步请求是以编程方式构造的GET或POST请求,该请求转到特殊URL。在Facebook示例中,客户端向http://www.facebook.com/ajax/chat/buddy_list.php发送POST请求以获取您在线的朋友列表。

这种模式有时被称为“AJAX”,它代表“异步JavaScript和XML”,即使服务器必须将响应格式化为XML也没有特别的原因。例如,Facebook返回JavaScript代码片段以响应异步请求。

除此之外,fiddler工具还允许您查看浏览器发送的异步请求。实际上,您不仅可以被动地观察请求,还可以修改和重新发送它们。事实上,这种易于“欺骗”的AJAX请求给使用记分板的在线游戏的开发者带来了很多麻烦。(显然,请不要以这种方式作弊。)

Facebook聊天提供了一个AJAX有趣问题的例子:将数据从服务器推送到客户端。由于HTTP是请求 - 响应协议,因此聊天服务器无法将新消息推送到客户端。相反,客户端必须每隔几秒轮询服务器以查看是否有任何新消息到达。

在这些类型的场景中,长轮询是一种减少服务器负载的有趣技术。如果服务器在轮询时没有任何新消息,则它根本不会发回响应。并且,如果在超时期限内收到此客户端的消息,服务器将找到未完成的请求并返回带有响应的消息。