前言
关于HTTP的知识比较繁杂,也比较零散,于是想要通过这篇文章对常用知识点进行总结,一些知识点描述是从网上搜集而来,如有侵权,可以联系我进行修改。
提出问题
- Http的报文结构。
- Http request的几种类型。
- Http的状态码含义。
- Http1.1和Http1.0的区别,以及缓存原理
- Http长连接keep-alive。
- Cookie与Session的作用于原理。
- 电脑上访问一个网页,整个过程是怎么样的:DNS、HTTP、TCP、OSPF、IP、ARP。
解答
1. Http的报文结构
http协议的请求报文和响应报文都是由以下4部分组成:
- 请求行
- 请求头
- 空行 CR + LF,回车 + 换行
- 请求体
2. Http request的几种类型
请求行
Request
格式:【方法 URL HTTP版本】 例如: GET /csrfToken HTTP/1.1
HTTP版本:目前有 HTTP/1.0、HTTP/1.1、HTTP/2.0 版本,其中 HTTP1.1 版本使用较广泛
方法 | 说明 | 支持HTTP协议版本 |
---|---|---|
GET | 获取资源 | 1.0 、1.1 |
POST | 传输实体主体 | 1.0、1.1 |
PUT | 传输文件 | 1.0、1.1 |
HEAD | 获得报文首部 | 1.0、1.1 |
DELETE | 删除资源 | 1.0、1.1 |
OPTIONS | 询问支持的方法 | 1.1 |
TRACE | 追踪路径 | 1.1 |
CONNECT | 要求用隧道协议连接代理 | 1.1 |
LINK | 建立和资源之间的联系 | 1.0 |
UNLINK | 断开连接关系 | 1.0 |
Response
格式:【HTTP版本 状态码 描述】 例如: HTTP/1.1 200 OK
、HTTP/1.1 404 NOT FOUND
类别 | 原因短语 | |
---|---|---|
1xx | Informational(信息性状态码) | 接收的请求正在处理 |
2xx | Success(成功状态码) | 请求正常处理完毕 |
3xx | Redirection(重定向状态码) | 需要进行附加操作以完成请求 |
4xx | Client Error(客户端错误状态码) | 服务器无法处理请求 |
5xx | Server Error(服务器错误状态码) | 服务器处理请求出错 |
3. Http的状态码含义
常用状态码
- 200:OK,请求被正常处理
- 204:No Content,请求被受理但没有资源可以返回,返回204响应,浏览器显示的页面不发生更新
- 206:Partial Content,客户端进行范围请求,服务器成功执行了这部分的GET请求,响应报文中包含由Content-Range指定范围的实体内容
- 301:Moved Permanently,永久性重定向,比如访问
http://test.zhixue.com/zbptadmin
,服务器会返回301,response的headers中会包含一个字段:Location: http://test.zhixue.com/zbptadmin/
,浏览器会按照这个地址重新请求,并且如果用户保存了书签,浏览器会自动按照Location更新书签 - 302:Found,临时性重定向,和301类似,但是浏览器不会更新书签
- 303:See Other,和302类似,但303明确表示客户端应该使用GET方法获取Location资源
- 备注:当301,302,303响应状态码返回时,几乎所有的浏览器都会把POST改成GET,并删除请求报文内的主体,之后请求会自动再次发送。301,302标准是禁止将POST方法改成GET方法的,但实际使用时浏览器厂商都会这么做。
- 304:Not Modified,发送附带条件的请求时,(附带条件的请求是指采用GET方法的请求报文中包含If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since中任一首部),条件不满足返回304,可直接使用客户端缓存,与重定向无关
- 307:Temporary Redirect,临时重定向,与302类似,只是强制要求使用POST方法
- 400:Bad Request,请求报文中存在语法错误,服务器无法识别
- 401:Unauthorized,请求需要认证
- 403:Forbidden,请求对应的资源禁止被访问
- 404:Not Found,服务器无法找到对应资源
- 500:Internal Server Error,服务器内部错误
- 503:Service Unavailable,服务器正忙
常见HTTP首部字段
通用首部字段(请求报文与响应报文都会使用的首部字段)
- Date:创建报文的时间
- Connection:连接的管理
- Cache-Control:缓存的控制
- Transfer-Encoding:报文主题的传输编码方式
请求首部字段(请求报文会使用的首部字段)
- Host:请求资源所在的服务器
- Accept:可处理的媒体类型
- Accept-Charset:可接收的字符集
- Accept-Encoding:可接收的内容编码
- Accept-Language:可接收的自然语言
响应首部字段(响应报文会使用的首部字段)
- Accept-Range:可接收的字节范围
- Location:让客户端重定向到的URI
- Server:HTTP服务器的安装信息
实体首部字段(请求报文与响应报文的实体部分使用的首部字段)
- Allow:资源可支持的HTTP方法
- Content-Type:实体主类的类型
- Content-Encoding:实体主体适用的编码方式
- Content-Language:实体主体的自然语言
- Content-Length:实体主体的字节数
- Content-Range:实体主体的位置范围,一般用于发出部分请求时使用
4. HTTP1.0、HTTP1.1、HTTP2.0区别
HTTP1.0 和 HTTP1.1 主要区别
-
长连接
- HTTP1.0需要使用keep-alive参数告知服务器要建立一个长连接,而HTTP1.1默认支持长连接
- HTTP是基于TCP/IP协议的,创建一个TCP连接是需要经过三次握手的,有一定的开销,如果每次通讯都要重新建立连接的话,对性能有影响。因此最好能维持一个长连接,可以用这个长连接来发送多个请求
-
节约带宽
- HTTP1.1支持只发送header信息,也就是HTTP的HEAD Method,如果服务器认为客户端有权限请求服务器,则返回100,否则返回401。客户端如果接收到100,才开始把请求体body发送到服务器。
- 这样,当服务器返回401的时候,客户端就可以不用发送请求体了,节约了带宽
- HTTP1.1支持分块传输,比如206状态码,由Content-Range指定传输内容,这是支持文件断点续传的基础。
-
HOST域
- 现在一台服务器上可以有多个虚拟主机,这些虚拟站点可以共享同一个ip和端口,HTTP1.0是没有host域的,HTTP1.1才支持这个参数
HTTP1.1 和 HTTP2.0的区别
-
多路复用
-
HTTP2.0使用了多路复用的技术,做到同一个连接并发处理多个请求,而且并发请求的数量比HTTP1.1大了好几个数量级
- 当然HTTP1.1也可以多建立几个TCP连接,来支持处理更多并发的请求,但是创建TCP连接本身也是有开销的
- TCP连接有一个预热和保护的过程,先检查数据是否传送成功,一旦成功过,则慢慢加大传输速度。因此对应瞬时并发的连接,服务器的响应就会变慢。所以最好能使用一个建立的连接,并且这个连接可以支持瞬时并发的请求
- HTTP/1.1,若干个请求排队串行化单线程处理,后面的请求等待前面请求的返回才能获得执行机会,一旦有某个请求超时,后续请求只能被阻塞,也就是人们常说的线头阻塞
- HTTP/2.0,多个请求可同时在一个连接上并行执行,某个任务耗时严重,不会影响到其他连接的正常执行
-
-
数据压缩
- HTTP1.1不支持header数据的压缩,HTTP2.0使用HPACK算法对header的数据进行压缩,这样数据体积小了,在网络上传输就会更快
-
服务器推送
- 当我们对HTTP2.0的web server请求数据的时候,服务器会顺便把一些客户端需要的资源一起推送到客户端,免得客户端再次创建连接发送请求到服务器获取。这种方式非常适合加载静态资源。
- 服务器推送的这些资源其实存在客户端的某个地方,客户端直接从本地加载这些资源就可以了,不用走网络,速度自然快很多。
HTTP缓存
缓存分类
- 强缓存
浏览器在加载资源时,先根据这个资源的一些http header判断它是否命中强缓存,如果命中,浏览器直接从自己的缓存中读取资源,不会发请求到服务器,此时状态码是200,但是看Size项是from memory cache或from disk cache
- 协商缓存
- 当强缓存没有命中时,浏览器一定会发送一个请求到服务器,通过服务器端依据资源的另外一些http header验证这个资源是否命中协商缓存,如果命中,服务器会将这个请求返回304,但是不会返回这个资源的数据,而是告诉客户端可以直接从缓存中加载这个资源,于是浏览器就又会从自己的缓存中去加载这个资源;如果没有命中,则将资源返回客户端,状态为200,浏览器同时依据response header中的相关项更新本地缓存数据
from memory cache 和 from disk cache
区别
- from memory cache 是从内存中读取缓存资源,很快,关闭浏览器后,内存中的资源就消失了
- from disk cache 是从磁盘中读取缓存资源,要比 from memory cache 慢,但是持久化,关闭浏览器后仍然存在
哪些资源存在memory,哪些资源存在disk
看了一些文章,大部分观点是说:
- 资源在disk和memory中都会存
- 当关闭浏览器,再打开那个页面的时候,从disk cache中获取缓存资源,同时将缓存资源存在了内存中,当再次刷新页面的时候,就从memory cache中读取,因为这样会更快一些
- 我自己试了一些页面,再次刷新还是有的from disk cache,有的from memory cache,网站被黑,所以这个持保留观点
- 还有的文章说css文件存在disk中,js等脚本存在memory中,个人认为这个不太靠谱,因为memory中的缓存在关闭浏览器就消失了,如果js只存在memory,就起不到缓存的作用了
强缓存相关http header
- Expires
Expires的值是服务端返回的到期时间,用GMT格式的字符串表示,如:Expires: Thu, 31 Dec 2016 23:55:55 GMT
。即下一次请求时,请求时间小于服务器返回的到期时间,直接使用缓存数据。不过Expires是HTTP1.0的东西,现在浏览器默认使用HTTP1.1,所以它的作用基本忽略。另一个问题是,到期时间是由服务器生成的,但是客户端时间可能和服务器时间有偏差,这就会导致缓存命中的误差。所以HTTP1.1的版本中,使用Cache-Control替代。
- Cache-Control
Cache-Control是最重要的规则。常见的取值有:
- ```private```:客户端可以缓存
- ```public```:客户端和代理服务器都可以缓存
- ```max-age=xxx```:缓存的内容将在xxx秒后失效,单位是秒
- ```no-cache```:需要使用**协商缓存**来验证缓存数据
- ```no-store```:不缓存
协商缓存相关http header
第1组:Last-Modified/If-Modified—Since
Last-Modified
:第一次请求资源时,服务器返回的http header,告诉浏览器资源的最后修改时间,为GMT格式,如Last-Modified: Thu, 24 Jan 2017 23:55:55 GMT
If-Modified-Since
:再次请求服务器资源时,浏览器设置在请求header中,值 为该资源第一次请求时服务器设置的Last-Modified
`值,如If-Modified-Since: Thu, 24 Jan 2017 23:55:55 GMT
,服务器收到请求后发现request header中有If-Modified-Since
,则与被请求资源的最后修改时间进行比对。若资源的最后修改时间大于If-Modified-Since
,说明资源又被改动过,则返回资源内容,状态码200,同时浏览器依据相应response header更新缓存资源;若资源的最后修改时间小于或等于If-Modified-Since
,说明资源无新修改,则返回状态码304,但是不返回资源,告知浏览器继续使用所保存的cache
第2组:Etag/If-None-Match
Etag
:服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器确定),如Etag: W/"5886c231-8d9"
If-None-Match
:再次请求服务器时,通过此字段告知服务器该资源的唯一标识,如If-None-Match: W/"5886c231-8d9"
,服务器收到请求后发现request header中有If-None-Match
,则与被请求资源的唯一标识进行比对,若不同,说明资源又被改动过,则返回资源内容,状态码200,同时浏览器依据相应response header更新缓存资源;若相同,则说明资源无更改,返回304,告知浏览器继续使用所保存的缓存资源
为什么要有Etag?
Last-Modified
颗粒度是秒,只能记录秒级的修改,比如1s内修改了N次,If-Modified-Since就无法判断了,所以要引入Etag。
总结
- 先执行强缓存策略,服务器通知浏览器一个缓存有效时间,在有效时间内,下次请求时直接使用缓存,不发起http请求,缓存从from memory cache或from disk cache中读取,若超过了有效时间,则执行协商缓存策略
- 对于协商缓存,将缓存信息中的Etag和Last-Modified的值通过If-None-Match和If-Modified-Since发送给服务器,由服务器进行校验,若资源无更改,返回304,浏览器继续使用缓存,若资源被更改,则返回资源,状态码200,同时浏览器更新缓存
流程图
浏览器第一次请求:
浏览器第二次请求:
5. Http长连接keep-alive
三个概念
- 短连接
所谓短连接,就是每次请求一个资源就建立连接,请求完成后立马关闭。每次请求都经过“创建TCP连接 -> 请求资源 -> 响应资源 -> 释放连接”。
- 长连接
所谓长连接(persistent connection),就是只建立一次TCP连接,多次HTTP请求都复用该连接。
- 并行连接
所谓并行连接(multiple connection),其实就是并发的短连接。
keep-alive
在HTTP/1.0里,为了实现client到web-server能支持长连接,必须在HTTP请求头里显式指定Connection: keep-alive
在HTTP/1.1里,就默认开启了keep-alive,要关闭keep-alive必须在HTTP请求头里显式指定Connection: close
现在大多数浏览器都默认是使用HTTP/1.1,所以keep-alive都是默认打开的。一旦client和server达成协议,那么长连接就建立好了。
keepalive_timeout
Httpd守护进程,一般都提供了keep-alive timeout时间设置参数。比如nginx的keepalive_timeout,和Apache的KeepAliveTimeout。这个keepalive_timout时间值意味着:一个http产生的tcp连接在传送完最后一个响应后,还需要hold住keepalive_timeout秒后,才开始关闭这个连接。Nginx配置中的keepalive_timeout默认为75s,
6. cookie与Session
这个重点在于理解,这里就不赘述了。