本文简单介绍下HTTP协议的重点内容。
HTTP版本迭代
-
HTTP/0.9 – 单行协议
唯一可用方法GET,是一个非常简陋的协议 -
HTTP/1.0 构建可扩展性
引入了http头,状态码,完善了其他请求方法,具备了除了html文档外其他文件的传输能力 -
HTTP/1.1 标准化的协议
1997年发布
1.连接可以复用,即长连接,不需要频繁创建连接
2.增加了管线化技术,即流水线,第一个响应未接受钱就可以发送第二个请求
3.支持响应分块,即可以请求一个资源的部分字节Accept-Range
4.引入host头,能够使不同域名配置在同一个IP地址的服务器上
5.额外的缓存控制,内容协商机制,语言,编码... -
HTTP2 更优异的表现
2015年正式标准化
1.改成了二进制协议而非文本协议,不再可读,也不再可以随便手动创建
2.使用了多路复用,并行的请求能在同一个连接中处理
3.压缩了header,因为头在一系列请求中常常是类似的
4.服务器推送机制 -
HTTP3 全新的版本
*目前仍然是草案状态,还未正式发布
弃用TCP协议,改为使用基于UDP协议的QUIC协议实现。
此变化主要为了解决HTTP/2中存在的TCP队头阻塞问题。由于HTTP/2在单个TCP连接上使用了多路复用,受到TCP拥塞控制的影响,少量的丢包就可能导致整个TCP连接上的所有流被阻塞。
HTTP的性能细节
对性能的优化基本都是因为:服务器的tcp连接资源很宝贵
http1.1的流水线 pipeline
实际上,1.1的流水线并不是一个好的提升,在现代浏览器中并不是默认被启用的
流水线管道是类似一个FIFO队列,而且1.1没有用编号标识每个请求,所以所有的响应都只能有序发送,有序接受。如果一个请求比较耗时,或者被程序阻塞了,那么后面的请求即使处理完毕了,也要等待。这个问题又叫http的队首阻塞。
所以干脆使用多个连接,但浏览器一般又限制并发连接数量,所以性能有瓶颈。
http2的多路复用 multiplexing
可以实现一个连接中多个请求的并发,解决了1.1的队首阻塞问题。而实现多路复用的关键在于:分帧,并且给帧分配编号,传输到客户端可以自行组装,也就具备了乱序传输的能力。而要实现分帧,使用二进制是最方便的。
仍然存在的问题:tcp队首阻塞问题,TCP 的阻塞问题是因为传输阶段可能会丢包,一旦丢包就会等待重新发包,阻塞后续传输,这个问题虽然有滑动窗口(Sliding Window)这个方案,但是只能增强抗干扰,并没有彻底解决。
而http3改用udp彻底解决了这个问题。
浏览器会限制同一个服务器的并发连接数量
为了避免服务器负载太大,浏览器是会限制用户对单个服务器的并发数量的,曾经默认的连接数量为 2 到 3 个,现在比较常用的并发连接数已经增加到 6 个。这是一种Dos保护。
服务器推送
服务端可以在发送页面HTML时主动推送其它资源,而不用等到浏览器解析到相应位置,发起请求再响应。例如服务端可以主动把JS和CSS文件推送给客户端,而不需要客户端解析HTML时再发送这些请求。
首部压缩
一个连接中,多个http请求/响应通常头部大部分行是相同的。http2会在服务端和客户端各维护一张‘首部表’,来记录上一次发送请求/响应的的行。对于相同的行,下次请求不在重新发送,只发送不同的行。
- 比如,语言、编码、是否长连接、用户类型等等很有可能都是重复的
- 这样减少了冗余数据,降低了网络开销
状态码
-
100 Continue
服务器收到了请求的初始部分,并且请客户端继续发送。在服务器发送了 100 Continue 状态码之后,如果收到客户端的请求,则必须进行响应。 -
101 Switching Protocols
切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议 -
200 OK
请求成功 -
301 Moved Permanently
永久重定向。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替 -
302 Found
临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI -
304 Not Modified
未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源 -
400 Bad Request
客户端请求的语法错误,服务器无法理解 -
403 Forbidden
服务器理解请求客户端的请求,但是拒绝执行此请求 -
404 Not Found
服务器无法根据客户端的请求找到资源 -
500 Internal Server Error
服务器内部错误,无法完成请求 -
502 Bad Gateway
网关错误,作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应 -
504 Gateway Time-out
网关超时,充当网关或代理的服务器,未及时从远端服务器获取请求
HTTP消息
Http1.x :可读的消息
HTTP消息又分 请求消息/响应消息
- 起始行/状态行
请求起始行:包括 HTTP方法 + 请求URL + HTTP版本
响应状态行:包括 HTTP版本 + 状态码 + 状态码信息 - Http headers
包括http的一些控制字段 - 一个空行
用于分隔header和body - Body
请求:不是所有的请求都有一个 body:例如获取资源的请求,GET,HEAD,DELETE 和 OPTIONS,通常它们不需要 body。
响应:不是所有的响应都有 body:具有状态码 (如 201 或 204) 的响应,通常不会有 body。
Http2 :帧
http2相当于是在http1和传输层之间新增了一个 分帧层。
引入了一个额外的步骤:将 HTTP/1.x 消息分成帧并嵌入到流 (stream) 中。数据帧和报头帧分离,这将允许报头压缩。将多个流组合,使得多路复用 (multiplexing)一个TCP连接。
HTTP请求类型
get和post区别
- GET 读取一个资源,可以将 GET 数据缓存在浏览器、代理或服务端。反复 GET 不应该对访问有副作用,没有副作用被称为幂等。
- POST 不是幂等的,意味着不能随意多次执行,因此不能缓存,如果尝试重新执行 POST 请求,浏览器会弹出提示框询问是否重新提交表单。
- GET 请求由 url 触发,想携带参数就只能在 url 后附加。
- POST 请求来自表单提交,表单数据被浏览器编码到 HTTP 请求报文的请求体中。主要有两种编码格式,一种是
application/..
,用来传输简单数据;另一种是multipart/form-data
格式,用来传输文件,对二进制数据传输效率高。 - 从攻击的角度说,无论 GET 还是 POST 都不安全,因为 HTTP 是明文协议。
- GET 长度受限于 url,而 url 的长度由浏览器和服务器决定。
POST 没有大小限制,起限制作用的是服务器的处理能力。 - GET请求的资源可以被浏览器缓存,POST不能被缓存。
HTTP cookie
cookie是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态。Cookie 使基于无状态的HTTP协议记录稳定的状态信息成为了可能。