深情一眼挚爱万年,我们从URL走到页面
是否有那么一个时刻让你感到原来一瞬间也可以变得无比的漫长呢?是恬静的你看着他球场轩昂?还是阳光的你看着她舞台绽放?哈哈,我相信在座的各位,你们心里都有一段自己的电影 。那么今天,请让我们回忆一下如何从URL走到页面( 请脑海播放《一眼万年》)。
从输入URL到我们看见页面,刚开始我们的感觉是转瞬即是,在学习了其中的蜿蜒之后又感到那是多么的绵长。
总的来说就是Web使用HTTP协议作为规范,通过指定的访问地址获取(上传)服务器资源。
各位看官,来来来,我们先复习一下一些干货知识
一 网络基础TCP/IP
1.TCP/IP协议族
通常使用的网络是在TCP/IP协议族的基础上运作的。HTTP是其内部一个子集。我们知道,计算机与网络设备之间的相互通信是基于相同的方法和规范,这个我们称之为协议,那么所有的此类协议并集就是TCP/IP协议族。
2.TCP/IP的分层管理
TCP/IP协议族里最重要的一条就是分层。按层次分为以下四层:
应用层、传输层、网络层和数据链路层。这样分层的好处是可以进行各层单独的设计改变,无需全局改变,只管自己,使设计简单化。
3.各层的作用
应用层
决定了向用户提供应用服务时通信的活动。TCP/IP协议族内预存了各类通用的应用服务,比如:FTP(File Transfer Protocol、文件传输协议),DNS(Domain Name System、域名系统)。HTTP协议也在这一层。
传输层
传输层对上层应用层,提供处于网络连接中的两台计算机之间的数据传输。该层有两个性质不同的协议:TCP(Transmission Control Protocol、传输控制协议),UDP(User Data Protocol、用户数据协议)。
网络层
用于处理在网络上流动的数据包。数据包是网络传输的最小单位。该层规定了通过怎样的路径(传输路线)到达对方计算机,并把数据吧传送给对方。即该层的作用就是在众多的路线中选择最优的一条传输路线。
链路层(数据链路层、网络接口层)
用来处理连接网络的硬件部分。包括控制操作系统、硬件的设备驱动、NIC(Network Interface Card、网络适配器,即网卡)及光纤等物理可见部分(包括连接器等一切传输媒介)
4 TCP/IP通信传输流
利用TCP/IP协议族进行网络通信时,会通过分层顺序与对方进行通信。发送端从应用层往下走,接收端则向应用层往上走。
“报告!那我们为什么要复习这些呢?”
“独秀同学请坐,我们接着说!”
从URL到页面的传输过程:
首先,作为发送端的客户端在应用层(HTTP协议)发出一个想看某个web页面的HTTP请求。接着,为了传输方便,在传输层(TCP/IP协议)把从应用层收到的数据(HTTP报文)进行分割,并在各个报文上打上标记序号及端口号后转发给网路层。在网络层(IP协议),增加作为通信目的地的MAC地址后转发给链路层。这样一来,发往网络的通信请求就准备齐全了。接收端的服务器在链路层接收到数据,按顺序往上层发送,一直到应用层。当数据传输到应用层,才算真正接收到由客户端发送的HTTP请求。发送端在层与层之间传输数据时,每经过一层时必定会被打上一个该层所属的首部信息。反之,在接收端每经过一层时会消去对应的首部信息。这种把信息层层包装起来的做法成为封装。
“哦哦,原来是这样!!”
“好了,我们具体走走过程”
一 输入URL
URL(Uniform Resource Locator),即统一资源定位符。简单理解,我们常说的网站名就是它了,比如百度(www.baidu.com)。一些常用到的URL协议:http,https,ftp,file协议等,其中http是明文传输,容易被破解,造成信息丢失泄露,https是加密传输,安全有保障,常见于购物网站。
二 域名解析
1、浏览器缓存解析
在我们向浏览器输入网址的时候,浏览器就已经开始在匹配可能的URL了,它会从历史记录,书签等浏览器本地缓存,寻找已经输入的字符串可能对应的之前使用过并已保存的URL,然后给出提示,让你可以补全URL地址。像chrome浏览器,它会直接从缓存中把网页展示出来,在按下 enter之前,页面就已经展现了。
2、系统缓存解析
如果浏览器本地缓存中没有对应的域名信息,紧接着浏览器会查看系统缓存情况,在本地硬盘的 hosts 文件,看看其中有没有和这个域名相对应的信息,如果有的话就直接使用 hosts 文件里面的 IP 地址。
3、路由器缓存解析
一般路由器也会缓存域名信息。在WIFI下,如果系统缓存里没有找到域名信息,当路由器有缓存该请求域名的情况下就会直接使用路由器上的缓存来解析域名信息
4、ISP DNS缓存解析
如果在本地的 hosts 文件没有能够找到对应的 ip 地址,浏览器会发出一个 DNS请求到本地DNS服务器 。本地DNS服务器一般都是你的网络接入服务器商ISP提供,比如中国电信,中国移动。查询你输入的网址的DNS请求到达本地DNS服务器之后,本地DNS服务器会首先查询它的缓存记录,如果缓存中有此条记录,就可以直接返回结果。如果没有,本地DNS服务器还要向DNS根服务器进行查询。
5、域服务器查询解析
根DNS服务器没有记录具体的域名和IP地址的对应关系,而是告诉本地DNS服务器,你可以到域服务器上去继续查询,并给出域服务器的地址。本地DNS服务器继续向域服务器发出请求,假如请求的对象是.com域服务器。.com域服务器收到请求之后,也不会直接返回域名和IP地址的对应关系,而是告诉本地DNS服务器,你的域名的解析服务器的地址。 最后,本地DNS服务器向域名的解析服务器发出请求,这时就能收到一个域名和IP地址对应关系,本地DNS服务器不仅要把IP地址返回给用户电脑,还要把这个对应关系保存在缓存中,以备下次别的用户查询时,可以直接返回结果,加快网络访问。
简单点,给个图片简单点
三 去往服务器的路上
拿到域名对应的IP地址之后,浏览器会以一个随机端口(1024<端口<65535)向服务器的WEB程序(常用的有Apache,nginx等)80端口发起TCP的连接请求。这个连接请求到达服务器端后(这中间通过各种路由设备,局域网内除外),进入到网卡,然后是进入到内核的TCP/IP协议栈(用于识别该连接请求,解封包,一层一层的剥开),还有可能要经过Netfilter防火墙(属于内核的模块)的过滤,最终到达WEB程序,最终建立了TCP/IP的连接。建立了TCP连接之后,发起一个http请求。一个典型的 http request header 一般需要包括请求的方法,例如 GET 或者 POST 等,这里我们先不说。这就是我们之前说的TCP/IP通信传输流,前面的图示很清楚。
四 服务器处理
1、服务器的永久重定向响应
服务器给浏览器响应一个301永久重定向响应,浏览器访问“http://www.google.com/” 而不是“http://google.com/”。为什么要如此麻烦?其中一个原因跟搜索引擎排名有关。如果一个页面有两个地址,就像http://www.Google.com/和http://Google.com/,搜索引擎会认为它们是两个网站,结果造成每个搜索链接都减少从而降低排名。而搜索引擎知道301永久重定向是什么意思,这样就会把访问带www的和不带www的地址归到同一个网站排名下。还有就是用不同的地址会造成缓存友好性变差,当一个页面有好几个名字时,它可能会在缓存里出现好几次。
2、浏览器跟踪重定向地址
现在浏览器明确了 "http://www.google.com/"才是要访问的正确地址,所以它会发送另一个http请求,从头再走一遍。
3、服务器处理请求
现在正确的http请求终于发送到了服务器这里,那么,服务器是如何处理我们的请求的呢?后端从在固定的端口接收到TCP报文开始,它会对TCP连接进行处理,对HTTP协议进行解析,并按照报文格式进一步封装成HTTP Request对象,供上层使用。
有些的网站会将你的请求送到反向代理服务器中,因为当网站访问量非常大,一台服务器已经不够用了。于是将同一个应用部署在多台服务器上,将大量用户的请求分配给多台机器处理。此时,客户端不是直接通过HTTP协议访问某网站应用服务器,而是先请求到Nginx反向代理服务器,Nginx再请求应用服务器,然后将结果返回给客户端。这样做的另一个好处,就是万一其中一台服务器光荣了,只要还有其他服务器正常运行,就不会影响用户使用。
五 浏览器渲染并展示网页
在浏览器没有完整接受全部HTML文档时,它就已经开始一点点地解析并显示这个页面了,不同浏览器解析的过程可能不太一样,下图对应的是WebKit内核渲染的过程,这个过程包括:
解析html以构建dom树 -> 构建render树 -> 布局render树 -> 绘制render树
浏览器在解析html文件时,会”自上而下,一句一句“加载,并在加载过程中进行解析渲染。在解析过程中,如果遇到Link标签、script标签和img标签等,会再发相应请求获取CSS、JS和图片,过程和HTML读取类似。并且请求过程是异步的,并不会影响html文档进行加载。。
解析过程中,浏览器首先会解析HTML文件构建DOM树,然后解析CSS文件构建渲染树,等到渲染树构建完成后,浏览器开始布局渲染树并将其绘制到屏幕上。这个过程比较复杂,涉及到两个概念: reflow(回流)和repaint(重绘)。
DOM节点中的各个元素都是以盒模型的形式存在,这些都需要浏览器去计算其位置和大小等,这个过程称为reflow;当盒模型的位置,大小以及其他属性,如颜色,字体,等确定下来之后,浏览器便开始绘制内容,这个过程称为repaint。
页面在首次加载时必然会经历reflow和repaint。reflow和repaint过程是非常消耗性能的,尤其是在移动设备上,它会破坏用户体验,有时会造成页面卡顿。所以我们应该尽可能少的减少reflow和repaint。
当文档加载过程中遇到JS文件,html文档会挂起渲染(加载解析渲染同步)的线程,不仅要等待文档中JS文件加载完毕,还要等待解析执行完毕,才可以恢复html文档的渲染线程。因为JS有可能会修改DOM,最为经典的例子是document.write,这意味着,在JS执行完成前,后续所有资源的下载可能是没有必要的,这是js阻塞后续资源下载的根本原因。所以JS代码最好还是放在html文档末尾。
JS的解析是由浏览器中的JS解析引擎完成的。JS是单线程运行,也就是说,在同一个时间内只能做一件事,所有的任务都需要排队,前一个任务结束,后一个任务才能开始。但是又存在某些任务比较耗时,如IO读写等,所以需要一种机制可以先执行排在后面的任务,这就是:同步任务(synchronous)和异步任务(asynchronous)。
JS的执行机制就可以看做是一个主线程加上一个任务队列(task queue)。同步任务就是放在主线程上执行的任务,异步任务是放在任务队列中的任务。所有的同步任务在主线程上执行,形成一个执行栈;异步任务有了运行结果就会在任务队列中放置一个事件;脚本运行时先依次运行执行栈,然后会从任务队列里提取事件,运行任务队列中的任务,这个过程是不断重复的,所以又叫做事件循环(Event loop)。
仅仅读完这些文字需要多久? 但在有些时候我们打开网页可能真的一秒不到(体会不到的同学建议使用chrome浏览器+固态硬盘)!从URL到页面,这里面的弯弯绕绕实在是太多,本文也只是强行说明了一番,后面内容部分参考自原博主,在此表示感谢!有不对之处欢迎批评指正,有些细节没有详述,待小白再学习学习。
本文作者:Jirengu-wk
原创内容,转载请注明出处。
参考
1 https://www.cnblogs.com/xianyulaodi/p/6547807.html#_label0
2《图解HTTP》[日] 上野宣 2014-05