做为软件开发人员,您确定会看到网络应用程序如何工做以及涉及哪些技术的高级画面:浏览器,HTTP,HTML,Web服务器,请求处理程序等。php
在本文中,咱们将深刻了解访问URL时发生的事件顺序。css
这一切都从这里开始:html
导航的第一步是找出访问域的IP地址。DNS查找进行以下:ajax
如下是递归DNS搜索的示意图:算法
关于DNS的一个使人担心的是,像wikipedia.org或facebook.com这样的整个域彷佛映射到一个IP地址。幸运的是有办法减轻瓶颈:数据库
大多数DNS服务器自己使用anycast来实现DNS查找的高可用性和低延迟。浏览器
您能够很是肯定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服务器发送回浏览器请求的响应:
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这样大规模扩展的网站。
在最简单的状况下,请求处理程序能够存储在结构反映URL结构的文件层次结构中,例如http://example.com/folder1/page1.aspx URL将映射到file / httpdocs / folder1 / page1的.aspx。也能够配置Web服务器软件,以便将URL手动映射到请求处理程序,所以page1.aspx的公共URL能够是http://example.com/folder1/page1。
每一个动态网站面临的一个有趣的难题是如何存储数据。较小的站点一般会有一个SQL数据库来存储他们的数据,但存储大量数据和/或有许多访问者的站点必须找到一种在多台机器上分割数据库的方式。解决方案包括分片(基于主键分割多个数据库的表),复制以及使用弱化一致性语义的简化数据库。
保持数据更新便宜的一种技术是将一些工做推迟到批处理做业。例如,Facebook必须及时更新新闻源,但支持“您可能认识的人”功能的数据可能只须要每晚更新(个人猜想,我实际上并不知道如何实现此功能)。批量做业更新致使一些不过重要的数据的陈旧,但可使数据更新更快更简单。
如下是服务器生成并发回的响应:
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时,它会注意到须要提取其余URL的标签。浏览器将发送GET请求以检索这些文件。
如下是我访问facebook.com的几个网址:
这些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几回,可能会收到来自不一样服务器的响应,这代表后台发生的负载平衡。
以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是请求 - 响应协议,所以聊天服务器没法将新消息推送到客户端。相反,客户端必须每隔几秒轮询服务器,以查看是否有新消息到达。
长时间轮询是减小这些类型场景中服务器负载的有趣技术。若是服务器在轮询时没有任何新消息,则根本不会发回响应。并且,若是在超时期限内收到了一个此客户端的消息,服务器将发现未完成的请求并返回消息。