作为软件开发人员,您肯定会看到网络应用程序如何工作以及涉及哪些技术的高级画面:浏览器,HTTP,HTML,Web服务器,请求处理程序等。
在本文中,我们将深入了解访问URL时发生的事件顺序。
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地址映射到多个物理服务器。不幸的是,anycast不适合TCP,在这种情况下很少使用。
大多数DNS服务器本身使用anycast来实现DNS查找的高可用性和低延迟。
3.浏览器向Web服务器发送HTTP请求
您可以非常确定Facebook的主页将不会从浏览器缓存中提供,因为动态页面会非常快速或即时(过期日期设置为过期)。
因此,浏览器会将此请求发送到Facebook服务器:
GET http://facebook.com/ HTTP / 1.1 接受:application / x-ms-application,image / jpeg,application / xaml + xml,[...] User-Agent:Mozilla / 4.0(compatible; MSIE 8.0; Windows NT 6.1; WOW64; [...] Accept-Encoding:gzip,deflate 连接:保持活力 主持人:facebook.com 饼干:DATR = 1265876274- [...] ; 区域设置= EN_US; LSD = WW [...] ; c_user = 2101 [...]
GET请求命名要提取的URL : “http://facebook.com/”。浏览器识别自己(User-Agent头),并说明它将接受什么类型的响应(Accept和Accept-Encoding标头)。该连接头要求服务器以保持TCP连接开放的进一步请求。
该请求还包含浏览器对此域的Cookie。您可能已经知道,Cookie是跟踪不同页面请求之间的网站状态的键值对。因此,Cookie会存储登录用户的名称,由服务器分配给用户的密码,用户的某些设置等。Cookie将存储在客户端上的文本文件中,并发送到服务器与每个请求。
有各种工具可让您查看原始的HTTP请求和相应的响应。我最喜欢的查看原始HTTP流量的工具是轻松的,但还有许多其他工具(例如FireBug)。这些工具在优化网站时是非常有帮助的。
除了GET请求之外,您可能熟悉的其他类型的请求是POST请求,通常用于提交表单。GET请求通过URL发送其参数(例如:http://robozzle.com/puzzle.aspx ?id = 85)。POST请求在请求正文中发送其参数,就在头文件下方。
网址“http://facebook.com/”中的尾部斜杠很重要。在这种情况下,浏览器可以安全地添加斜杠。对于http://example.com/folderOrFile表单的网址,浏览器无法自动添加斜杠,因为folderOrFile是否是文件夹或文件不清楚。在这种情况下,浏览器将不用斜杠访问URL,服务器将以重定向进行响应,导致不必要的往返。
Facebook服务器以永久重定向方式进行响应
这是Facebook服务器发送回浏览器请求的响应:
HTTP / 1.1 301永久移动 Cache-Control:private,no-store,no-cache,must-revalidate,post-check = 0, 前检查= 0 过期日:2000年1月1日星期六00:00:00 GMT 位置:http://www.facebook.com/ P3P:CP =“DSP LAW” Pragma:不缓存 Set-Cookie:made_write_conn = deleted; expires =星期四,2009年2月12日05:09:50 GMT; 路径= /; 域= .facebook.com; 仅Http 内容类型:text / html; 字符集= utf-8的 X-Cnection:关闭 日期:2010年2月12日,星期五05:09:51 GMT 内容长度:0
服务器回复了301移动永久响应,告诉浏览器转到“http://www.facebook.com/”而不是“http://facebook.com/”。
有一些有趣的原因为什么服务器坚持重定向,而不是立即响应用户想要看到的网页。
一个原因与搜索引擎排名有关。请参阅如果同一页面有两个URL,例如http://www.igoro.com/和http://igoro.com/,搜索引擎可能会认为它们是两个不同的网站,每个网站的入站链路较少,因此排名较低。搜索引擎了解永久重定向(301),并将来自两个来源的传入链接组合成单个排名。
此外,同一内容的多个URL不是缓存友好的。当一段内容有多个名称时,它会在缓存中潜在出现多次。
浏览器遵循重定向
浏览器现在知道“http://www.facebook.com/”是正确的URL,因此它会发出另一个GET请求:
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
标题的含义与第一个请求相同。
服务器'处理'请求
服务器将收到GET请求,处理它并发送回应。
这似乎是一个简单的任务,但事实上,这里发生了很多有趣的事情 - 即使在像我的博客这样的简单网站上,更不用说像Facebook这样大规模扩展的网站。
- Web服务器软件
Web服务器软件(例如IIS或Apache)接收HTTP请求,并决定执行哪个请求处理程序来处理此请求。请求处理程序是一个读取请求并生成响应的HTML的程序(在ASP.NET,PHP,Ruby,...中)。在最简单的情况下,请求处理程序可以存储在结构反映URL结构的文件层次结构中,例如http://example.com/folder1/page1.aspx URL将映射到file / httpdocs / folder1 / page1的.aspx。也可以配置Web服务器软件,以便将URL手动映射到请求处理程序,因此page1.aspx的公共URL可以是http://example.com/folder1/page1。
- 请求处理程序
请求处理程序读取请求,其参数和Cookie。它将读取并可能更新存储在服务器上的一些数据。然后,请求处理程序将生成一个HTML响应。
每个动态网站面临的一个有趣的难题是如何存储数据。较小的站点通常会有一个SQL数据库来存储他们的数据,但存储大量数据和/或有许多访问者的站点必须找到一种在多台机器上分割数据库的方式。解决方案包括分片(基于主键分割多个数据库的表),复制以及使用弱化一致性语义的简化数据库。
保持数据更新便宜的一种技术是将一些工作推迟到批处理作业。例如,Facebook必须及时更新新闻源,但支持“您可能认识的人”功能的数据可能只需要每晚更新(我的猜测,我实际上并不知道如何实现此功能)。批量作业更新导致一些不太重要的数据的陈旧,但可以使数据更新更快更简单。
7.服务器发回一个HTML响应
以下是服务器生成并发回的响应:
HTTP / 1.1 200 OK Cache-Control:private,no-store,no-cache,must-revalidate,post-check = 0, 前检查= 0 过期日:2000年1月1日星期六00:00:00 GMT P3P:CP =“DSP LAW” Pragma:不缓存 内容编码:gzip 内容类型:text / html; 字符集= utf-8的 X-Cnection:关闭 转移编码:分块 日期:2010年2月12日,星期五09:05:55 GMT 2B3
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的扩展。
浏览器开始渲染HTML
即使在浏览器收到整个HTML文档之前,它也开始渲染网站:
浏览器发送嵌入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,则可以立即停止传输。
你可以猜测网址中的“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代码片段。
除此之外,提示工具可让您查看浏览器发送的异步请求。实际上,你不仅可以被动地观察请求,还可以修改并重新发送。事实上,这是一个易于“欺骗”AJAX请求的事实,对于使用记分牌的在线游戏的开发者来说,造成了很大的伤害。(显然,请不要以这种方式作弊。)
Facebook聊天提供了一个AJAX有趣的问题的例子:将数据从服务器推送到客户端。由于HTTP是请求 - 响应协议,因此聊天服务器无法将新消息推送到客户端。相反,客户端必须每隔几秒轮询服务器,以查看是否有新消息到达。
长时间轮询是减少这些类型场景中服务器负载的有趣技术。如果服务器在轮询时没有任何新消息,则根本不会发回响应。而且,如果在超时期限内收到了一个此客户端的消息,服务器将发现未完成的请求并返回消息。