这个系列的文章的第二篇,继续总结~~
这是从一个问题上衍生出的知识体系,这个问题是
从输入URL到页面加载的过程。
先梳理下这个流程
第一步
从浏览器接收url到开启网络请求线程(浏览器的进程/线程模型,js的运行机制)
浏览器的进程
浏览器是多进程的。有一个主进程,以及每一个tab页都会新开一个进程(某些情况下(比如空白tab)多个tab会合并成一个进程)
进程可能包括主进程,插件进程,GPU,tab页等等。
- brower进程
主进程,负责协调,主控等
- 第三方插件进程
每种类型的插件都会有一个进程,仅当使用插件时才会创建。
- GPU进程
只有一个,用于3d绘制
- 浏览器默认进程(内核)
每个tab页对应一个进程,负责页面渲染,脚本执行,互不影响,有时候会优化(多个空白tab会合并成一个)
浏览器的多线程内核
每个tab页可以看作浏览器的内核的进程,这个进程是多线程的,它有以下几大线程:
- GUI渲染线程
- JavaScript线程(这就是为什么一直说JS是单线程的原因)
- 事件触发线程
- 定时器触发线程
- 网络请求线程
每次网络请求都需要开辟单独线程进行,如果url解析到http请求,就会新开线程去处理资源下载。(http2.0可以实现tcp连接复用)
JS的运行机制
参考我的另一篇文章
js执行机制 事件循环
第二步
开启网络线程到发出一个完整的http请求(dns查询,tcp/IP请求,五层因特网协议栈等知识)
DNS查询IP
如果输入的是域名,需要DNS解析成IP,过程如下:
- 如果浏览器有缓存,就直接使用浏览器的缓存,如果没有,就使用本地的缓存
- 如果本地也没有缓存,就用host,再没有的话就向DNS服务器查询(中间路由有缓存的话,可以用路由缓存等)IP
dns查询是很耗时的,如果解析域名过多,会让首屏加载变慢,可以用dns-prefetch优化
tcp/IP请求
http的本质就是tcp/ip请求
这部分需要了解三次握手和断开连接时的四次挥手。
三次握手
tcp将http的长报文分为短报文,通过三次握手建立连接,进行传输数据。
- 客户端:hi,我是客户端,你是服务器吗
- 服务器: hi,我是服务器,你是客户端吗
- 客户端: 对,我是客户端
建立连接成功后,就可以开始传输数据啦~~
四次挥手
- 主动方: hi,我要断开连接啦,我只能被动接收数据了
- 被动方: hi, 我收到啦
- 被动方: hi,我也要断开连接啦
- 主动方:好的,我被动接收数据的连接也关掉了。
之后就断开了连接,无法通信。
tcp/ip的并发限制
浏览器对同一域名下的并发的tcp连接是有限制的(2-10个不等),而且在http2.0之前,一个资源下载就需要一个tcp/ip请求。
get/post的区别
get和post本质上虽然都是tcp/ip,但是除了在http层面外,在tcp/ip层面也有区别的,get只会产生一个数据包(把headers和data一起发出去),post请求会发送两个数据包(先发送headers,收到100之后会再发data)
五层因特网协议栈
从客户端发出http请求到服务器接收,中间会经过一系列的流程.简单概括就是:
从应用层发送http请求,到传输层通过三次握手建立tcp/ip连接,再到网络层ip寻址,再到数据链路层的封装成帧,最后到物理层的利用物理介质传输.
还有一个完整的OSI七层框架,多了会话层和表示层
会话层:管理不同用户和进程之间的对话,比如控制登录和登出
表示层: 处理两个通信系统中交换信息的表示方式,包括数据格式的交换,数据加密与解密,数据压缩等。
第三步
从服务器接收到请求到对应后台接收到请求(负载均衡,安全拦截以及后台内部的处理)
负载均衡
对于大型项目来说,并发访问量是很大的,这种情况下一台服务器肯定是不够的,所以一般会有若干个服务器组成一个集群,配合反向代理实现负载均衡。
用户发起请求都指向调度服务器,然后调度服务器根据实际的调度算法,分配不同的请求给对应的集群中的服务器执行,然后调度器等待实际服务器的http响应,再返回给浏览器
安全拦截
后台一般都会加拦截器,安全拦截验证,跨域验证等等
第四步
- 前台和后台的交互(http头部,响应码,报文结构,cookie等 ,gzip压缩等)
http头部
这部分包括三个部分
通用头部
Request Url: 请求的服务器的地址
Request Method: 请求方式(GET,POST,HEAD,OPTIONS,PUT,DELETE,CONNECT,TRACE)
(http1.0定义了三种请求方法,GET,POST,HEAD,http1.1新增了5种方法,OPTIONS,PUT,DELETE,CONNECT,TRACE)
Status Code: 请求返回的状态码
Remote Address: 请求的远程服务器的地址(会转成IP)
请求头部
Accept: 接收类型,表示浏览器支持的MIME((Multipurpose Internet Mail Extensions) 是描述消息内容类型的因特网标准)类型,对应服务端返回的的content-type
Accept-Encoding:浏览器支持的压缩格式,如gzip
Content-Type: 浏览器发出去的实体内容的类型
Cache-Control: 指定请求和返回的缓存机制,如no-cache
If-Modify-Since: 对应服务端的Last-Modified,用来匹配文件是否变动,是否使用缓存,只能精确到1s内,是http1.0的
Expires: 在这个时间内使用缓存,http1.0
Max-age: 代表资源在本地缓存多少秒,有效时间内使用缓存
If-none-Match: 对应服务端的Etag,用来匹配文件内容是否改变
Cookie:有cookie并且同域访问时会带上
Connection: 服务端和客户端通信连接方式,keep-alive,表示使用长连接(数据传输完成了保持TCP连接不断开(不发RST包、不四次挥手),客户端的长连接不可能无限期的拿着,会有一个超时时间,服务器有时候会告诉客户端超时时间,如果服务器没有告诉客户端超时时间也没关系,服务端可能主动发起四次挥手断开TCP连接,客户端能够知道该TCP连接已经无效;另外TCP还有心跳包来检测当前连接是否还活着)
Host:请求的服务器URL
Origin: 最初的请求是哪里发起的,只会精确到端口
Referer: 该页面的来源,会精确到页面地址,csrf拦截常用到这个字段
User-Agent:用户客户端的一些信息,如浏览器信息
响应头部
Access-Control-Allow-Headers: 服务器允许的请求的headers
Access-Control-Allow-Methods: 服务器允许请求的方法
Access-Control-Allow-Origin: 服务器允许的请求的origin
Content-Type:服务器返回的实体内容的类型
date:数据从服务端发起的时间
cache-control:告诉客户端缓存机制
Last-modified: 请求资源的最后修改时间
Expires:告知客户端在这个时间内使用缓存
Max-age:告知客户端在本地缓存多少秒
Etag:请求资源的标识,表示资源是否改变
Set-cookie:设置和页面相关联的cookie,服务器通过这个头部把cookie传给客户端
keep-alive:如果客户端设置了keep-alive,服务端会有相应的响应,比如timeout=20
Server:服务器的信息。比如Apache
响应码
不同范围的状态的意义
- 1xx—请求已被接收,继续处理
- 2xx—请求已被接受,理解
- 3xx—重定向,完成操作需要进一步的处理
- 4xx—客户端错误(参数错误,语法错误或者请求无法实现)
- 5xx—服务端错误
常见的状态码
- 200—请求已被接收并成功返回客户端
- 302—重定向
- 304—用浏览器的缓存
- 400—客户端请求有误,请求参数有误等
- 401—请求没有权限
- 403—禁止访问(比如未登录时禁止)
- 404—找不到资源
- 500—服务器内部错误
- 503—服务不可用
cookie
cookie是浏览器本地存储的一种方式,一般帮助客户端和服务端通信,用来检验身份,结合服务端的session使用。
简单说下使用场景:
- 用户登录
- 服务端收到请求,生成session,会有用户的信息
- 生成一个sessionid
- 服务端在登录页面写入cookie
- 浏览器就有这个cookie了,访问同域名的时候都会自动带上这个cookie
gzip
gzip的压缩效率很高,高达70%以上,具体可以参考我另一篇文章前端性能优化之gzip
第五步
- 缓存问题(http缓存,缓存头部,etag,cache-control等)
缓存这部分可以参考我另一篇文章
浏览器缓存机制分析
- 浏览器接收到http数据包后的解析过程(解析html,词法分析解析成dom树,解析css生成css规则树,合并成render树,然后布局,绘制渲染,复合图层的合成,GPU绘制,外链资源的处理,loaded和domcontentloaded等)
复合层,合成层,GPU,硬件提速请参考这篇文章 https://juejin.im/entry/59dc9…
- css的可视化模型(元素的渲染规则,如包含块,控制框,BFC,IFC等概念)
BFC部分可以参考这篇笔记
BFC
- JS引擎解析过程(JS的解释阶段,预处理阶段,执行阶段生成上下文,VO,作用域链,回收机制等)
JS执行机制部分可参考这篇文章
js执行机制
总的来说,知识要点就是以下这些~~
核心知识
浏览器模型
浏览器的进程和线程
渲染原理
构建dom树,css树,render树,reflow,repaint,复合层和简单层,GPU渲染
JS解析过程
字节-> 分词 -> 语法树 -> 解析成机器码
JS运行机制
变量提升,函数提升,VO, AO, this
重点知识
http相关
http1.0 http1.1 http2.0,https
http2.0的主要新特性
- 多路复用(一个tcp/ip连接可以请求多个资源)
- 首部压缩(http头部压缩,减少体积)
- 二进制分帧(在应用层和传输层多了一层二进制分帧层,改进了传输性能,实现低延迟和高吞吐量)
- 服务端推送(服务端对客户端的一个请求可以发出多个响应,可以主动通知客户端)
https就是建立在http基础上,在请求前先建立ssl连接,确保接下来的通信都是加密的,无法被窃取。
下面简单说下SSL/TLS握手流程:
- 浏览器请求建立ssl连接,并向服务端发送一个随机数client random和客户端支持的加密方法,比如RSA加密,此时是明文传输
- 服务端从中选出一组加密算法与hash算法,回复一个随机数server random,并将自己的身份信息以证书的形式发给浏览器(包括网站地址,非对称加密的公钥,证书的颁发机构等)
浏览器收到服务端发的证书后
- 验证证书的合法性(颁发机构是否合法,证书中的网址是否和所在的网址相同),如果证书信任,浏览器前面会出现一个小锁的图标
- 用户接收证书后(不管信不信任),浏览器会生成一个新的随机数premaster-key,然后用证书中的公钥和指定的加密方式加密premaster-key,发送给服务端
- 利用client random,server random和premaster-key通过一定的算法可以生成一个http连接传输的对称加密session key
- 使用约定好的hash算法计算握手消息,并使用生成的session key加密,将之前生成的所有信息发送给服务端
- 服务端接收到浏览器的回复
- 利用已知的加解密方式和自己的私钥解密客户端发来的信息,获取premaster-key
- 和浏览器相同的规则生成session key
- 使用session key解密浏览器发来的握手信息,并验证hash是否与浏览器发来的一致
- 使用session key加密一段握手信息,发送给浏览器
- 浏览器解密服务端发来的握手信息的hash,如果与服务端发来的hash一致,则此次握手结束。
web安全相关(xss,csrf)
xss 跨站脚本攻击
csrf 跨站请求伪造
跨域及处理
跨域处理参考这个系列的前一篇文章~~
从前端小白到中高级前端需要掌握的技能总结(1)