浏览器工作原理与实践--浏览上下文组:如何计算Chrome中渲染进程的个数

经常有朋友问到如何计算Chrome中渲染进程个数的问题,那么今天就来完整地解答这个问题。

在前面“04 | 导航流程”这一讲中我们介绍过了,在默认情况下,如果打开一个标签页,那么浏览器会默认为其创建一个渲染进程。不过我们在“04 | 导航流程”中还介绍了同一站点的概念,如果从一个标签页中打开了另一个新标签页,当新标签页和当前标签页属于同一站点的话,那么新标签页会复用当前标签页的渲染进程。

具体地讲,如果我从极客邦(www.geekbang.org) 的标签页中打开新的极客时间(time.geekbang.org) 标签页,由于这两个标签页属于同一站点(相同协议、相同根域名),所以他们会共用同一个渲染进程。你可以看下面这张Chrome的任务管理器截图:

多个标签页运行在同一个渲染进程

观察上图,我们可以看到,极客邦官网和极客时间标签页都共用同一个渲染进程,该进程ID是84748。

不过如果我们分别打开这两个标签页,比如先打开极客邦的标签页,然后再新建一个标签页,再在这个新标签页中打开极客时间,这时候我们可以看到这两个标签页分别使用了两个不同的渲染进程。你可以参看下图:

多个标签页运行在不同的渲染进程中

那么到了这里,你一定会很好奇,既然都是同一站点,为什么从A标签页中打开B标签页,就会使用同一个渲染进程,而分别打开这两个标签页,又会分别使用不同的渲染进程?

标签页之间的连接

要搞清楚这个问题,我们要先来分析下浏览器标签页之间的连接关系。

我们知道,浏览器标签页之间是可以通过JavaScript脚本来连接的,通常情况下有如下几种连接方式:

第一种是通过<a>标签来和新标签建立连接,这种方式我们最熟悉,比如下面这行代码是从极客邦标签页里面拷贝过来的:

<a  href="https://time.geekbang.org/" target="_blank" class="">极客时间</a>

这是从极客邦官网中打开极客时间的链接,点击该链接会打开新的极客时间标签页,新标签页中的window.opener的值就是指向极客邦标签页中的window,这样就可以在新的极客时间标签页中通过opener来操作上个极客邦的标签页了。这样我们可以说,这两个标签页是有连接的。

另外,还可以通过JavaScript中的window.open方法来和新标签页建立连接,演示代码如下所示:

new_window = window.open("http://time.geekbang.org")

通过上面这种方式,可以在当前标签页中通过new_window来控制新标签页,还可以在新标签页中通过window.opener来控制当前标签页。所以我们也可以说,如果从A标签页中通过window.open的方式打开B标签页,那么A和B标签页也是有连接的。

其实通过上述两种方式打开的新标签页,不论这两个标签页是否属于同一站点,他们之间都能通过opener来建立连接,所以他们之间是有联系的。在WhatWG规范中,把这一类具有相互连接关系的标签页称为浏览上下文组( browsing context group)。

既然提到浏览上下文组,就有必要提下浏览上下文,通常情况下,我们把一个标签页所包含的内容,诸如window对象,历史记录,滚动条位置等信息称为浏览上下文。这些通过脚本相互连接起来的浏览上下文就是浏览上下文组。如果你有兴趣,可以参考下规范文档。

也就是说,如果在极客邦的标签页中,通过链接打开了多个新的标签页,不管这几个新的标签页是否是同一站点,他们都和极客邦的标签页构成了浏览上下文组,因为这些标签页中的opener都指向了极客邦标签页。

Chrome浏览器会将浏览上下文组中属于同一站点的标签分配到同一个渲染进程中,这是因为如果一组标签页,既在同一个浏览上下文组中,又属于同一站点,那么它们可能需要在对方的标签页中执行脚本。因此,它们必须运行在同一渲染进程中。

现在我们清楚了浏览器是怎么分配渲染进程的了,接下来我们就可以来分析文章开头提的那个问题了:

既然都是同一站点,为什么从A标签页中打开B标签页,就会使用同一个渲染进程? 而分别打开这两个标签页,又会分别使用不同的渲染进程?

首先来看第一种,在极客邦标签页内部通过链接打开极客时间标签页,那么极客时间标签页和极客邦标签页属于同一个浏览上下文组,且它们属于同一站点,所以浏览器会将它们分配到同一个渲染进程之中。

而第二种情况就简单多了,因为第二个标签页中并没有第一个标签页中的任何信息,第一个标签页也不包含任何第二个标签页中的信息,所以他们不属于同一个浏览上下文组,因此即便他们属于同一站点,也不会运行在同一个渲染进程之中。下面是我画的计算标签页的流程图,你可以参考下:

计算标签页使用的渲染进程数目

一个“例外”

好了,现在我们清楚了Chrome浏览器为标签页分配渲染进程的策略了:

  1. 如果两个标签页都位于同一个浏览上下文组,且属于同一站点,那么这两个标签页会被浏览器分配到同一个渲染进程中。

  2. 如果这两个条件不能同时满足,那么这两个标签页会分别使用不同的渲染进程来渲染。

现在你可以想一下,如果从A标签页中打开B标签页,那我们能肯定A标签页和B标签页属于同一浏览上下文组吗?

答案是“不能”,下面我们就来看个例子,在“04 | 导航流程”的留言区中,ID为“芳华年月”的朋友就提出了这样的一个问题:

请问老师,https://linkmarket.aliyun.com内新开的标签页都是新开一个渲染进程,能帮忙解释下吗?

我们先来复现下“芳华年月”所描述的现象,首先打开linkmarket.aliyun.com这个标签页,再在这个标签页中随便点击两个链接,然后就打开了两个新的标签页了,如下图所示:

“例外”情况

我通过A标签页中的链接打开了两个新标签页,B和C,而且我们也可以看出来,A、B、C三个标签页都属于同一站点,正常情况下,它们应该共用同一个渲染进程,不过通过上图我们可以看出来,A、B、C三个标签页分别使用了三个不同的渲染进程。

既然属于同一站点,又不在同一个渲染进程中,所以可以推断这三个标签页不属于同一个浏览上下文组,那么我们接下来的分析思路就很清晰了:

  1. 首先验证这三个标签页是不是真的不在同一个浏览上下文组中;

  2. 然后再分析它们为什么不在同一浏览上下文组。

为了验证猜测,我们可以通过控制台,来看看B标签页和C标签标签页的opener的值,结果发现这两个标签页中的opener的值都是null,这就确定了B、C标签页和A标签页没有连接关系,当然也就不属于同一浏览上下文组了。

验证了猜测,接下来的我们就是来查查,阿里的这个站点是不是采用了什么特别的手段,移除了这两个标签页之间的连接关系。

我们可以看看实现链接的HTML文件,如下图所示:

链接使用了rel = noopener

通过上图,我们可以发现,a链接的rel属性值都使用了noopener 和 noreferrer,通过noopener,我们能猜测得到这两个值是让被链接的标签页和当前标签页不要产生连接关系。

通常,将noopener的值引入rel属性中,就是告诉浏览器通过这个链接打开的标签页中的opener值设置为null,引入noreferrer是告诉浏览器,新打开的标签页不要有引用关系。

好了,到了这里我们就知道了,通过linkmarket.aliyun.com标签页打开新的标签页要使用单独的一个进程,是因为使用了rel= noopener的属性,所以新打开的标签页和现在的标签页就没有了引用关系,当然它们也就不属于同一浏览上下文组了。这也同时解答了“芳华年月”所提出的问题。

站点隔离

上面我们都是基于标签页来分析渲染进程的,不过我在“35|安全沙箱”中介绍过了,目前Chrome浏览器已经默认实现了站点隔离的功能,这意味着标签页中的iframe也会遵守同一站点的分配原则,如果标签页中的iframe和标签页是同一站点,并且有连接关系,那么标签页依然会和当前标签页运行在同一个渲染进程中,如果iframe和标签页不属于同一站点,那么iframe会运行在单独的渲染进程中。

我们先来看下面这个具体的例子吧:

<head><title>站点隔离:demo</title><style>iframe {width: 800px;height: 300px;}</style>
</head>
<body><div><iframe src="iframe.html"></iframe></div><div><iframe src="https://www.infoq.cn/"></iframe></div><div><iframe src="https://time.geekbang.org/"></iframe></div><div><iframe src="https://www.geekbang.org/"></iframe></div>
</body>
</html>

在Chrome浏览器中打开上面这个标签页,然后观察Chrome的任务管理,我们会发现这个标签页使用了四个渲染进程,如下图所示:

iframe使用单独的渲染进程

结合上图和HTML代码,我们可以发现,由于InfoQ、极客邦两个iframe与父标签页不属于同一站点,所以它们会被分配到不同的渲染进程中,而iframe.html和源标签页属于同一站点,所以它会和源标签页运行在同一个渲染进程中。下面是我画的计算iframe使用渲染进程数目的流程图,你可以对照着参考下:

计算iframe所使用的渲染进程数目

总结

好了,本节的内容就介绍到这里,下面我来总结下本文的主要内容:

首先我们使用了两种不同的方式打开两个标签页,第一种是从A标签页中通过链接打开了B标签页,第二种是分别打开A和B标签页,这两种情况下的A和B都属于同一站点。

通过Chrome的任务管理器我们发现,虽然A标签页和B标签页都属于同一站点,不过通过第一种方式打开的A标签页和B标签页会共用同一个渲染进程,而通过第二种方式打开的两个标签页却分别使用了两个不同的渲染进程。

这是因为,使用同一个渲染进程需要满足两个条件:首先A标签页和B标签页属于同一站点,其次A标签页和B标签页需要有连接关系。

接着,我们分析了一个“例外”,如果在链接中加入了rel=noopener属性,那么通过链接打开的新标签页和源标签页之间就不会建立连接关系了。

最后我们还分析了站点隔离对渲染进程个数的影响,如果A标签页中的iframe和A标签页属于同一站点,那么该iframe和A标签页会共用同一个渲染进程,如果不是,则该iframe会使用单独的渲染进程。

好了,到了这里相信你已经会计算渲染进程的个数了。

在最后我们还要补充下同源策略对同一站点的限制,虽然Chrome会让有连接且属于同一站点的标签页运行在同一个渲染进程中,不过如果A标签页和B标签页属于同一站点,却不属于同源站点,那么你依然无法通过opener来操作父标签页中的DOM,这依然会受到同源策略的限制。

简单地讲,极客邦和极客时间属于同一站点,但是他们并不是同源的,因为同源是需要相同域名的,虽然根域名geekbang.org相同,但是域名却是不相同的,一个是time.geekbang.org,一个是www.geekbang.org, 因此浏览器判断它们不是同源的,所以依然无法通过time.geekbang.org标签页中的opener来操作www.geekbang.org中的DOM。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/542.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Echarts-知识图谱

Echarts-知识图谱 demo地址 打开CodePen 效果 思路 1. 生成根节点 2. 根据子节点距离与根节点的角度关系&#xff0c;生成子节点坐标&#xff0c;进而生成子节点 3. 从子节点上按角度生成对应的子节点 4. 递归将根节点与每一层级子节点连线核心代码 定义节点配置 functio…

基于springboot实现车辆管理系统设计项目【项目源码+论文说明】计算机毕业设计

基于springboot实现车辆管理系统演示 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了车辆管理系统的开发全过程。通过分析车辆管理系统管理的不足&#xff0c;创建了一个计算机管理车辆管理系统的方案。文章介…

黑洞路由、 DDoS 攻击 、 环路

黑洞路由 DDoS 攻击 DDoS 攻击是一种针对服务器、服务或网络的恶意行为。DDoS 攻击通过向目标发送大量流量&#xff0c;使其不堪重负&#xff0c;导致资源和带宽被耗尽。因此&#xff0c;目标可能会变慢或崩溃&#xff0c;无法正常处理合法的流量。DDoS 攻击通常是由僵尸网络…

在龙梦迷你电脑福珑2.0上使用Fedora 28 龙梦版

在龙梦迷你电脑福珑2.0上使用Fedora 28 龙梦版。这个版本的操作系统ISO文件是&#xff1a;Fedora28_for_loongson_MATE_Live_7.2.iso 。它在功能方面不错。能放音乐&#xff0c;能看cctv直播&#xff0c;有声音&#xff0c;能录屏&#xff0c;能在局域网里用PuTTY的ssh方式连接…

《苏东坡 传》一蓑烟雨任平生

《苏东坡 传》一蓑烟雨任平生 林语堂&#xff0c;中国现代著名作家、学者、翻译家、语言学家。 张振玉 译 文章目录 《苏东坡 传》一蓑烟雨任平生[toc]摘录小结感悟 摘录 苏东坡是个秉性难改的乐天派&#xff0c;是悲天悯人的道德家&#xff0c;是黎民百姓的好朋友&#xff0c;…

C语言C/S架构PACS影像归档和通信系统源码 医院PACS系统源码

C语言C/&#xff33;架构PACS影像归档和通信系统源码 医院PACS系统源码 医院影像科PACS系统&#xff0c;意为影像归档和通信系统。它是应用在医院影像科室的系统&#xff0c;主要的任务是把日常产生的各种医学影像&#xff08;包括核磁、CT、超声、各种X光机、各种红外仪、显微…

JAVA ASM总结篇-03

MethodVisitor ClassVisitor的visitMethod能够访问到类中某个方法的一些入口信息&#xff0c;那么针对具体方法中字节码的访问是由MethodVisitor来进行的 访问顺序如下&#xff0c;其中visitCode和visitMaxs仅调用一次&#xff0c;标志方法字节码访问的开始和结束 MethodVisi…

不羁联盟怎么参与测试 不羁联盟测试时间+参与测试方法分享

不羁联盟怎么参与测试 不羁联盟测试时间参与测试方法分享 《不羁联盟》是由育碧&#xff08;Ubisoft&#xff09;开发的一款6v6团队合作射击游戏。游戏的背景设定在一个后启示录时代的废土世界中&#xff0c;玩家能够身临其境地感受到废土世界的荒凉和残酷。游戏在内测时候就受…

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台级联时,下级平台未发流是什么原因?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

AUTOCAD输出或打印PDF文件时,如何将图形居中且布满图纸?

AUTOCAD输出或打印PDF文件时,如何将图形居中且布满图纸? 如下图所示,我们打开一份DWG格式的图纸文件,然后点击上方的“打印“图标, 如下图所示, 打印机/绘图仪这里选择“DWG To PDF“; 图纸尺寸:这里以普通的A4纸为例进行说明; 打印比例选择“布满图纸“; 打印偏移…

优维应用级数字化架构管理:让企业运维天堑变通途

在优维科技的产品视角中&#xff0c;数字化架构管理就像是一门精妙的艺术&#xff0c;它将上层应用模型的业务概念以可视化的方式呈现出来&#xff0c;使得业务逻辑和流程变得更加直观、清晰。我们将这样的管理方式理解为“给企业搭起一座桥梁”——在这座桥梁的搭建过程中&…

express服务器 authorization 前端获取不到的问题

服务器生成token 设置在响应头&#xff0c;但是前端获取不到 const token JWT.generate({ id: new Date().getTime(), userName }, 10s) res.header(Authorization, token) axios.interceptors.response.use((response) > {console.log(response);if (response.data?.co…

破解费用管理迷局,企业费用管理从不止于报销

数字化变革浪潮下&#xff0c;各种企业费用报销软件如雨后春笋般不断涌现&#xff0c;企业报销效率大幅提升&#xff0c;部分财务处理流程得到固化和优化&#xff0c;报销早已不再是企业费时费力的财务难题。那么&#xff0c;企业费用管里如何实现呢&#xff1f; 企业费用贯穿于…

ubuntu上安装调试SVN服务

刚成立团队需要临时搭建一台SVN服务器&#xff0c;所以对照网上的一些提示做了下&#xff0c;操作起来不复杂&#xff0c;还是踩了不少坑&#xff0c;顺便原理性了解了下。 主要操作步骤如下&#xff1a; 1&#xff1a;安装svn sudo apt-get install subversion 2: 创建svn版…

NVIDIA智算中心“产品”上市,AI工业革命的iPhone时刻

GTC 2024落下帷幕了&#xff0c;但这个大会的信息仍在AI产业和经济中发酵。咨询机构WIKIBON认为&#xff0c;GTC 2024在整个科技史中的意义超过了当年史蒂夫乔布斯的iPod和iPhone发布。在AI将永久改变人类的共识下&#xff0c;GTC 2024在广度、愿景、生态系统等方面都有着深远影…

Nacos注册中心的使用

一&#xff1a;服务注册 步骤如下&#xff1a; 引入依赖 配置Nacos地址 重启 1、添加依赖 在需要注册的项目的pom.xml中添加依赖&#xff1a; <!--nacos 服务注册发现--> <dependency><groupId>com.alibaba.cloud</groupId><artifactId>s…

利用Python进行大规模数据处理【第173篇—数据处理】

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 利用Python进行大规模数据处理&#xff1a;Hadoop与Spark的对比 随着数据量的不断增长&…

ros仿真启动小龟

1.启动RosMaster&#xff08;管理Ros中各个节点的“大管家”&#xff0c;每次启动Ros时需要首先启动RosMaster&#xff09; roscorefangfang-inspiron-5580:~/ros2/download/rosdistro$ roscore ... logging to /home/fang/.ros/log/6ec2d790-fe1d-11ee-aba8-1c1bb5cdec7c/ros…

java多线程-线程通信

简介 最常见的模式&#xff1a;生产者-消费者模式 线程通信模型 常见API 生产者抢到资源&#xff0c;生成资源&#xff0c;自己进入等待&#xff0c;唤醒消费者消费者抢到资源&#xff0c;消费数据&#xff0c;自己进入等待&#xff0c;唤醒生产者 定义容器 定义一个容器&#…

python/pygame 挑战魂斗罗 笔记(二)

一、建立地面碰撞体&#xff1a; 现在主角Bill能够站立在游戏地图的地面&#xff0c;是因为我们初始化的时候把Bill的位置固定了self.rect.y 250。而不是真正的站在地图的地面上。 背景地图是一个完整的地图&#xff0c;没有地面、台阶的概念&#xff0c;就无法通过碰撞检测来…