2023年11月28日发(作者:)

访问⽹页流程

1. 浏览器 发送请求到 dns服务器,dns服务器 进⾏域名解析,解析完成之后 浏览器 拿到了 ⽹页服务器 IP地址

2. 浏览器 根据拿回来的ip地址发送http请求给 ⽹页服务器

3. ⽹页服务器 接收到http请求并处理,从⾃⼰的硬盘⽬录⾥找到 浏览器 请求的⽹页⽂件并返回给 浏览器

4. 浏览器 接收到 ⽹页服务器 返回的⽹页⽂件,开始⽤⾃⼰的内核渲染⽹页,并最终展⽰到显⽰器上

这⾥的每⼀步都环环相扣,中间哪个步骤都不能掉链⼦。并且每个步骤的执⾏速度,都会影响到我们对某个⽹站打开速度的直观感受。我们

再把影响这四个步骤的速度的因素来逐⼀分析:

浏览器 发送请求到 dns服务器,dns服务器 进⾏域名解析,解析完成之后 浏览器 拿到了 ⽹页服务器 IP

地址

浏览器初步解析⽤户往地址栏输⼊的字符串。

如果⽤户输⼊的字符串是合法的⽹址:浏览器会检查⾃带的 预加载HSTS列表(HTTP严格传输安全列表),这个列表⾥包含了那些请

求浏览器只使⽤ https 进⾏连接的⽹站。如果⽹站在这个列表⾥,浏览器会使⽤ https ⽽不是 http 协议,否则,没有标明协议的url域名

会默认使⽤ http 协议访问。(p.s. ⼀个⽹站哪怕不在 HSTS 列表⾥,也可以要求浏览器对⾃⼰使⽤HSTS政策进⾏访问。浏览器向⽹

站发出第⼀个HTTP请求之后,⽹站会返回浏览器⼀个响应,请求浏览器只使⽤HTTPS发送请求。然⽽,就是这第⼀个HTTP请求,却

可能会使⽤户受到⿊客攻击,这也是为什么现代浏览器都预置了HSTS列表)

如果⽤户输⼊的字符串不是⽹址,只是瞎⼏把打的词语:浏览器会将地址栏中输⼊的⽂字传给⽤户设置的默认搜索引擎,⽐如百度。

⼤部分情况下,在把⽂字传递给搜索引擎的时候,URL会带有特定的⼀串字符,⽤来告诉搜索引擎这次搜索来⾃这个特定浏览器。这

时⽤户想要访问的域名就是百度的域名 加上在地址栏⾥瞎⼏把打的搜索关键字谁是世界第⼀帅最终拼凑出来的

在以上两种情况中,浏览器都会检查输⼊⽤户输⼊的字符串是否含有不是 a-z A-Z0-9之类的字符。如果⽤户输⼊的域名有⾮ASCII

字符的话,浏览器会对域名部分使⽤ punycode 编码。例如 中国.cn,会被浏览器⽤Punycode转换为:xn--fiqs8s. cnpunycode编码

是因为操作系统的核⼼都是英⽂组成,早期的dns服务器只⽀持英⽂域名的解析,并且解析也是由英⽂代码交换,所以dns服务器并不

⽀持直接的中⽂域名解析,所有中⽂域名的解析都需要先转成punycode码。其实⽬前所说和各种浏览器都完美⽀持后来才出现的中⽂

域名,只是浏览器给中⽂域名⾃动转码了,这样就不需要⽼旧的dns服务器再次安装中⽂域名转码控件来兼容中⽂域名的解析了。

浏览器这时候得到了⽤户想要访问的⽹页服务器的域名,下⼀步是要根据这个域名拿到⽹页服务器的ip地址。

浏览器会检查该域名是否在⾃⼰的缓存当中,因为浏览器默认会把⽤户访问过的⽹站缓存在本地。如果浏览器缓存中没有,浏览器就

会去调⽤操作系统的getHostByName库函数进⾏查询。getHostByName函数会⾸先检查域名是否在本地的hosts⽂件⾥,host是⼀个

记录着 域名 -> ip地址 映射关系表 的⽂件,hosts的位置不同的操作系统有所不同。如果 getHostByName没有在本地的 hosts⽂件 ⾥找

到域名对应的ip地址,它将会向 dns服务器 发送⼀条dns查询请求,去获取域名对应的IP地址。

dns服务器开始解析。dns服务器硬件配置差,机房温度太⾼,受到ddos攻击,不合理的解析协议算法等,都会导致dns服务器域名解

析速度慢。

另:好的⽹络架构应该会在局域⽹内设⽴⼀个缓存服务器,把那些局域⽹内⼤家都经常请求的⽹址的域名ip映射,甚⾄是⽹址内容都

缓存下来,就不⽤跑去⼤⽼远的dns服务器那⾥先解析地址,之后再取⽹页⽂件了。就好⽐是全世界⼈民都喜欢吃麦当劳的薯条,但麦

当劳不会只在美国开唯⼀⼀家全球总店,⽽是世界各地都开了分店,⽽且每家分店都有薯条卖,这样⼤家就不⽤跑去美国总店吃薯条

了,出家门右转就能找到分店吃薯条了,在⽹络世界⾥,这个技术叫做CDN

浏览器 根据拿回来的ip地址发送http/https请求给 ⽹页服务器

浏览器通过本机的操作系统的http模块发送http请求,和⽹页服务器通过经典的tcp三次握⼿之后建⽴可靠的连接(从硬件层⾯来说,⽤

户的http请求数据流依次会经过⽤户的主机上的⽹卡 ->⽔晶头 -> ⽹线 ...),这⼀步的速度没啥好说的,主要就是 tcp http 这些协议

的算法的空间复杂度,时间复杂度的问题。

这个步骤可能会掉链⼦,举个掉链⼦的栗⼦:中间⼈攻击。⿊客截包之后篡改http请求头的 request host,让⽤户的请求最终发去了别

的地⽅,⽽⾮⽤户的⽬标⽹页服务器。⽐如⽤户想去真·⽹页服务器请求⼀个修改密码的⽹页,结果这个请求发了去⿊客服务器那⾥,

⿊客服务器给⽤户返回了⼀张⾼仿的修改密码页,⽤户不假思索就往这个⽹页上输⼊了⾃⼰的密码,然后就..........

真实案例:邮件重置密码时,劫持了邮件的内容,将host替换掉,然后⽤户点击发起链接的事后,⾝份认证信息(这⾥⼀般指的是⽹

站传给重置密码者的随机token)会⾃动传到恶意的host上⾯,从⽽导致攻击者可以劫持账户(已知⾝份认证信息)。

http请求头就好⽐是包裹上⾯贴着的快递单,上⾯写着这个包裹从哪来,要去哪等等信息,被随意篡改会出事的。

⽹页服务器 接收到http请求并处理,从⾃⼰的硬盘⽬录⾥找到 浏览器 请求的⽹页⽂件并返回给 浏览器

以上这步和⽹页服务器的性能有关。

⽹页服务器的http服务选择的是⽀持⾼并发的nginx,还是Apache,或者IIS都有影响,他们都属于http协议的实现,底层可能涉及到操

作系统的io速度/线程的异步执⾏/内存管理等,我对此涉猎不深,略过不表。题外话:gobuffer pythonnode都没有buffer,后⾯

俩加了bufferio那项⾄少再快⼀半。所以服务端的http服务,我看好 go

有个疑问:如果⽹页服务器的硬盘⽤的都是ssd,可能 io 速度能快⼀些,对打开⽤户访问某个⽹站的速度有直观上的提升吗?

浏览器 接收到 ⽹页服务器 返回的⽹页⽂件,开始⽤⾃⼰的内核渲染⽹页,并最终展⽰到显⽰器上

(这⼀步不考虑 服务端渲染 的情况,我们讨论最普通的 ⽤户端渲染

浏览器开始进⾏html解析

浏览器内核有很多种,但都包含 js引擎, css引擎,html解析引擎。

html解析引擎的主要⼯作是⽣成dom节点树。dom树是以dom元素以及其属性为节点的树。

由于不能使⽤常⽤的解析技术,浏览器创造了专门⽤于解析HTML的解析器。解析算法在 HTML5 标准规范中有详细介绍,算法主要包

含了两个阶段:标记化 dom树的构建。

html不能使⽤常见的⾃顶向下或⾃底向上⽅法来进⾏解析,主要原因是以下⼏点 html本⾝可容错的特性 HTML本⾝可能是残缺

的,对于常见的残缺,浏览器需要有传统的容错机制来⽀持它们,⽐如可能会写漏/写成了 解析过程需要反复。对于

其他语⾔来说,源码不会在解析过程中发⽣变化,是静态的。但是对于HTML来说,例如js脚本中包含的 () ⽅法会在源

码中添加内容,也就是说,解析过程实际上会动态改变最初输⼊的html

注意,解析 HTML ⽹页时永远不会出现语法错误,浏览器会⾃动修复所有错误,然后继续解析。

html解析完成

浏览器开始加载⽹页的外部资源(CSS,图像,Javascript ⽂件等)。这个说来话长,⽆数前端⼯程师为了能减少这⾥加载资源要发

送的http请求数量,减⼩外部资源的体积,⽤了各种令⼈窒息的操作·····················⽐如把整个⽹站⽤到的⼩图标放在⼀张png的雪碧

图,webpack的模块按需加载

此时浏览器把⽂档标记为可交互的,浏览器开始 解析 处于 推迟 defer)模式的脚本,也就是那些需要在⽂档 解析 完毕之后再 执⾏

的脚本。之后⽂档的状态会变为完成,浏览器会执⾏ onload 事件。

js引擎开始执⾏同步的 js 代码。

csscss

引擎开始解析代码,渲染页⾯(这个过程和传统⼯⼚⾥报纸的印刷⼗分类似,先把元素框的⼤概位置布局固定好,再往上细致

地喷颜⾊纹理之类)

根据css语法和句法去分析.CSS⽂件和