从输入URL到页面展示到底发生了什么

1、输入地址

当我们开始在浏览器中输入网址的时候,浏览器其实就已经在智能的匹配可能得 url 了,他会从历史记录,书签等地方,找到已经输入的字符串可能对应的 url,然后给出智能提示,让你可以补全url地址。对于 google的chrome 的浏览器,他甚至会直接从缓存中把网页展示出来,就是说,你还没有按下 enter,页面就出来了。

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

请求一旦发起,浏览器首先要做的事情就是解析这个域名,一般来说,浏览器会首先查看本地硬盘的 hosts 文件,看看其中有没有和这个域名对应的规则,如果有的话就直接使用 hosts 文件里面的 ip 地址。

如果在本地的 hosts 文件没有能够找到对应的 ip 地址,浏览器会发出一个 DNS请求到本地DNS服务器 。

3、浏览器向 web 服务器发送一个 HTTP 请求

拿到域名对应的IP地址之后,浏览器会以一个随机端口(1024<端口<65535)作为客户端端口向服务器的WEB程序(常用的有httpd,nginx等)80端口发起TCP的连接请求。

在发出请求后需要通过TCP/IP协议栈的层层协议,具体如下

应用层

这一层组装http协议,格式化数据

浏览器就开始打包本次请求,这里根据传输数据加密与否分为 HTTP 请求和 HTTPS 请求,使用的分别是 HTTP 协议和 HTTPS 协议,无论使用哪种协议,都要封装请求头和请求参数,以便服务器返回相应的响应。

DNS、HTTP、HTTPS 所在的层是应用层,经过应用层封装后,浏览器将应用层的包交个下一层去完成,这个过程通过 socket 编程来实现。

传输层

这一层组装TCP协议,添加连接客户端与服务端的端口信息

传输层有两种协议,一种是无连接的 UDP 协议,一种是面向连接的 TCP 协议,UDP 无需建立连接即可通信,但是不可靠,可能会丢包,TCP 需要三次握手建立连接,能够保证数据包达到目的地,但是有额外的开销,性能和速度不如 UDP。具体使用哪个协议,需要根据具体需求来定。

对于 HTTP/HTTPS 请求来说,都是基于 TCP 协议的可靠连接,TCP 协议有两个端口,一个是浏览器监听的端口(监听服务器响应),一个是服务器监听的端口(监听客户端请求,对于 HTTP 请求,通常是 80 端口,对于 HTTPS 请求,通常是 443 端口)。在传输层,会将这两个端口封装到TCP协议头中,以供操作系统根据端口来判断,将包发送到服务器的那个进程。

网络层

这一层组装IP协议,添加本地和目标机器的IP地址

传输层封装完成后,浏览器将包交给操作系统的网络层,网络层的协议是 IP 协议,在这一层,会给传输层传递过来的包加上 IP 头,其中包含源 IP 地址(浏览器所在机器)、目标 IP 地址(服务器所在机器)等信息。

操作系统知道目标机器 IP 地址后,就开始根据它来寻找目标机器,通过子网掩码对IP地址与运算得出网络地址,如果是本机局域网内的机器,网络地址必定相同,如果是局域网之外的机器,则通过ARP协议获取对应目标机器的MAC地址(网卡标识),如果不是局域网之外的机器,则通过网关和路由找到对应目标机器所在的局域网,然后再通过ARP协议获取对应目标机器的MAC地址。

链路层

这一层组装以太网协议,添加MAC 地址添加到 MAC 头中

因为以太网协议最长为1500个字节,而IP协议总长度可以达到65535个字节,所以就需要以字节为单位对 0 和 1 进行分组,并且要标识好每一组电信号的信息特征,然后按照分组的顺序依次发送,以太网规定一组电信号就是一个数据包,一个数据包被称为帧,经由网卡发出

注:使用网卡(NIC)的情况下,MAC地址会被烧到ROM中,任何一张网卡的MAC地址都是全球唯一的。有人可能会问,有了IP地址为什么还要MAC地址?MAC地址就相当于你的身份证号,一旦出生就写死了,一辈子都不会变,而且具有全局唯一性。IP地址可以动态分配,不能保证全局唯一,只能保证局域网内唯一,相当于你的居住地址,可能过段时间就会变。 网关收到包以后,会根据自己的知识判断下一步怎么走,网关往往是一个路由器,到某个目标 IP 地址怎么走,有一个路由表。网络请求包往往需要经过多个网关的跳转,才能达到最终的目标机器。


4、服务器的永久重定向响应

服务器给浏览器响应一个301永久重定向响应,这样浏览器就会访问“http://www.google.com/” 而非“http://google.com/”。

为什么服务器一定要重定向而不是直接发送用户想看的网页内容呢?其中一个原因跟搜索引擎排名有关。如果一个页面有两个地址,就像http://www.yy.com/和http://yy.com/,搜索引擎会认为它们是两个网站,结果造成每个搜索链接都减少从而降低排名。而搜索引擎知道301永久重定向是什么意思,这样就会把访问带www的和不带www的地址归到同一个网站排名下。还有就是用不同的地址会造成缓存友好性变差,当一个页面有好几个名字时,它可能会在缓存里出现好几次。

扩展知识

1)301和302的区别。

301和302状态码都表示重定向,就是说浏览器在拿到服务器返回的这个状态码后会自动跳转到一个新的URL地址,这个地址可以从响应的Location首部中获取(用户看到的效果就是他输入的地址A瞬间变成了另一个地址B)——这是它们的共同点。

他们的不同在于。301表示旧地址A的资源已经被永久地移除了(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址

302表示旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。 SEO302好于301

2)重定向原因:

(1)网站调整(如改变网页目录结构);

(2)网页被移到一个新地址;

(3)网页扩展名改变(如应用需要把.php改成.Html或.shtml)。

这种情况下,如果不做重定向,则用户收藏夹或搜索引擎数据库中旧地址只能让访问客户得到一个404页面错误信息,访问流量白白丧失;再者某些注册了多个域名的网站,也需要通过重定向让访问这些域名的用户自动跳转到主站点等。

3)什么时候进行301或者302跳转呢?

 当一个网站或者网页24—48小时内临时移动到一个新的位置,这时候就要进行302跳转,而使用301跳转的场景就是之前的网站因为某种原因需要移除掉,然后要到新的地址访问,是永久性的。

清晰明确而言:使用301跳转的大概场景如下:

1、域名到期不想续费(或者发现了更适合网站的域名),想换个域名。

2、在搜索引擎的搜索结果中出现了不带www的域名,而带www的域名却没有收录,这个时候可以用301重定向来告诉搜索引擎我们目标的域名是哪一个。

3、空间服务器不稳定,换空间的时候。

5、浏览器跟踪重定向地址

浏览器知道了 "http://www.google.com/"才是要访问的正确地址,所以它会发送另一个http请求。这里没有啥好说的

6、服务器处理请求并响应

目标服务器网卡接收到数据包,发现与网络请求包的 MAC 地址对上了,取下MAC头,将包传递给上一层网络层,发现 IP 也对上了,就取下 IP 头,然后交给传输层。

在传输层里,对于收到的每一个包,都要回复包收到了,这个回复不是此次请求的响应,仅仅是回复包已收到而已,这个回复会沿着包的来路回去。如果过了一段时间(超时时间),客户端还是没有收到来自服务器的回复,会重新发送这个包,直到收到回复为止。同样,这个重发也不是重新发起上面那个客户端请求,而是传输层将同一个请求反复重试,对用户来说,只有一次请求。

回到目标服务器,当网络包到达传输层后,TCP头中有一个服务器监听端口号,通过这个端口号,可以找到网站正在监听的端口,即 Nginx 中配置的 80/443 端口,端口对上之后,取下 TCP 头,将网络包交给应用层,开始对 HTTP/HTTPS 请求进行处理。

如果是前端资源的话,直接通过 Nginx 进行响应,如果是 PHP 动态请求的话,再由 Nginx 将请求转发给后台运行的 PHP-FPM 进程进行处理。当然如果 Nginx 做了负载均衡,以及后端服务是分布式系统或者提供了微服务的化(涉及到RPC远程调用),还有更加复杂的处理逻辑。

当后台服务处理完成后,就会返回一个 HTTPS 的响应包,告知用户请求成功,并返回响应内容,同样这个网络响应包和请求包一样,自上而下经过层层打包,顺着来路经过层层「关卡」(网关),回到发起请求的客户端,然后再经过自下而上的处理,最终将数据返回到客户端浏览器。

7、浏览器显示 HTML

在浏览器没有完整接受全部HTML文档时,它就已经开始显示这个页面了,浏览器是如何把页面呈现在屏幕上的呢?不同浏览器可能解析的过程不太一样,这里我们只介绍webkit的渲染过程,下图对应的就是WebKit渲染的过程,这个过程包括:、


浏览器在解析html文件时,会”自上而下“加载,并在加载过程中进行解析渲染。在解析过程中,如果遇到请求外部资源时,如图片、外链的CSS、iconfont等,请求过程是异步的,并不会影响html文档进行加载。

解析过程中,浏览器首先会解析HTML文件构建DOM树,然后解析CSS文件构建渲染树,等到渲染树构建完成后,浏览器开始布局渲染树并将其绘制到屏幕上。这个过程比较复杂,涉及到两个概念: reflow(回流)和repain(重绘)。

DOM节点中的各个元素都是以盒模型的形式存在,这些都需要浏览器去计算其位置和大小等,这个过程称为relow;当盒模型的位置,大小以及其他属性,如颜色,字体,等确定下来之后,浏览器便开始绘制内容,这个过程称为repain。

页面在首次加载时必然会经历reflow和repain。reflow和repain过程是非常消耗性能的,尤其是在移动设备上,它会破坏用户体验,有时会造成页面卡顿。所以我们应该尽可能少的减少reflow和repain。


当文档加载过程中遇到js文件,html文档会挂起渲染(加载解析渲染同步)的线程,不仅要等待文档中js文件加载完毕,还要等待解析执行完毕,才可以恢复html文档的渲染线程。因为JS有可能会修改DOM,最为经典的document.write,这意味着,在JS执行完成前,后续所有资源的下载可能是没有必要的,这是js阻塞后续资源下载的根本原因。所以我明平时的代码中,js是放在html文档末尾的。

JS的解析是由浏览器中的JS解析引擎完成的,比如谷歌的是V8。JS是单线程运行,也就是说,在同一个时间内只能做一件事,所有的任务都需要排队,前一个任务结束,后一个任务才能开始。但是又存在某些任务比较耗时,如IO读写等,所以需要一种机制可以先执行排在后面的任务,这就是:同步任务(synchronous)和异步任务(asynchronous)。

JS的执行机制就可以看做是一个主线程加上一个任务队列(task queue)。同步任务就是放在主线程上执行的任务,异步任务是放在任务队列中的任务。所有的同步任务在主线程上执行,形成一个执行栈;异步任务有了运行结果就会在任务队列中放置一个事件;脚本运行时先依次运行执行栈,然后会从任务队列里提取事件,运行任务队列中的任务,这个过程是不断重复的,所以又叫做事件循环(Event loop)。

在浏览器显示HTML时,它会注意到需要获取其他地址内容的标签。这时,浏览器会发送一个获取请求来重新获得这些文件。比如我要获取外图片,CSS,JS文件等,类似于下面的链接:

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

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

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

这些地址都要经历一个和HTML读取类似的过程。所以浏览器会在DNS中查找这些域名,发送请求,重定向等等...

不像动态页面,静态文件会允许浏览器对其进行缓存。有的文件可能会不需要与服务器通讯,而从缓存中直接读取,或者可以放到CDN中。


已上便是从输入URL到页面展示到底发生的过程。

你可能感兴趣的:(从输入URL到页面展示到底发生了什么)