做互联网方向的路上,每个工程师都要去了解一些互联网底层的知识,HTTP则是其中之一,从HTTP1到1.1再到2.0,每一次升级都是代表着一次互联网的革新。了解底层知识点,在开发中才知道如何去筛选更好的方案,从而应对各式各样的业务。本文就给大家介绍一下互联网底层知识点--HTTP协议
本文摘自简书 (作者: 一个人在路上走下去),并进行总结。
HTTP协议
HTTP(超文本传输协议,HyperTextTransfer Protocol)是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。是用于从WWW服务器传输超文本到本地浏览器的传输协议。默认使用80端口,HTTP客户端发起一个请求,建立一个到服务器指定端口(默认是80端口)的TCP连接。HTTP协议和TCP协议是不冲突的,HTTP定义在七层协议中的应用层,TCP解决的是传输层的逻辑。HTTP使用TCP而不是UDP的原因在于(打开)一个网页必须传送很多数据,而TCP协议提供传输控制,按顺序组织数据,和错误纠正。HTTP协议的瓶颈及其优化技巧都是基于TCP协议本身的特性。如TCP建立连接时三次握手有1.5个RTT(round-triptime)的延迟,为了避免每次请求的都经历握手带来的延迟,应用层会选择不同策略的http长链接方案。又如TCP在建立连接的初期有慢启动(slow start)的特性,所以连接的重用总是比新建连接性能要好。
HTTP连接使用的是“请求—响应”的方式,不仅在请求时需要先建立连接,而且需要客户端向服务器发出请求后,服务器端才能回复数据。HTTP/1.0是第一个在通讯中指定版本号的HTTP 协议版本,至今仍被广泛采用,特别是在代理服务器中。HTTP/1.1是当前版本,持久连接被默认采用,并能很好地配合代理服务器工作,还支持以管道方式同时发送多个请求,以便降低线路负载,提高传输速度。HTTP/2.0在HTTP 1.x的基础上,大幅度的提高了web性能,减少了网络延迟。HTTP1.0和1.1在之后很长的一段时间内会一直并存,这是由于网络基础设施更新缓慢所决定的。
HTTP1.0
同时,带宽和延迟也是影响一个网络请求的重要因素。在网络基础建设已经使得带宽得到极大的提升的当下,大部分时候都是延迟在于响应速度。基于此会发现,http1.0被抱怨最多的就是连接无法复用,和head of line blocking这两个问题。理解这两个问题有一个十分重要的前提:客户端是依据域名来向服务器建立连接,一般PC端浏览器会针对单个域名的server同时建立6~8个连接,手机端的连接数则一般控制在4~6个。显然连接数并不是越多越好,资源开销和整体延迟都会随之增大。连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大。head of line blocking会导致带宽无法被充分利用,以及后续健康请求被阻塞。
head of line blocking(holb)会导致健康的请求会被不健康的请求影响,而且这种体验的损耗受网络环境影响,出现随机且难以监控。为了解决holb带来的延迟,协议设计者设计了一种新的pipelining机制。pipelining只能适用于http1.1,而且由于使用苛刻,很多浏览器厂商并不支持。
HTTP1.1
为了克服HTTP/1.0的这个缺陷,HTTP/1.1支持持久连接(HTTP/1.1的默认模式使用带流水线的持久连接),在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟。一个包含有许多图像的网页文件的多个请求和应答可以在一个连接中传输,但每个单独的网页文件的请求和应答仍然需要使用各自的连接。HTTP 1.1还允许客户端不用等待上一次请求结果返回,就可以发出下一次请求,但服务器端必须按照接收到客户端请求的先后顺序依次回送响应结果,以保证客户端能够区分出每次请求的响应内容,这样也显著地减少了整个下载过程所需要的时间。
在HTTP/1.1,Request 和 Response 头中都有可能出现一个 connection 的头,此 header 的含义是当 client 和 server 通信时对于长链接如何进行处理。
在HTTP/1.1,client 和 server 都是默认对方支持长链接的,如果 client 使用 HTTP/1.1 协议,但又不希望使用长链接,则需要在 header 中指明 connection 的值为 close;如果 server 方也不想支持长链接,则在 response 中也需要明确说明 connection 的值为 close。不论 request 还是response 的 header 中包含了值为 close 的 connection,都表明当前正在使用的 tcp 链接在当天请求处理完毕后会被断掉。以后 client 再进行新的请求时就必须创建新的 tcp 链接了。
<code>RANGE:bytes</code>
是HTTP/1.1新增内容,HTTP/1.0每次传送文件都是从文件头开始,即0字节处开始。
<code>RANGE:bytes=XXXX</code>
表示要求服务器从文件XXXX字节处开始传送,这就是我们平时所说的断点续传!
由上,HTTP/1.1相较于 HTTP/1.0 协议的区别主要体现在:
缓存处理
带宽优化及网络连接的使用
错误通知的管理
消息在网络中的发送
安全性及完整性
HTTP2.0
多路复用 (Multiplexing)
多路复用允许同时通过单一的 HTTP/2 连接发起多重的请求-响应消息。在 HTTP/1.1协议中浏览器客户端在同一时间,针对同一域名下的请求有一定数量限制。超过限制数目的请求会被阻塞。这也是为何一些站点会有多个静态资源 CDN 域名的原因之一,拿 Twitter 为例,http://twimg.com,目的就是变相的解决浏览器针对同一域名的请求限制阻塞问题。而 HTTP/2 的多路复用(Multiplexing) 则允许同时通过单一的 HTTP/2 连接发起多重的请求-响应消息。因此 HTTP/2 可以很容易的去实现多流并行而不用依赖建立多个 TCP 连接,HTTP/2 把 HTTP 协议通信的基本单位缩小为一个一个的帧,这些帧对应着逻辑流中的消息。并行地在同一个 TCP 连接上双向交换消息。
二进制分帧
HTTP/2在 应用层(HTTP/2)和传输层(TCP or UDP)之间增加一个二进制分帧层。在不改动 HTTP/1.x 的语义、方法、状态码、URI 以及首部字段的情况下, 解决了HTTP1.1的性能限制,改进传输性能,实现低延迟和高吞吐量。在二进制分帧层中, HTTP/2 会将所有传输的信息分割为更小的消息和帧(frame),并对它们采用二进制格式的编码 ,其中 HTTP1.x 的首部信息会被封装到 HEADER frame,而相应的 Request Body 则封装到 DATA frame 里面。
HTTP/2 通信都在一个连接上完成,这个连接可以承载任意数量的双向数据流。在过去, HTTP 性能优化的关键并不在于高带宽,而是低延迟。TCP 连接会随着时间进行自我调谐,起初会限制连接的最大速度,如果数据成功传输,会随着时间的推移提高传输的速度。这种调谐则被称为 TCP 慢启动。由于这种原因,让原本就具有突发性和短时性的 HTTP 连接变的十分低效。HTTP/2 通过让所有数据流共用同一个连接,可以更有效地使用 TCP 连接,让高带宽也能真正的服务于 HTTP 的性能提升。
这种单连接多资源的方式,减少服务端的链接压力,内存占用更少,连接吞吐量更大;而且由于 TCP 连接的减少而使网络拥塞状况得以改善,同时慢启动时间的减少,使拥塞和丢包恢复速度更快。
首部压缩(Header Compression)
HTTP/1.1并不支持 HTTP 首部压缩,为此 SPDY 和 HTTP/2 应运而生,SPDY 使用的是通用的DEFLATE 算法,而 HTTP/2则使用了专门为首部压缩而设计的 HPACK 算法。
服务端推送(Server Push)
服务端推送是一种在客户端请求之前发送数据的机制。在 HTTP/2 中,服务器可以对客户端的一个请求发送多个响应。Server Push 让 HTTP1.x 时代使用内嵌资源的优化手段变得没有意义;如果一个请求是由你的主页发起的,服务器很可能会响应主页内容、logo 以及样式表,因为它知道客户端会用到这些东西。这相当于在一个 HTML 文档内集合了所有的资源,不过与之相比,服务器推送还有一个很大的优势:可以缓存!也让在遵循同源的情况下,不同页面之间可以共享缓存资源成为可能。
HTTPS协议
HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全。为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。现在的HTTPS都是用的TLS协议,但是由于SSL出现的时间比较早,并且依旧被现在浏览器所支持,因此SSL依然是HTTPS的代名词。
HTTPS在传输数据之前需要客户端(浏览器)与服务端(网站)之间进行一次握手,在握手过程中将确立双方加密传输数据的密码信息。TLS/SSL协议不仅仅是一套加密传输的协议,TLS/SSL中使用了非对称加密,对称加密以及HASH算法。握手过程的简单描述如下:
浏览器将自己支持的一套加密规则发送给网站。
获得网站证书之后浏览器要做以下工作:
如果证书受信任,或者是用户接受了不受信的证书,浏览器会生成一串随机数的密码,并用证书中提供的公钥加密。
使用约定好的HASH计算握手消息,并使用生成的随机数对消息进行加密,最后将之前生成的所有信息发送给网站。
网站接收浏览器发来的数据之后要做以下的操作:
使用自己的私钥将信息解密取出密码,使用密码解密浏览器发来的握手消息,并验证HASH是否与浏览器发来的一致。
使用密码加密一段握手消息,发送给浏览器
浏览器解密并计算握手消息的HASH,如果与服务端发来的HASH一致,此时握手过程结束,之后所有的通信数据将由之前浏览器生成的随机密码并利用对称加密算法进行加密。
HTTP请求方式
请求方式 |
功能及作用 |
GET |
请求获取Request-URI所标识的资源 |
POST |
在Request-URI所标识的资源后附加新的数据 |
HEAD |
请求获取由Request-URI所标识的资源的响应消息报头 |
PUT |
请求服务器存储一个资源,并用Request-URI作为其标识 |
DELETE |
请求服务器删除Request-URI所标识的资源 |
TRACE |
请求服务器回送收到的请求信息,主要用于测试或诊断 |
CONNECT |
保留将来使用 |
OPTIONS |
请求查询服务器的性能,或者查询与资源相关的选项和需求 |
HTTP 状态码
状态代码有三位数字组成,第一个数字定义了响应的类别,且有五种可能取值:
状态码 |
功能及作用 |
1xx |
指示信息--表示请求已接收,继续处理 |
2xx |
成功--表示请求已被成功接收、理解、接受 |
3xx |
重定向--要完成请求必须进行更进一步的操作 |
4xx |
客户端错误--请求有语法错误或请求无法实现 |
5xx |
服务器端错误--服务器未能实现合法的请求 |
详细内容
状态码 |
状态信息 |
功能及作用 |
100 |
Continue |
初始的请求已经接受,客户应当继续发送请求的其余部分。(HTTP 1.1新) |
101 |
Switching Protocols |
服务器将遵从客户的请求转换到另外一种协议(HTTP 1.1新) |
200 |
OK |
一切正常,对GET和POST请求的应答文档跟在后面 |
201 |
Created |
服务器已经创建了文档,Location头给出了它的URL |
202 |
Accepted |
已经接受请求,但处理尚未完成。 |
203 |
Non-Authoritative Information |
文档已经正常地返回,但一些应答头可能不正确,因为使用的是文档的拷贝(HTTP 1.1新) |
204 |
No Content |
没有新文档,浏览器应该继续显示原来的文档。如果用户定期地刷新页面,而Servlet可以确定用户文档足够新,这个状态代码是很有用的。缓存 |
205 |
Reset Content |
Reset Content 没有新的内容,但浏览器应该重置它所显示的内容。用来强制浏览器清除表单输入内容(HTTP 1.1新)。 |
206 |
Partial Content |
客户发送了一个带有Range头的GET请求,服务器完成了它(HTTP 1.1新) |
300 |
Multiple Choices |
客户请求的文档可以在多个位置找到,这些位置已经在返回的文档内列出。如果服务器要提出优先选择,则应该在Location应答头指明 |
301 |
Moved Permanently |
客户请求的文档在其他地方,新的URL在Location头中给出,浏览器应该自动地访问新的URL。 |
302 |
Found |
类似于301,但新的URL应该被视为临时性的替代,而不是永久性的。注意,在HTTP1.0中对应的状态信息是“Moved Temporatily”。 |
303 |
See Other |
类似于301/302,不同之处在于,如果原来的请求是POST,Location头指定的重定向目标文档应该通过GET提取(HTTP 1.1新) |
304 |
Not Modified |
客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。服务器告诉客户,原来缓冲的文档还可以继续使用 |
305 |
Use Proxy |
客户请求的文档应该通过Location头所指明的代理服务器提取(HTTP 1.1新) |
307 |
Temporary Redirect |
类似于301/302,不同之处在于,如果原来的请求是POST,Location头指定的重定向目标文档应该通过GET提取(HTTP 1.1新) |
400 |
Bad Request |
请求出现语法错误 |
401 |
Unauthorized |
客户试图未经授权访问受密码保护的页面。应答中会包含一个WWW-Authenticate头,浏览器据此显示用户名字/密码对话框,然后在填写合适的Authorization头后再次发出请求 |
403 |
Forbidden |
资源不可用。服务器理解客户的请求,但拒绝处理它。通常由于服务器上文件或目录的权限设置导致 |
404 |
Not Found |
无法找到指定位置的资源。 |
405 |
Method Not Allowed |
请求方法(GET、POST、HEAD、DELETE、PUT、TRACE等)对指定的资源不适用。(HTTP 1.1新) |
406 |
Not Acceptable |
指定的资源已经找到,但它的MIME类型和客户在Accpet头中所指定的不兼容(HTTP 1.1新) |
407 |
Proxy Authentication Required |
类似于401,表示客户必须先经过代理服务器的授权。(HTTP 1.1新) |
408 |
Request Timeout |
在服务器许可的等待时间内,客户一直没有发出任何请求。客户可以在以后重复同一请求。(HTTP 1.1新) |
409 |
Conflict |
通常和PUT请求有关。由于请求和资源的当前状态相冲突,因此请求不能成功。(HTTP 1.1新 |
410 |
Gone |
|
411 |
Length Required |
服务器不能处理请求,除非客户发送一个Content-Length头。(HTTP 1.1新) |
412 |
Precondition Failed |
请求头中指定的一些前提条件失败(HTTP 1.1新) |
413 |
Request Entity Too Large |
目标文档的大小超过服务器当前愿意处理的大小。如果服务器认为自己能够稍后再处理该请求,则应该提供一个Retry-After头(HTTP 1.1新) |
414 |
Request URI Too Long |
URI太长(HTTP 1.1新) |
416 |
Requested Range Not Satisfiable |
服务器不能满足客户在请求中指定的Range头。(HTTP 1.1新) |
500 |
Internal Server Error |
服务器遇到了意料不到的情况,不能完成客户的请求。 |
501 |
Not Implemented |
服务器不支持实现请求所需要的功能。例如,客户发出了一个服务器不支持的PUT请求。 |
502 |
Bad Gateway |
服务器作为网关或者代理时,为了完成请求访问下一个服务器,但该服务器返回了非法的应答 |
503 |
Service Unavailable |
服务器由于维护或者负载过重未能应答。例如,Servlet可能在数据库连接池已满的情况下返回503。服务器返回503时可以提供一个Retry-After头。 |
504 |
Gateway Timeout |
由作为代理或网关的服务器使用,表示不能及时地从远程服务器获得应答。(HTTP 1.1新) |
505 |
HTTP Version Not Supported |
服务器不支持请求中所指明的HTTP版本。(HTTP 1.1新) |
版权声明:本站内容全部来自于腾讯微信公众号,属第三方自助推荐收录。《如何优雅的谈论HTTP/1.0/1.1/2.0》的版权归原作者「GOBAT」所有,文章言论观点不代表Lambda在线的观点, Lambda在线不承担任何法律责任。如需删除可联系QQ:516101458
文章来源: 阅读原文
GOBAT微信公众号:gobat2015
手机扫描上方二维码即可关注GOBAT微信公众号