浏览器多进程多线程

# 浏览器多进程多线程

# 梳理主干流程

回到这道题上,如何回答呢?先梳理一个骨架

知识体系中,最重要的是骨架,脉络。有了骨架后,才方便填充细节。所以,先梳理下主干流程:

1. 从浏览器接收url到开启网络请求线程(这一部分可以展开浏览器的机制以及进程与线程之间的关系)

2. 开启网络线程到发出一个完整的http请求(这一部分涉及到dns查询,tcp/ip请求,五层因特网协议栈等知识)

3. 从服务器接收到请求到对应后台接收到请求(这一部分可能涉及到负载均衡,安全拦截以及后台内部的处理等等)

4. 后台和前台的http交互(这一部分包括http头部、响应码、报文结构、cookie等知识,
可以提下静态资源的cookie优化,以及编码解码,如gzip压缩等)

5. 单独拎出来的缓存问题,http的缓存(这部分包括http缓存头部,etag,catch-control等)

6. 浏览器接收到http数据包后的解析流程(解析html-词法分析然后解析成dom树、解析css生成css规则树、
合并成render树,然后layout、painting渲染、复合图层的合成、GPU绘制、外链资源的处理、loaded和domcontentloaded等)

7. CSS的可视化格式模型(元素的渲染规则,如包含块,控制框,BFC,IFC等概念)

8. JS引擎解析过程(JS的解释阶段,预处理阶段,执行阶段生成执行上下文,VO,作用域链、回收机制等等)

9. 其它(可以拓展不同的知识模块,如跨域,web安全,hybrid模式等等内容)

梳理出主干骨架,然后就需要往骨架上填充细节内容

# 从浏览器接收url到开启网络请求线程

这一部分展开的内容是:浏览器进程/线程模型,JS的运行机制

# 多进程的浏览器

浏览器是多进程的,有一个主控进程,以及每一个tab页面都会新开一个进程(某些情况下多个tab会合并进程)

进程可能包括主控进程,插件进程,GPU,tab页(浏览器内核)等等

  • Browser进程:浏览器的主进程(负责协调、主控),只有一个
  • 第三方插件进程:每种类型的插件对应一个进程,仅当使用该插件时才创建
  • GPU进程:最多一个,用于3D绘制
  • 浏览器渲染进程(内核):默认每个Tab页面一个进程,互不影响,控制页面渲染,脚本执行,事件处理等(有时候会优化,如多个空白tab会合并成一个进程)

如下图:

img

# 多线程的浏览器内核

每一个tab页面可以看作是浏览器内核进程,然后这个进程是多线程的,它有几大类子线程

  • GUI线程

  • JS引擎线程

  • 事件触发线程

  • 定时器线程

  • 网络请求线程

    # 本文重点 - 多进程浏览器架构

    不扯以前的旧的浏览器架构,Chrome 浏览器的架构如下图所示(不一定最新)。需要注意的是,像 UI process, Network process 等等这些进程都有可能会被“降级”为 Browser process 的线程(UI thread, Network thread)

    When Chrome is running on powerful hardware, it may split each service into different processes giving more stability, but if it is on a resource-constraint device, Chrome consolidates services into one process saving memory footprint.

img

img img

可以看到,里面的JS引擎是内核进程中的一个线程,这也是为什么常说JS引擎是单线程的

# 解析URL

输入URL后,会进行解析(URL的本质就是统一资源定位符)

URL一般包括几大部分:

  • protocol,协议头,譬如有http,ftp等
  • host,主机域名或IP地址
  • port,端口号
  • path,目录路径
  • query,即查询参数
  • fragment,即#后的hash值,一般用来定位到某个位置

# 网络请求都是单独的线程

每次网络请求时都需要开辟单独的线程进行,譬如如果URL解析到http协议,就会新建一个网络线程去处理资源下载

因此浏览器会根据解析出得协议,开辟一个网络线程,前往请求资源(这里,暂时理解为是浏览器内核开辟的,如有错误,后续修复)

# 更多

由于篇幅关系,这里就大概介绍一个主干流程,关于浏览器的进程机制,更多可以参考以前总结的一篇文章(因为内容实在过多,里面包括JS运行机制,进程线程的详解)

从浏览器多进程到JS单线程,JS运行机制最全面的一次梳理 (opens new window)

# 开启网络线程到发出一个完整的http请求

这一部分主要内容包括:dns查询,tcp/ip请求构建,五层因特网协议栈等等

仍然是先梳理主干,有些详细的过程不展开(因为展开的话内容过多)

# DNS查询得到IP

如果输入的是域名,需要进行dns解析成IP,大致流程:

  • 如果浏览器有缓存,直接使用浏览器缓存,否则使用本机缓存,再没有的话就是用host
  • 如果本地没有,就向dns域名服务器查询(当然,中间可能还会经过路由,也有缓存等),查询到对应的IP

注意,域名查询时有可能是经过了CDN调度器的(如果有cdn存储功能的话)

而且,需要知道dns解析是很耗时的,因此如果解析域名过多,会让首屏加载变得过慢,可以考虑dns-prefetch优化

这一块可以深入展开,具体请去网上搜索,这里就不占篇幅了(网上可以看到很详细的解答)

# tcp/ip请求

http的本质就是tcp/ip请求

需要了解3次握手规则建立连接以及断开连接时的四次挥手

tcp将http长报文划分为短报文,通过三次握手与服务端建立连接,进行可靠传输

三次握手的步骤:(抽象派)

客户端:hello,你是server么?
服务端:hello,我是server,你是client么
客户端:yes,我是client

建立连接成功后,接下来就正式传输数据

然后,待到断开连接时,需要进行四次挥手(因为是全双工的,所以需要四次挥手)

四次挥手的步骤:(抽象派)

主动方:我已经关闭了向你那边的主动通道了,只能被动接收了
被动方:收到通道关闭的信息
被动方:那我也告诉你,我这边向你的主动通道也关闭了
主动方:最后收到数据,之后双方无法通信

tcp/ip的并发限制

浏览器对同一域名下并发的tcp连接是有限制的(2-10个不等)

而且在http1.0中往往一个资源下载就需要对应一个tcp/ip请求

所以针对这个瓶颈,又出现了很多的资源优化方案

get和post的区别

get和post虽然本质都是tcp/ip,但两者除了在http层面外,在tcp/ip层面也有区别。

get会产生一个tcp数据包,post两个

具体就是:

  • get请求时,浏览器会把headersdata一起发送出去,服务器响应200(返回数据),
  • post请求时,浏览器先发送headers,服务器响应100 continue, 浏览器再发送data,服务器响应200(返回数据)。

再说一点,这里的区别是specification(规范)层面,而不是implementation(对规范的实现)

# 五层因特网协议栈

其实这个概念挺难记全的,记不全没关系,但是要有一个整体概念

其实就是一个概念: 从客户端发出http请求到服务器接收,中间会经过一系列的流程。

简括就是:

从应用层的发送http请求,到传输层通过三次握手建立tcp/ip连接,再到网络层的ip寻址,再到数据链路层的封装成帧,最后到物理层的利用物理介质传输。

当然,服务端的接收就是反过来的步骤

五层因特网协议栈其实就是:

1.应用层(dns,http) DNS解析成IP并发送http请求

2.传输层(tcp,udp) 建立tcp连接(三次握手)

3.网络层(IP,ARP) IP寻址

4.数据链路层(PPP) 封装成帧

5.物理层(利用物理介质传输比特流) 物理传输(然后传输的时候通过双绞线,电磁波等各种介质)

当然,其实也有一个完整的OSI七层框架,与之相比,多了会话层、表示层。

OSI七层框架:物理层数据链路层网络层传输层会话层表示层应用层

表示层:主要处理两个通信系统中交换信息的表示方式,包括数据格式交换,数据加密与解密,数据压缩与终端类型转换等

会话层:它具体管理不同用户和进程之间的对话,如控制登陆和注销过程

# 从服务器接收到请求到对应后台接收到请求