作者:前端学苑 公号 / 前端小贾 (本文来自作者投稿)

编者荐语

性能是前端编码规范、网络层面、辅助工具等相互作用的结果。

这是一个兼顾广度和深度的问题,优化好了可以加快首屏加载速度提高用户留存率,节省服务器资源降低成本等,也是区分初高级前端工程师的重要标准。

本文重点

  • 掌握HTTP报文及其在实践中的运用
  • 掌握浏览器中的“强缓存” 和 “协商缓存”
  • 掌握TCP三次握手和四次挥手的运行机制及意义
  • 掌握HTTP1.0/1.1/2.0之间的区别

为了把HTML、CSS和JavaScript转化成活灵活现、绚丽多彩的网页,浏览器需要处理一系列的中间过程。

优化性能其实就是了解这个过程中发生了什么

即CRP(Critical Rendering Path,关键渲染路径)

从输入 URL 到页面展示,这中间发生了什么?

1)URL解析
2)缓存检查
3)DNS 解析:将域名解析成 IP 地址;
4)TCP 连接:TCP 三次握手;
5)发送 HTTP 请求;
6)服务器处理请求并返回 HTTP 的报文;
7)浏览器解析渲染页面;
8)断开连接:TCP 四次挥手;

整个过程的关键点展开的说一下。

URL解析

1、地址解析

HTTP 是明文传输协议,连接简单,是无状态的。

HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 HTTP 协议安全。

端口号:HTTP  80,HTTPS  443。FTP 21

2、编码(面试常问)

encodeURI  编码/ decodeURI 解码

对整个URL的编码:处理空格/中文...

var uriStr = "http://www.baidu.com?name=张三&num=001 zs";var uriec = encodeURI(uriStr);document.write("编码后的" + uriec);编码后的http://www.baidu.com?name=%E5%BC%A0%E4%B8%89&num=001%20zs

var uridc = decodeURI(uriec);document.write("解码后的" + uridc);解码后的http://www.baidu.com?name=张三&num=001 zs

encodeURIComponent / decodeURIComponent

主要对传递的参数信息编码

let url = `http://www.jb51.net/api/?lx=1&name=${encodeURIComponent("前端学苑")}&from=${encodeURIComponent("http://www.baidu.com/")}`

结果:http://www.jb51.net/api/?lx=1&name=%E5%89%8D%E7%AB%AF%E5%AD%A6%E8%8B%91&from=http%3A%2F%2Fwww.baidu.com%2F

URI / URL / URN

(1)URI统一资源标识符,用来唯一的标识一个资源。
(2)URL统一资源定位器,它是一种具体的URI,即URL可以用来标识一个资源,
而且还指明了如何locate这个资源。
(3)URN统一资源命名,是通过名字来标识资源,比如mailto:java-net@java.sun.com。

缓存检查

缓存检测:产品性能优化的重要手段。

缓存位置:

1)Memory Cache : 内存缓存
2)Disk Cache:硬盘缓存

补充回答:(面试常问)

1)打开网页:查找 disk cache 中是否有匹配,如有则使用,如没有则发送网络请求。
2)普通刷新:因TAB没关闭,因此memory cache是可用的,会被优先使用,其次才是disk cache。
3)强制刷新:浏览器不使用缓存,因此发送的请求头部均带有 Cache-control: no-cache,服务器直接返回 200 和最新内容。

说明:页面刷新的情况:先看有没有内存,如果没有走硬盘。页面重新加载:直接走硬盘。

注: html 页面一般不做强缓存:每一次html的请求都是正常的HTTP请求。

缓存方式

  • 强缓存(Expires / Cache-Control)
  • 协商缓存(Last-Modified / ETag)

强缓存

强缓存 Expires / Cache-Control浏览器对于强缓存的处理:根据第一次请求资源时返回的响应头来确定的。

1)Expires: 缓存过期时间,用来指定资源到期的时间(HTTP/1.0)

2)Cache-Control: cache-control: max-age=2592000第一次拿到资源后的2592000秒内(30天),再次发送请求,读取缓存中的信息(HTTP/1.1)。

3)两者同时存在的话,Cache-Control优先级高于Expires

强缓存流程导图

补充回答:(面试常问)

强缓存问题,如果服务器文件更新了,但是本地还是有缓存,这样不就拿不到最新的信息了吗?

处理方式:

1)服务器更新资源后,让资源名称和之前不一样,这样页面导入全新的资源。

例如:

index.abc.jsindex.cde.js

处理结果:webpack hash name。

2)当文件更新后,我们在html导入的时候,设置一个后缀[时间戳]

例如:

<script src="index.js?123456"><script src="index.js?234234">

处理结果:随机码或时间戳。

协商缓存

协商缓存与强缓存区别:协商缓存总会和服务器协商,所以一定要发HTTP请求的。

协商缓存 Last-Modified / ETag协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。

协商缓存流程导图

补充回答:

第一次向服务器发送请求

协商缓存缓存没有,向服务器发送请求 (没有传递任何的标识);

服务器收到请求准备内容;

last-modified: 资源文件最后更新的时间;

ETag:记录的是一个标识 (也是根据资源文件更新生成的,每一次资源更新都会重新生成一个 ETag);

说明:客户端拿到信息后渲染,把信息和标识缓存到本地。

第二次发请求

if-Modified-Since = Last-Modified 值if-None-Match = ETag 值
给服务器;

说明:服务器根据标识判断文件是否更新。

扩展问题:

1)304时,本地缓存文件丢失了怎么办?会向服务器再发请求 ,获取最新的数据。

2)什么情况下强缓存协商缓存都要设置?一般情况下都需要设置的。

3)强缓存与协商缓存策略,针对于我们的静态资源文件,而且是不经常更新的。

数据缓存

数据缓存流程导图

cookie 和 session 区别 (面试常问)

1)cookie数据存放在客户的浏览器上,session数据放在服务器上。

2)cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session

3)session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie

4)单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie

5)可以考虑将登陆信息等重要信息存放为session,其他信息如果需要保留,可以放在cookie中。

DNS解析

在地址栏输入的域名并不是最后资源所在的真实位置,域名只是与IP地址的一个映射。

DNS域名解析有两种方法:递归查询迭代查询

首先走递归查询:主机向本地域名服务器的查询采用递归查询。


其次走迭代查询:本地域名服务器向根域名服务器的查询采用迭代查询。


每一次DNS解析时间预计在20\~120毫秒

1)减少DNS请求次数

2)DNS预获取(DNS Prefetch)

<meta http-equiv="x-dns-prefetch-control" content="on"><link rel="dns-prefetch" href="//static.360buyimg.com"/><link rel="dns-prefetch" href="//misc.360buyimg.com"/><link rel="dns-prefetch" href="//img10.360buyimg.com"/><link rel="dns-prefetch" href="//d.3.cn"/><link rel="dns-prefetch" href="//d.jd.com"/>

服务器拆分的优势

1)资源的合理利用;
2)抗压能力加强;
3)提高HTTP并发;

TCP三次握手

TCP三次握手,建立连接通道

1) 客户端发送一个 SYN (标志)码给服务器,要求建立数据连接。(第一次握手,由浏览器发起,告诉服务器我要发送请求了)

2) 服务器SYN和自己处理一个SYN (标志);叫SYN+ACK (确认包);发送给客户端,可以建立连接。(第二次握手,由服务器发起,告诉浏览器我准备接受了,你赶紧发送吧)

3) 客户端再次发送ACK向服务器,服务器验证 ACK 没问题,建立连接。(第三次握手,由浏览器发送,告诉服务器,我马上就发了,准备接受吧)

  • seq序号,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记;

  • ack确认序号,只有ACK标志位为1时,确认序号字段才有效,ack=seq+1;

  • 标志位

ACK:确认序号有效

RST:重置连接

SYN:发起一个新连接

FIN:释放一个连接

TCP三次握手流程导图

三次握手为什么不用两次,或者四次? (面试常问)

TCP作为一种可靠传输控制协议,其核心思想:既要保证数据可靠传输,又要提高传输的效率!

数据传输

HTTP请求报文与响应报文格式

请求报文包含:

  • 请求行:包含请求方法、URI、HTTP版本信息;
  • 请求头;
  • 请求体。

响应报文包含:

  • 响应行:包含HTTP版本、状态码、状态码的原因短语;
  • 响应头
  • 响应体

HTTP Request Header 常见的请求头:

1)Accept: 浏览器能够处理的内容类型  application/json, text/javascript, /; q=0.01

2)Accept-Charset: 浏览器能够显示的字符集

3)Accept-Encoding: 浏览器能够处理的压缩编码 gzip  application/json, text/javascript, /; q=0.01

4)Accept-Language: 浏览器当前设置的语言 zh-CN,zh;q=0.9,en;q=0.8

5)Connection: 浏览器与服务器之间连接的类型 keep-alive

6)Cookie: 当前页面设置的任何 Cookie

7)Host: 发出请求的页面所在的域  www.baidu.com

8)Referer: 发出请求的页面的URL

9)User-Agent: 浏览器的用户代理字符串

HTTP Responses Header常见响应头:

1)Date: 表示消息发送的时间,时间的描述格式由rfc822定义

2)server: 服务器名字

3)Connection: 浏览器与服务器之间连接的类型

4)content-type: 表示后面的文档属于什么MIME类型

5)Cache-Control: 控制HTTP缓存

HTTP 状态码 (面试常问)

101: 切换协议

200: 请求被正常处理

206: 客户端只是请求资源的一部分,服务器只对请求的部分资源执行GET方法,相应报文中通过Content-Range指定范围的资源。(视频大小)

301: 永久性重定向

302: 临时重定向

304: 发送附带条件的请求时,条件不满足时返回,与重定向无关 (用于缓存控制)

307: 协商缓存

400: 请求无效

401: 请求需要认证

403: 服务器已经得到请求,但是拒绝执行

404: 服务器无法找到对应资源

500: 服务器内部错误

502: 网关错误

503: 服务器正忙

TCP四次挥手

1)客户端发送 FIN (结束)报文,通知服务器数据已经传输完毕;(第一次挥手:由浏览器发起的,发送给服务器,我请求报文发送完了,你准备关闭吧) 用来关闭Client到Server的数据传送。

2)服务器接收到之后,通知客户端我收到了SYN,发送ACK(确认)给客户端,数据还没有传输完成。(第二次挥手:由服务器发起的,告诉浏览器,我请求报文接受完了,我准备关闭了,你也准备吧)

3)服务器已经传输完毕,再次发送FIN通知客户端,数据已经传输完毕;(第三次挥手:由服务器发起,告诉浏览器,我响应报文发送完了,你准备关闭吧) 用来关闭Server到Client的数据传送

4)客户端再次发送ACK,进入TIME\_WAIT状态,服务器和客户端关闭连接。(第四次挥手:由浏览器发起,告诉服务器,我的响应报文接受完了,我准备关闭了,你也准备吧)

TCP四次挥手流程导图

为什么连接的时候是三次握手,关闭的时候却是四次握手?(面试常问)

1)服务器端收到客户端的SYN连接请求报文后,可以直接发送SYN+ACK报文。

2)但关闭连接时,当服务器端收到FIN报文时,很可能并不会立即关闭链接,所以只能先回复一个ACK报文,告诉客户端:”你发的FIN报文我收到了”,只有等到服务器端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送,故需要四步握手。

Connection: keep-alive

当使用Keep-Alive模式时,Keep-Alive功能使 客户端到服务器端的连接持续有效,对服务器的后继请求时,Keep-Alive功能避免了建立或者重新建立连接。

通过使用keep-alive机制,可以减少tcp连接建立次数,也意味着可以减少TIME_WAIT状态连接,以此提高性能和提高httpd服务器的吞吐率 (更少的tcp连接意味着更少的系统内核调用,socket的accept()和close()调用)。

HTTP版本间的对比

HTTP1.0和HTTP1.1的一些区别

1)缓存处理

HTTP1.0中主要使用 Last-Modified,Expires 来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略:ETag,Cache-Control…

2)带宽优化及网络连接的使用

HTTP1.1支持断点续传,即返回码是206(Partial Content)

3)错误通知的管理

HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除…

4)Host头处理

HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)

5)长连接

HTTP1.1中默认开启Connection:keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。

HTTP2.0和HTTP1.X相比的新特性

1)新的二进制格式(Binary Format)

HTTP1.x的解析是基于文本,基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合,基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。

2)header压缩

HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。

3)服务端推送(server push)

例如我的网页有一个sytle.css的请求,在客户端收到sytle.css数据的同时,服务端会将sytle.js的文件推送给客户端,当客户端再次尝试获取sytle.js时就可以直接从缓存中获取到,不用再发请求了

// 通过在应用生成HTTP响应头信息中设置Link命令

Link: styles.css>; rel=preload; as=style, </example.png>; rel=preload; as=image

4)多路复用(MultiPlexing)

  • HTTP/1.0  每次请求响应,建立一个TCP连接,用完关闭
  • HTTP/1.1 「长连接」 若干个请求排队串行化单线程处理,后面的请求等待前面请求的返回才能获得执行机会,一旦有某请求超时等,后续请求只能被阻塞,毫无办法,也就是人们常说的线头阻塞;
  • HTTP/2.0 「多路复用」多个请求可同时在一个连接上并行执行,某个请求任务耗时严重,不会影响到其它连接的正常执行;

感谢大家

如果你觉得这篇内容对你挺有启发,我想邀请你帮我三个小忙:

  1. 点个「在看」,让更多的人也能看到这篇内容(喜欢不点在看,都是耍流氓 -_-)
  2. 欢迎加我微信「Augenstern9728」一起交流学习...
  3. 关注公众号「前端时光屋」,持续为你推送精选好文。

http发送16进制报文_HTTP系列探索HTTP网络层的”前端性能优化“相关推荐

  1. [计算机网络]java 实现 udp 通信发送 16 进制报文

    最近有个项目,需要根据卡号生成韦根信号,然后发送给韦根转换器,再让韦根转换器把我发送的内容解析成韦根信号 用的韦根转换器是这家公司的: 韦根26转网络维根转TCP/网络转韦根26TCP转维根 根据人家 ...

  2. http发送16进制报文_阿里云物联网平台使用心得(25)MQTT协议详解UNSUBSCRIBE报文...

    题目 大家好,超子又和大家见面了,超子我能力有限,水平不高,有什么错误的地方,欢迎板砖.超子今天给大家介绍一下UNSUBSCRIBE报文. UNSUBSCRIBE报文 从上图中可知,UNSUBSCRI ...

  3. http发送16进制报文_图解HTTP 第三章HTTP报文内的HTTP信息

    1.HTTP报文 1).报文首部 服务器或客户端需处理的请求或响应的内容及属性 2)空行 16进制  0x0a 16进制 0x0d CR(Carriage Return,回车)'\n' LF(Line ...

  4. java串口发送16进制数据_MFC串口通信发送16进制数据的方法

    本文实例为大家分享了MFC串口通信发送16进制数据的具体代码,供大家参考,具体内容如下 MFC串口通信会使用m_mscomm控件. 发送数据一般是在edit control 里输入自己想发送的内容,然 ...

  5. 使用串口调试助手发送16进制数

    发送16进制的1(即0x01),应该写01,不能去掉前面的0,更不能写成0x01

  6. matlab上位机串口通信中如何发送16进制数,而不是当做ASCII字符发送(已实测成功)

    转载 (找了很长时间,朋友帮忙找到了发送方法) https://zhidao.baidu.com/question/383761631.html 用matlab发送16进制数据,可以用fwrite直接 ...

  7. 串口调试助手 发送16进制与现实16进制数据

    话不多说,直接干货. 使用串口助手发送16进制数据: 如图所示:第一步,选中16进制发送. 第二步:输入你要发送的数据(所有的16进制数据去掉0x符号) 第三步:点击16进制显示 第四步:查看返回值 ...

  8. esp32的uart串口发送16进制通信指令调用实例

    esp32的uart串口发送16进制通信指令调用实例 简介 最近想用esp32通过uart发送的16进制指令来控制一个语言播放模块,记录一下调用uart的过程,请大佬斧正.比较愚笨,过程中踩了很多坑, ...

  9. python socket发送16进制数据_Python UDP Socket 16进制数据发送

    注:此篇文章首次发表于我的一篇CSDN博客里边,现转载于此. 今天琢磨了一下Python UDP Socket 16进制数据发送. 原以为UDP发送和接受的都是字符,怎么能够发送16进制?但细想,其实 ...

最新文章

  1. RK3288 双屏异显,两屏默认方向不一致
  2. c# string 占位符_C# 基础知识系列- 9 字符串的更多用法(一)
  3. 内存泄露、内存溢出以及解决方法
  4. 现代通用计算机的雏,1834年巴贝奇设计的( )是现代通用计算机的雏形 答案:分析机...
  5. vim 配置_「go」 配置vim用于go 开发
  6. python 函数可以作为容器对象的元素_14、函数对象和闭包
  7. 错误解决:当前目录下有so,提示 error while loading shared libraries
  8. python自动发帖源码_Python3实现的 自动发帖小工具 -电脑资料
  9. JAVA实现Word转Pdf文件
  10. 微信公众号获得城市及街道位置信息
  11. 机器翻译与人工智能研究报告(2018年第五期)
  12. Windform c# pictureBox 更换背景图片
  13. 安全专业委员会发言_企业安全委员会发言
  14. ECMAScript 简介
  15. 炔烃/NH2/COOH/NHS ester/N3/酰胫/马来酰亚胺/四嗪/DBCO/C12/鬼笔环肽等基团修饰BODIPY558/568
  16. week6 day4 并发编程之多线程 理论
  17. [python]的functools.partial(偏函数)
  18. 计算机图形学--扫描线填充算法
  19. nmap常用命令有哪些
  20. 如何防止别人利用我的邮箱大量发垃圾邮件

热门文章

  1. CSDN公众号新功能上线,居然还能搜出小姐姐???(文末有福利)
  2. 程序员的年龄越大编程能力越弱???原来我们都理解错了
  3. 确认!别再相信Python了! 程序员:就你敢说...
  4. 使用云原生buildpacks将你的代码转换成Docker Image | 技术干货
  5. Docker精华问答 | 数据库为什么不适合放在 Docker 中运行?
  6. 强推!盘点阿里巴巴 15 款开发者工具 | 程序员硬核评测
  7. ajax异步同步加载PHP代码,jquery中的ajax同步和异步详解
  8. neon浮点运算_ARM 浮点运算详解
  9. python 多线程 廖雪峰_python中多线程与多进程中的数据共享问题
  10. oracle升级后出现 ora-02055,分布式更新失败 0ra-02055错误 请各位指点(在线等待)...