HTTP常见面试题
- 1.HTTP有哪些方法?这些方法的具体作⽤是什么?
- 2.GET和POST有什么区别?
- 3.PUT和POST都是给服务器发送新增资源,有什么区别?
- 4.PUT和PATCH都是给服务器发送修改资源,有什么区别?
- 5. 如何理解 URI?
- 5.http的请求报⽂是什么样的?
- 6.http的响应报⽂是什么样的?
- 7.聊⼀聊HTTP的部⾸有哪些?
- 聊⼀聊HTTP的状态码有哪些?
- 005: 简要概括一下 HTTP 的特点?HTTP 有哪些缺点?
- 008: HTTP 如何处理大文件的传输?
- 009: HTTP 中如何处理表单数据的提交?
- HTTP的keep-alive是⼲什么的?
- 7.说说http https的区别,https如何保证安全的?
- HTTP2相对于HTTP1.x有什么优势和特点?
- HTTP的缓存的过程是怎样的?
- 推荐阅读
1.HTTP有哪些方法?这些方法的具体作⽤是什么?
方法
- HTTP1.0定义了三种请求⽅法: GET, POST 和 HEAD⽅法
- HTTP1.1新增了五种请求⽅法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT
作用
- GET: 通常⽤于请求服务器发送某些资源
- HEAD: 请求资源的头部信息, 并且这些头部与 HTTP GET ⽅法请求时返回的⼀致。该请求⽅法的⼀个使⽤场景是在下载⼀个⼤⽂件前先获取其⼤⼩再决定是否要下载, 以此可以节约带宽资源
- OPTIONS: ⽤于获取⽬的资源所⽀持的通信选项
- POST: 发送数据给服务器
- PUT: ⽤于新增资源或者使⽤请求中的有效负载替换⽬标资源的表现形式
- DELETE: ⽤于删除指定的资源
- PATCH: ⽤于对资源进⾏部分修改
- CONNECT: HTTP/1.1协议中预留给能够将连接改为管道⽅式的代理服务器
- TRACE: 回显服务器收到的请求,主要⽤于测试或诊断
2.GET和POST有什么区别?
- 数据传输方式不同:GET请求通过URL传输数据,⽽POST的数据通过请求体传输。
- 安全性不同:POST的数据因为在请求主体内,所以有⼀定的安全性保证,⽽GET的数据在URL中,通过历史记
录,缓存很容易查到数据信息。 - 数据类型不同:GET只允许 ASCII 字符,⽽POST⽆限制
- GET无害: 刷新、后退等浏览器操作GET请求是⽆害的,POST可能重复提交表单
- 特性不同:GET是安全(这⾥的安全是指只读特性,就是使⽤这个⽅法不会引起服务器状态变化)且幂等(幂等的
概念是指同⼀个请求⽅法执⾏多次和仅执⾏⼀次的效果完全相同),⽽POST是⾮安全⾮幂等
或者这样回答
首先最直观的是语义上的区别。
而后又有这样一些具体的差别:
- 从缓存的角度,GET 请求会被浏览器主动缓存下来,留下历史记录,而 POST 默认不会。
- 从编码的角度,GET 只能进行 URL 编码,只能接收 ASCII 字符,而 POST 没有限制。
- 从参数的角度,GET 一般放在 URL 中,因此不安全,POST 放在请求体中,更适合传输敏感信息。
- 从幂等性的角度,GET是幂等的,而POST不是。(幂等表示执行相同的操作,结果也是相同的)
- 从TCP的角度,GET 请求会把请求报文一次性发出去,而 POST 会分为两个 TCP 数据包,首先发 header 部分,如果服务器响应100(continue), 然后发 body 部分。(火狐浏览器除外,它的 POST 请求只发一个 TCP 包)
3.PUT和POST都是给服务器发送新增资源,有什么区别?
PUT 和POST⽅法的区别是,
- PUT⽅法是幂等的,⽽POST⽅法是⾮幂等的。幂等连续调⽤⼀次或者多次的效果相同(⽆副作⽤)
- 通常情况下,PUT的URI指向是具体单⼀资源,⽽POST可以指向资源集合。
举个例⼦,我们在开发⼀个博客系统,当我们要创建⼀篇⽂章的时候往往⽤ POSThttps://www.jianshu.com/articles
,这个请求的语义是,在articles的资源集合下创建⼀篇新的⽂章,如果我们多次提交这个请求会创建多个⽂章,这是⾮幂等的。⽽ PUT https://www.jianshu.com/articles/820357430
的语义是更新对应⽂章下的资源(⽐如修改作者名称等),这个URI指向的就是单⼀资源,⽽且是幂等的,⽐如你把『刘德华』修改成『蔡徐坤』,提交多少次都是修改成『蔡徐坤』
ps: 『POST表示创建资源,PUT表示更新资源』这种说法是错误的,两个都能创建资源,根本区别就在于幂等性
4.PUT和PATCH都是给服务器发送修改资源,有什么区别?
PUT和PATCH都是更新资源,⽽PATCH⽤来对已知资源进⾏局部更新。
⽐如我们有⼀篇⽂章的地址 https://www.jianshu.com/articles/820357430
,这篇⽂章的可以表示为:
article = {
author: 'dxy',
creationDate: '2019-6-12',
content: '我写⽂章像蔡徐坤',
id: 820357430
}
当我们要修改⽂章的作者时,我们可以直接发送 PUT https://www.jianshu.com/articles/820357430
,这个时候的数据应
该是:
{
author:'蔡徐坤',
creationDate: '2019-6-12',
content: '我写⽂章像蔡徐坤',
id: 820357430
}
这种直接覆盖资源的修改⽅式应该⽤put,但是你觉得每次都带有这么多⽆⽤的信息,那么可以发送 PATCHhttps://www.jianshu.com/articles/820357430
,这个时候只需要:
{
author:'蔡徐坤',
}
5. 如何理解 URI?
URI, 全称为(Uniform Resource Identifier), 也就是统一资源标识符,它的作用很简单,就是区分互联网上不同的资源。
但是,它并不是我们常说的网址, 网址指的是URL, 实际上URI包含了URN和URL两个部分,由于 URL 过于普及,就默认将 URI 视为 URL 了。
URI 的结构
URI 真正最完整的结构是这样的。
可能你会有疑问,好像跟平时见到的不太一样啊!先别急,我们来一一拆解。
scheme 表示协议名,比如http, https, file等等。后面必须和://连在一起。
user:passwd@ 表示登录主机时的用户信息,不过很不安全,不推荐使用,也不常用。
host:port表示主机名和端口。
path表示请求路径,标记资源所在位置。
query表示查询参数,为key=val这种形式,多个键值对之间用&隔开。
fragment表示 URI 所定位的资源内的一个锚点,浏览器可以根据这个锚点跳转到对应的位置。
举个例子:
https://www.baidu.com/s?wd=HTTP&rsv_spt=1
这个 URI 中,https
即scheme
部分,www.baidu.com
为host:port
部分(注意,http 和 https 的默认端口分别为80、443),/s
为path
部分,而wd=HTTP&rsv_spt=1
就是query
部分。
URI 编码
URI 只能使用ASCII, ASCII 之外的字符是不支持显示的,而且还有一部分符号是界定符,如果不加以处理就会导致解析出错。
因此,URI 引入了编码机制,将所有非 ASCII 码字符和界定符转为十六进制字节值,然后在前面加个%
。
如,空格被转义成了%20
,三元被转义成了%E4%B8%89%E5%85%83
。
5.http的请求报⽂是什么样的?
请求报⽂有4部分组成:
- 请求⾏
- 请求头部
- 空⾏
- 请求体
- 请求⾏包括:请求⽅法字段、URL字段、HTTP协议版本字段。 它们⽤空格分隔。例如,GET /index.html
HTTP/1.1。 - 请求头部:请求头部由关键字/值对组成,每⾏⼀对,关键字和值⽤英⽂冒号“:”分隔
- User-Agent:产⽣请求的浏览器类型。
- Accept:客户端可识别的内容类型列表。
- Host:请求的主机名,允许多个域名同处⼀个IP地址,即虚拟主机。
- 请求体: post put等请求携带的数据
6.http的响应报⽂是什么样的?
请求报⽂有4部分组成:
- 响应⾏
- 响应头
- 空⾏
- 响应体
- 响应⾏: 由协议版本,状态码和状态码的原因短语组成,例如 HTTP/1.1 200 OK 。
- 响应头:响应部⾸组成
- 响应体:服务器响应的数据
7.聊⼀聊HTTP的部⾸有哪些?
内容很多,重点看标『✨ 』内容
通⽤⾸部字段(General Header Fields):请求报⽂和响应报⽂两⽅都会使⽤的⾸部
- Cache-Control 控制缓存 ✨
- Connection 连接管理、逐条⾸部 ✨
- Upgrade 升级为其他协议
- via 代理服务器的相关信息
- Wraning 错误和警告通知
- Transfor-Encoding 报⽂主体的传输编码格式 ✨
- Trailer 报⽂末端的⾸部⼀览
- Pragma 报⽂指令
- Date 创建报⽂的⽇期
请求⾸部字段(Reauest Header Fields):客户端向服务器发送请求的报⽂时使⽤的⾸部
- Accept 客户端或者代理能够处理的媒体类型 ✨
- Accept-Encoding 优先可处理的编码格式
- Accept-Language 优先可处理的⾃然语⾔
- Accept-Charset 优先可以处理的字符集
- If-Match ⽐较实体标记(ETage) ✨
- If-None-Match ⽐较实体标记(ETage)与 If-Match相反 ✨
- If-Modified-Since ⽐较资源更新时间(Last-Modified)✨
- If-Unmodified-Since⽐较资源更新时间(Last-Modified),与
- If-Modified-Since相反 ✨
- If-Rnages 资源未更新时发送实体byte的范围请求
- Range 实体的字节范围请求 ✨
- Authorization web的认证信息 ✨
- Proxy-Authorization 代理服务器要求web认证信息
- Host 请求资源所在服务器 ✨
- From ⽤户的邮箱地址
- User-Agent 客户端程序信息 ✨
- Max-Forwrads 最⼤的逐跳次数
- TE 传输编码的优先级
- Referer 请求原始放的url
- Expect 期待服务器的特定⾏为
响应⾸部字段(Response Header Fields):从服务器向客户端响应时使⽤的字段 - Accept-Ranges 能接受的字节范围
- Age 推算资源创建经过时间
- Location 令客户端重定向的URI ✨
- vary 代理服务器的缓存信息
- ETag 能够表示资源唯⼀资源的字符串 ✨
- WWW-Authenticate 服务器要求客户端的验证信息
- Proxy-Authenticate 代理服务器要求客户端的验证信息
- Server 服务器的信息 ✨
- Retry-After 和状态码503 ⼀起使⽤的⾸部字段,表示下次请求服务器的时
实体⾸部字段(Entiy Header Fields):针对请求报⽂和响应报⽂的实体部分使⽤⾸部 - Allow 资源可⽀持http请求的⽅法 ✨
- Content-Language 实体的资源语⾔
- Content-Encoding 实体的编码格式
- Content-Length 实体的⼤⼩(字节)
- Content-Type 实体媒体类型
- Content-MD5 实体报⽂的摘要
- Content-Location 代替资源的yri
- Content-Rnages 实体主体的位置返回
- Last-Modified 资源最后的修改资源 ✨
- Expires 实体主体的过期资源
聊⼀聊HTTP的状态码有哪些?
RFC 规定 HTTP 的状态码为三位数,被分为五类:
- 1xx: 表示目前是协议处理的中间状态,还需要后续操作。
- 2xx: 表示成功状态。
- 3xx: 重定向状态,资源位置发生变动,需要重新请求。
- 4xx: 请求报文有误。
- 5xx: 服务器端发生错误。
接下来就一一分析这里面具体的状态码。
1xx
101 Switching Protocols。在HTTP升级为WebSocket的时候,如果服务器同意变更,就会发送状态码 101。
2XX 成功
- 200 OK,表示从客户端发来的请求在服务器端被正确处理 ✨
- 201 Created 请求已经被实现,⽽且有⼀个新的资源已经依据请求的需要⽽建⽴
- 202 Accepted 请求已接受,但是还没执⾏,不保证完成请求
- 204 No content,表示请求成功,但响应报⽂不含实体的主体部分
- 206 Partial Content顾名思义,表示部分内容,它的使用场景为 HTTP 分块下载和断点续传,当然也会带上相应的响应头字段Content-Range。✨
3XX 重定向
- 301 moved permanently,永久性重定向,表示资源已被分配了新的 URL✨
比如你的网站从 HTTP 升级到了 HTTPS 了,以前的站点再也不用了,应当返回301,这个时候浏览器默认会做缓存优化,在第二次访问的时候自动访问重定向的那个地址。
而如果只是暂时不可用,那么直接返回302即可,和301不同的是,浏览器并不会做缓存优化。 - 302 found,临时性重定向,表示资源临时被分配了新的 URL ✨
- 303 see other,表示资源存在着另⼀个 URL,应使⽤ GET ⽅法丁⾹获取资源
- 304 not modified,当协商缓存命中时会返回这个状态码,详见浏览器缓存。✨
- 307 temporary redirect,临时重定向,和302含义相同
4XX 客户端错误
- 400 bad request,请求报⽂存在语法错误 ✨
- 401 unauthorized,表示发送的请求需要有通过 HTTP 认证的认证信息 ✨
- 403 forbidden,表示对请求资源的访问被服务器拒绝 , 这实际上并不是请求报文出错,而是服务器禁止访问,原因有很多,比如法律禁止、信息敏感。✨
- 404 not found,表示在服务器上没有找到请求的资源 ✨
- 408 Request timeout, 客户端请求超时
- 409 Confict, 请求的资源可能引起冲突
5XX 服务器错误
- 500 internal sever error,表示服务器端在执⾏请求时发⽣了错误 ✨
- 501 Not Implemented 请求超出服务器能⼒范围,例如服务器不⽀持当前请求所需要的某个功能,或者请求是服务器不⽀持的某个⽅法
- 503 service unavailable,表明服务器暂时处于超负载或正在停机维护,⽆法处理请求
- 502 Bad Gateway: 服务器自身是正常的,但访问的时候出错了,啥错误咱也不知道。
- 505 http version not supported 服务器不⽀持,或者拒绝⽀持在请求中使⽤的 HTTP 版本
同样是重定向307,303,302的区别?
302是http1.0的协议状态码,在http1.1版本的时候为了细化302状态码⼜出来了两个303和307。
303明确表示客户端应当采⽤get⽅法获取资源,他会把POST请求变为GET请求进⾏重定向。 307会遵照浏览器标准,
不会从post变为get。
005: 简要概括一下 HTTP 的特点?HTTP 有哪些缺点?
HTTP 特点
HTTP 的特点概括如下:
-
灵活可扩展,主要体现在两个方面。一个是语义上的自由,只规定了基本格式,比如空格分隔单词,换行分隔字段,其他的各个部分都没有严格的语法限制。另一个是传输形式的多样性,不仅仅可以传输文本,还能传输图片、视频等任意数据,非常方便。
-
可靠传输。HTTP 基于 TCP/IP,因此把这一特性继承了下来。这属于 TCP 的特性,不具体介绍了。
-
请求-应答。也就是一发一收、有来有回, 当然这个请求方和应答方不单单指客户端和服务器之间,如果某台服务器作为代理来连接后端的服务端,那么这台服务器也会扮演请求方的角色。
-
无状态。这里的状态是指通信过程的上下文信息,而每次 http 请求都是独立、无关的,默认不需要保留状态信息。
HTTP 缺点
无状态:所谓的优点和缺点还是要分场景来看的,对于 HTTP 而言,最具争议的地方在于它的无状态。
在需要长连接的场景中,需要保存大量的上下文信息,以免传输大量重复的信息,那么这时候无状态就是 http 的缺点了。
但与此同时,另外一些应用仅仅只是为了获取一些数据,不需要保存连接上下文信息,无状态反而减少了网络开销,成为了 http 的优点。
明文传输:即协议里的报文(主要指的是头部)不使用二进制数据,而是文本形式。
这当然对于调试提供了便利,但同时也让 HTTP 的报文信息暴露给了外界,给攻击者也提供了便利。WIFI陷阱就是利用 HTTP 明文传输的缺点,诱导你连上热点,然后疯狂抓你所有的流量,从而拿到你的敏感信息。
队头阻塞问题:当 http 开启长连接时,共用一个 TCP 连接,同一时刻只能处理一个请求,那么当前请求耗时过长的情况下,其它的请求只能处于阻塞状态,也就是著名的队头阻塞问题。接下来会有一小节讨论这个问题。
008: HTTP 如何处理大文件的传输?
对于几百 M 甚至上 G 的大文件来说,如果要一口气全部传输过来显然是不现实的,会有大量的等待时间,严重影响用户体验。因此,HTTP 针对这一场景,采取了范围请求
的解决方案,允许客户端仅仅请求一个资源的一部分。
如何支持
当然,前提是服务器要支持范围请求,要支持这个功能,就必须加上这样一个响应头:
Accept-Ranges: none
用来告知客户端这边是支持范围请求的。
Range 字段拆解
而对于客户端而言,它需要指定请求哪一部分,通过Range这个请求头字段确定,格式为bytes=x-y。接下来就来讨论一下这个 Range 的书写格式:
- 0-499表示从开始到第 499 个字节。
- 500- 表示从第 500 字节到文件终点。
- 100表示文件的最后100个字节。
服务器收到请求之后,首先验证范围是否合法,如果越界了那么返回416
错误码,否则读取相应片段,返回206
状态码。
同时,服务器需要添加Content-Range字段,这个字段的格式根据请求头中Range字段的不同而有所差异。
具体来说,请求单段数据
和请求多段数据
,响应头是不一样的。
举个例子:
// 单段数据
Range: bytes=0-9
// 多段数据
Range: bytes=0-9, 30-39
接下来我们就分别来讨论着两种情况
单段数据
对于单段数据的请求,返回的响应如下:
HTTP/1.1 206 Partial Content
Content-Length: 10
Accept-Ranges: bytes
Content-Range: bytes 0-9/100
i am xxxxx
值得注意的是Content-Range字段,0-9表示请求的返回,100表示资源的总大小,很好理解。
多段数据
接下来我们看看多段请求的情况。得到的响应会是下面这个形式:
HTTP/1.1 206 Partial Content
Content-Type: multipart/byteranges; boundary=00000010101
Content-Length: 189
Connection: keep-alive
Accept-Ranges: bytes
--00000010101
Content-Type: text/plain
Content-Range: bytes 0-9/96
i am xxxxx
--00000010101
Content-Type: text/plain
Content-Range: bytes 20-29/96
eex jspy e
--00000010101--
这个时候出现了一个非常关键的字段Content-Type: multipart/byteranges;boundary=00000010101
,它代表了信息量是这样的:
- 请求一定是多段数据请求
- 响应体中的分隔符是 00000010101
因此,在响应体中各段数据之间会由这里指定的分隔符分开,而且在最后的分隔末尾添上–表示结束。
以上就是 http 针对大文件传输所采用的手段。
009: HTTP 中如何处理表单数据的提交?
在 http 中,有两种主要的表单提交的方式,体现在两种不同的Content-Type取值:
- application/x-www-form-urlencoded
- multipart/form-data
由于表单提交一般是POST请求,很少考虑GET,因此这里我们将默认提交的数据放在请求体中。
application/x-www-form-urlencoded
对于application/x-www-form-urlencoded
格式的表单内容,有以下特点:
- 其中的数据会被编码成以&分隔的键值对。
- 字符以URL编码方式编码。
如:
// 转换过程: {a: 1, b: 2} -> a=1&b=2 -> 如下(最终形式)
"a%3D1%26b%3D2"
multipart/form-data
对于multipart/form-data
而言:
- 请求头中的
Content-Type
字段会包含boundary,且boundary的值有浏览器默认指定。例:
Content-Type: multipart/form-data;boundary=----WebkitFormBoundaryRRJKeWfHPGrS4LKe
。 - 数据会分为多个部分,每两个部分之间通过分隔符来分隔,每部分表述均有 HTTP 头部描述子包体,如
Content-Type
,在最后的分隔符会加上–表示结束。
相应的请求体是下面这样:
Content-Disposition: form-data;name="data1";
Content-Type: text/plain
data1
----WebkitFormBoundaryRRJKeWfHPGrS4LKe
Content-Disposition: form-data;name="data2";
Content-Type: text/plain
data2
----WebkitFormBoundaryRRJKeWfHPGrS4LKe--
HTTP的keep-alive是⼲什么的?
在早期的HTTP/1.0中,每次http请求都要创建⼀个连接,⽽创建连接的过程需要消耗资源和时间,为了减少资源消耗,缩短响应时间,就需要重⽤连接。在后来的HTTP/1.0中以及HTTP/1.1中,引⼊了重⽤连接的机制,就是在http请求头中加⼊Connection: keep-alive来告诉对⽅这个请求响应完成后不要关闭,下⼀次咱们还⽤这个请求继续交流。协议规定HTTP/1.0如果想要保持⻓连接,需要在请求头中加上Connection: keep-alive。
keep-alive的优点:
- 较少的CPU和内存的使⽤(由于同时打开的连接的减少了)
- 允许请求和应答的HTTP管线化
- 降低拥塞控制 (TCP连接减少了)
- 减少了后续请求的延迟(⽆需再进⾏握⼿)
- 报告错误⽆需关闭TCP连
7.说说http https的区别,https如何保证安全的?
总的来说,http是HTTP协议运行在TCP之上。所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份。 https是HTTP运行在SSL/TLS之上,SSL/TLS运行在TCP之上。所有传输的内容都经过加密, 加密采用对称加密,但对称加密的密钥用服务器方的证书进行了非对称加密。 此外客户端可以验证服务器端的身份,如果配置了客户端验证,服务器方也可以验证客户端的身份。
(1).为什么有了HTTP为什么还要HTTPS?
https是安全版的http,因为http协议的数据都是明⽂进⾏传输的,所以对于⼀些敏感信息的传输就很不安全,HTTPS就是为了解决HTTP的不安全⽽⽣的。
(2).HTTPS是如何保证安全的?
过程⽐较复杂,我们得先理解两个概念
对称加密:
即通信的双⽅都使⽤同⼀个秘钥进⾏加解密,⽐如特务接头的暗号,就属于对称加密
对称加密虽然很简单性能也好,但是⽆法解决⾸次把秘钥发给对⽅的问题,很容易被⿊客拦截秘钥。
⾮对称加密:
- 私钥 + 公钥= 密钥对
- 即⽤私钥加密的数据,只有对应的公钥才能解密,⽤公钥加密的数据,只有对应的私钥才能解密
- 因为通信双⽅的⼿⾥都有⼀套⾃⼰的密钥对,通信之前双⽅会先把⾃⼰的公钥都先发给对⽅
- 然后对⽅再拿着这个公钥来加密数据响应给对⽅,等到到了对⽅那⾥,对⽅再⽤⾃⼰的私钥进⾏解密
⾮对称加密虽然安全性更⾼,但是带来的问题就是速度很慢,影响性能。
解决⽅案:
那么结合两种加密⽅式,将对称加密的密钥使⽤⾮对称加密的公钥进⾏加密,然后发送出去,接收⽅使⽤私钥进⾏解密,得到对称加密的密钥,然后双⽅可以使⽤对称加密来进⾏沟通。
此时⼜带来⼀个问题,中间⼈问题:
如果此时在客户端和服务器之间存在⼀个中间⼈,这个中间⼈只需要把原本双⽅通信互发的公钥,换成⾃⼰的公钥,这样中间⼈就可以轻松解密通信双⽅所发送的所有数据。
所以这个时候需要⼀个安全的第三⽅颁发证书(CA),证明身份的身份,防⽌被中间⼈攻击。
证书中包括:签发者、证书⽤途、使⽤者公钥、使⽤者私钥、使⽤者的HASH算法、证书到期时间等。
但是问题来了,如果中间⼈篡改了证书,那么身份证明是不是就⽆效了?这个证明就⽩买了,这个时候需要⼀个新的技术,数字签名。
数字签名就是⽤CA⾃带的HASH算法对证书的内容进⾏HASH得到⼀个摘要,再⽤CA的私钥加密,最终组成数字签名。
当别⼈把他的证书发过来的时候,我再⽤同样的Hash算法,再次⽣成消息摘要,然后⽤CA的公钥对数字签名解密,得到CA创建的消息摘要,两者⼀⽐,就知道中间有没有被⼈篡改了。
这个时候就能最⼤程度保证通信的安全了。
面试官:说说http https的区别,https如何保证安全的?
HTTP2相对于HTTP1.x有什么优势和特点?
⼆进制分帧
帧:HTTP/2 数据通信的最⼩单位消息:指 HTTP/2 中逻辑上的 HTTP 消息。例如请求和响应等,消息由⼀个或多个帧
组成。
流:存在于连接中的⼀个虚拟通道。流可以承载双向消息,每个流都有⼀个唯⼀的整数ID
HTTP/2 采⽤⼆进制格式传输数据,⽽⾮ HTTP 1.x 的⽂本格式,⼆进制协议解析起来更⾼效。
头部压缩
HTTP/1.x会在请求和响应中中重复地携带不常改变的、冗⻓的头部数据,给⽹络带来额外的负担。
- HTTP/2在客户端和服务器端使⽤“⾸部表”来跟踪和存储之前发送的键-值对,对于相同的数据,不再通过每次请求和响应发送
- ⾸部表在HTTP/2的连接存续期内始终存在,由客户端和服务器共同渐进地更新;
- 每个新的⾸部键-值对要么被追加到当前表的末尾,要么替换表中之前的值。
你可以理解为只发送差异数据,⽽不是全部发送,从⽽减少头部的信息量
服务器推送
服务端可以在发送⻚⾯HTML时主动推送其它资源,⽽不⽤等到浏览器解析到相应位置,发起请求再响应。例如服务端可以主动把JS和CSS⽂件推送给客户端,⽽不需要客户端解析HTML时再发送这些请求。
服务端可以主动推送,客户端也有权利选择是否接收。如果服务端推送的资源已经被浏览器缓存过,浏览器可以通过发送RST_STREAM帧来拒收。主动推送也遵守同源策略,服务器不会随便推送第三⽅资源给客户端。
多路复⽤
HTTP 1.x 中,如果想并发多个请求,必须使⽤多个 TCP 链接,且浏览器为了控制资源,还会对单个域名有 6-8个的TCP链接请求限制。
HTTP2中:
- 同域名下所有通信都在单个连接上完成。
- 单个连接可以承载任意数量的双向数据流。
- 数据流以消息的形式发送,⽽消息⼜由⼀个或多个帧组成,多个帧之间可以乱序发送,因为根据帧⾸部的流标识可以重新组装
拓展阅读
HTTP/2特性及其在实际应用中的表现
HTTP的缓存的过程是怎样的?
1.浏览器缓存的力量
通常情况下的步骤是:
- 客户端向服务器发出请求,请求资源
- 服务器返回资源,并通过响应头决定缓存策略
- 客户端根据响应头的策略决定是否缓存资源(这⾥假设是),并将响应头与资源缓存下来
- 在客户端再次请求且命中资源的时候,此时客户端去检查上次缓存的缓存策略,根据策略的不同、是否过期等判断是直接读取本地缓存还是与服务器协商缓存
1.什么时候会触发强缓存或者协商缓存?
强缓存
- 强缓存离不开两个响应头 Expires 与 Cache-Control
Expires:Expires是http1.0提出的⼀个表示资源过期时间的header,它描述的是⼀个绝对时间,由服务器返回,Expires受限于本地时间,如果修改了本地时间,可能会造成缓存失效
Expires: Wed, 11 May 2018 07:20:00 GMT
- Cache-Control: Cache-Control 出现于 HTTP / 1.1,优先级⾼于 Expires ,表示的是相对时间
Cache-Control: max-age=315360000
⽬前主流的做法使⽤ Cache-Control 控制缓存,除了 max-age 控制过期时间外,还有⼀些不得不提
- Cache-Control: public可以被所有⽤户缓存,包括终端和CDN等中间代理服务器
- Cache-Control: private只能被终端浏览器缓存,不允许中继缓存服务器进⾏缓存
- Cache-Control: no-cache,先缓存本地,但是在命中缓存之后必须与服务器验证缓存的新鲜度才能使⽤
- Cache-Control: no-store,不会产⽣任何缓存
在缓存有效期内命中缓存,浏览器会直接读取本地的缓存资源,当缓存过期之后会与服务器进⾏协商。
协商缓存
当第⼀次请求时服务器返回的响应头中没有Cache-Control和Expires或者Cache-Control和Expires过期抑或它的属性设置为no-cache时,那么浏览器第⼆次请求时就会与服务器进⾏协商。
如果缓存和服务端资源的最新版本是⼀致的,那么就⽆需再次下载该资源,服务端直接返回304 Not Modified 状态码,如果服务器发现浏览器中的缓存已经是旧版本了,那么服务器就会把最新资源的完整内容返回给浏览器,状态码就是200 Ok。
服务器判断缓存是否是新鲜的⽅法就是依靠HTTP的另外两组信息
Last-Modified/If-Modified-Since
客户端⾸次请求资源时,服务器会把资源的最新修改时间 Last-Modified:Thu, 19 Feb 2019 08:20:55 GMT 通过响应部⾸发送给客户端,当再次发送请求是,客户端将服务器返回的修改时间放在请求头 If-Modified-Since:Thu, 19 Feb 201908:20:55 GMT 发送给服务器,服务器再跟服务器上的对应资源进⾏⽐对,如果服务器的资源更新,那么返回最新的资
源,此时状态码200,当服务器资源跟客户端的请求的部⾸时间⼀致,证明客户端的资源是最新的,返回304状态码,表示客户端直接⽤缓存即可。
ETag/If-None-Match
ETag的流程跟Last-Modified是类似的,区别就在于ETag是根据资源内容进⾏hash,⽣成⼀个信息摘要,只要资源内容有变化,这个摘要就会发⽣巨变,通过这个摘要信息⽐对,即可确定客户端的缓存资源是否为最新,这⽐Last-Modified的精确度要更⾼。
响应头
因此整体的缓存流程图如下:
推荐阅读
1.送给前端er一份 HTTP 基础知识大图
2.解读HTTP/2与HTTP/3 的新特性
3.图解 | 你管这破玩意儿叫TCP?
4.缓存
①HTTP缓存策略
②前端缓存最佳实践
5.HTTP灵魂之问,巩固你的 HTTP 知识体系
6.面试大厂,这些 HTTP 面试题要掌握