您当前的位置:首页 > 计算机 > 软件应用 > 浏览器应用

浏览器的工作机制原理

时间:06-03来源:作者:点击数:

浏览器其实就是一个team,工作很忙很忙,但却井然有序、管理得当,其中既得益于和其他团队的亲密协作,同时也十分注重团队内部每个部门的分工协调。那么这个team日常到底做了哪些工作呢。


团队主要分组

各组主要任务安排:

  • 用户界面组:负责浏览器的工具栏、地址栏、菜单栏,以及页面前进 / 后退按钮的显示,换句话说,除了主界面里访问的页面外,其他部分都是用户界面组的。
  • 浏览器引擎组:负责用户界面和渲染引擎之间的指令通信,提供对渲染引擎的高级接口。
  • 渲染引擎组:负责将url获取到的内容,显示到主界面。
  • 网络组:负责网络请求,比如HTTP请求,为所有平台提供底层实现。
  • 用户界面后端组:负责绘制窗口小部件比如窗口、组合框。
  • JS解释器组:负责解析和执行JavaScript代码。
  • 数据存储组:负责浏览器在硬盘上存储的各种数据,例如cookie,网络数据库。

主管老浏今早心情很好,精力也很充沛,昨天甲方正常关闭了浏览器,晚上没有加班。像之前的时候,甲方的电脑经常开一晚上,浏览器也不关,老浏就得几个晚上连续的加班。到了公司,浏览器还没开。等其他伙伴都齐了,时间也刚好,浏览器一开,大家都已经做好了上班的准备。用户界面组,把已经准备好了初始设定好的主题,地址栏,各种标签、菜单、按钮都呈现出来了,渲染引擎组也把预备好的默认页面渲染了出来,第一份任务完成,大伙送了一口气,浏览器初始化ok了。

这会甲方来需求了,“老浏我给你个url,你帮我访问一下,把结果呈现给我”。
老浏把这个url先给了用户界面组,“需要用你们地址栏,检测一下这个url的字符串是不是写的合格”,用户界面组简单分析了一下,没问题。
“数据存储组,你们有这个url的缓存么?”,数据存储组接过ur回库里查了查。”有缓存,他之前访问过,但是缓存已经过期了,重新请求吧“,这会url就到了网络组的手里。
网络组拿到url后,首先进行DNS域名解析工作。组里刚新来一个实习生,问组里的前辈:”哥,为啥咱们要先做DNS域名解析啊“。”你个笨小子,咋学的。因为啊,地址栏里输入的域名和网络服务器的IP地址是有映射关系的,我们得把这个域名解析成IP地址,然后就找到对应的那个服务器了“。实习生又问了:”那具体怎么请求啊?“,”你是真一点不会啊,看你还挺愿意学的,和你简单说说。我们先在本地hosts文件看看有没有这个网址的映射关系,有就直接调用进行解析,没有的话,再看看那本地DNS解析器有没有缓存,没有再看看本地DNS服务器,如果还找不到就得走迭代查询了,一层一层的去找了。“
正在聊天的过程中,旁边的同时来消息了,找到IP了。这会就要进行有名的三次握手过程了,进行TCP链接。网络组组长拿着IP对实习生说:”这个任务咱们有明确的流程规范,你看看然后去和服务器部门的人去对接一下去“。

TCP三次握手
当建立协议的时候,tcp进行了3次握手:
1、客户端发送了一个带有SYN的Tcp报文到服务器,这个三次握手中的开始。表示客户端想要和服务端建立连
接。主机A发送位码为syn=1,随机产生seq number=1234567的数据包到服务器,主机B由SYN=1知道,
A要求建立联机。
2、服务端接收到客户端的请求,返回客户端报文,这个报文带有SYN和ACK标志,询问客户端是否准备好。 
主机B收到请求后要确认联机信息,向A发送ack number=(主机A的seq+1),syn=1,ack=1,随机产生
seq=7654321的包。
3、客户端再次响应服务端一个ACK,表示我已经准备好。主机A收到后检查ack number是否正确,即第一次
发送的seq number+1,以及位码ack是否为1,若正确,主机A会再发送ack number=(主机B的seq+1),
ack=1,主机B收到后确认seq值与ack=1则连接建立成功。
”沟通好了,已经链接了。开始发起HTTP请求,让服务器部那边处理下请求,接受HTTP响应,一定要按照规范传输过来”。

HTTP请求格式:

请求行(requestline) 请求头部(header) 空行 请求数据

常用请求头部:

Accept: 接收类型,表示浏览器支持的MIME类型
(对标服务端返回的Content-Type)
Accept-Encoding:浏览器支持的压缩类型,如gzip等,超出类型不能接收
Content-Type:客户端发送出去实体内容的类型
Cache-Control: 指定请求和响应遵循的缓存机制,如no-cache
If-Modified-Since:对应服务端的Last-Modified,用来匹配看文件是否变动,只能精确到1s之内,http1.0中
Expires:缓存控制,在这个时间内不会请求,直接使用缓存,http1.0,而且是服务端时间
Max-age:代表资源在本地缓存多少秒,有效时间内不会请求,而是使用缓存,http1.1中
If-None-Match:对应服务端的ETag,用来匹配文件内容是否改变(非常精确),http1.1中
Cookie: 有cookie并且同域访问时会自动带上
Connection: 当浏览器与服务器通信时对于长连接如何进行处理,如keep-alive
Host:请求的服务器URL
Origin:最初的请求是从哪里发起的(只会精确到端口),Origin比Referer更尊重隐私
Referer:该页面的来源URL(适用于所有类型的请求,会精确到详细页面地址,csrf拦截常用到这个字段)
User-Agent:用户客户端的一些必要信息,如UA头部等
”叮叮叮~“,”喂,我是服务器部的,你们的HTTP请求已经收到了,我们把报文封装成Request对象,已经处理完了,我们还是返回给你们Response对象,包含状态码,响应头,响应报文就行对吧“。

状态码:

1xx:指示信息--表示请求已接收,继续处理 
2xx:成功--表示请求已被成功接收、理解、接受 
3xx:重定向--要完成请求必须进行更进一步的操作 
4xx:客户端错误--请求有语法错误或请求无法实现 
5xx:服务器端错误--服务器未能实现合法的请求

常用响应头部:

Access-Control-Allow-Headers: 服务器端允许的请求Headers
Access-Control-Allow-Methods: 服务器端允许的请求方法
Access-Control-Allow-Origin: 服务器端允许的请求Origin头部(譬如为*)
Content-Type:服务端返回的实体内容的类型
Date:数据从服务器发送的时间
Cache-Control:告诉浏览器或其他客户,什么环境可以安全的缓存文档
Last-Modified:请求资源的最后修改时间
Expires:应该在什么时候认为文档已经过期,从而不再缓存它
Max-age:客户端的本地资源应该缓存多少秒,开启了Cache-Control后有效
ETag:请求变量的实体标签的当前值
Set-Cookie:设置和页面关联的cookie,服务器通过这个头部把cookie传给客户端
Keep-Alive:如果客户端有keep-alive,服务端也会有响应(如timeout=38)
Server:服务器的一些相关信息
ok,网络组,忙忙碌碌的,终于完成了任务,下面就该是渲染的部分了。网络组将服务器返回结果给了渲染引擎组。”大家伙,干得好,再接再厉,准备进入主流程“,老浏鼓励到。
渲染引擎组是一个大组,人数是各组最多的,而且还下分好多小组。渲染引擎组组长收到传来的内容一看,心里一震,这次要渲染的内容很多啊,而且几乎没做多少渲染优化,压力很大啊。”哎,虽然这次任务紧,胆子大,但是什么情况咱们没见过,没有压缩的超级大图,没有逐步渲染的骨架,没有按需加载的模块,咱们都抗过来了,这次也没问题”。组长给全组人不断打气。
第一步,先交给DOM小组,你们把HTML内容翻译一下,构建出出来DOM树。
第二步,交给CSS小组,你们构建一下CSS树,你们和DOM小组可以并行工作。
第三步,布局小组的,你们根据DOM组和CSS组产出的DOM树和CSS树,合并一下,产出一个render树。
第四步,布局小组,你们还需要进行分层工作,生成个分层树。
第五步,每一层都要生成单独的绘制列表,然后发给合成线程组。
第六步,合成线程组会根据用户可见区域将图层划分成图块,只有可见部分才会绘制。
第七步,合成线程小组和栅格化线程池小组,你们两组配合一下,通过你们维护的栅格化的线程池这将视口附近的图块经过栅格化,转换成位图。
第八步,合成线程组将触发DrawQuad绘制图块,通知浏览器进程组。

渲染进程
浏览器线程组获取到各层的信息,便会联系GPU,将各层进行复合操作,显示出来。

WebKit 主流程

Mozilla 的 Gecko 呈现引擎主流程
“嗯。。。咱们这里需要优化一下,不能等完整的HTML文件都接受完,再一步一步渲染,应该在接受部分的时候就开始先渲染。”
渲染引擎组还有两个最重要的工作,一个是reflow(回流),一个是回流回流repaint(重绘)。回流指的是元素的内容、结构、位置或尺寸发送变化,需要重新计算样式和布局。重绘指的是元素的变化仅仅是一些不影响布局和结构的属性时,触发的操作。等全部渲染完后,若出现布局变化,会重现触发回流重绘的步骤。
信息接受完了,准备关闭TCP链接,进行四次挥手操作。
当终止协议的时候,tcp进行了4次握手: 由于Tcp连接是进行全双工工作的,因此每个方向都必须单独进行关
闭,这个原则是当一方完成他的数据发送的 时候就发送一个FIN来终止这个方向的连接,收到这个FIN意味着这
个方向上没有数据的流动,一个TCP连接在 收到这个FIN之后还能发送消息,首先执行关闭的一方进行主动的关
闭,而另一方进行被动的关闭。
1、TCP发送一个FIN,用来关闭客户到服务端的连接。
2、服务端收到这个FIN,他发回一个ACK,确认收到序号为收到序号+1,和SYN一样,一个FIN将占用一个序号。
3、服务端发送一个FIN到客户端,服务端关闭客户端的连接。
4、客户端发送ACK报文确认,并将确认的序号 +1,这样关闭完成。
“完美,我们又完成了一次伟大的胜利,没有阻塞,没有延迟,不过之后我们还是需要做下复盘,下次怎么能更快,有哪些需要优化的部分”。老浏流露出喜悦的表情。

整体工作流程

  1. 地址栏输入url,回车。
  2. 浏览器查找是否有本地缓存。
  3. 进行DNS解析url,获取IP地址。
  4. 根据IP进行TCP链接(三次握手)。
  5. 发起HTTP请求。
  6. 服务器接收HTTP请求,处理,并作出HTTP响应。
  7. 主流程渲染。
    1. 构建DOM树。
    2. 构建CSS树。
    3. 构建布局树,并进行分层处理,提交合成线程。
    4. 合成线程将图层划分图块,经过光栅化线程转换成位图。
    5. 合成线程发送回执图块命令DrawQuad给浏览器进程。
    6. 浏览器进程根据DrawQuad消息生成页面,显示出来。
  8. 关闭TCP链接(四次挥手)。
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门