目录
HTTP概述
设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法,它是一个基于 TCP/IP 通信协议来传输数据的应用层协议。
「HTTP 是一个在计算机世界里专门在两点之间传输文字、图片、音频、视频等超文本数据的约定和规范。」
(HTTP通常跑在TCP/IP协议栈
之上,依靠IP协议实现寻址和路由
、TCP协议实现可靠数据传输
、DNS协议实现域名查找
、SSL/TLS协议实现安全通信
。当然,WebSocket、HTTPDNS依赖于HTTP。
HTTP的历史
早在 HTTP 建立之初,主要就是为了将超文本标记语言(HTML)文档从Web服务器传送到客户端的浏览器。也是说对于前端来说,我们所写的HTML页面将要放在我们的 web 服务器上,用户端通过浏览器访问url地址来获取网页的显示内容,但是到了 WEB2.0 以来,我们的页面变得复杂,不仅仅单纯的是一些简单的文字和图片,同时我们的 HTML 页面有了 CSS,Javascript,来丰富我们的页面展示,当 ajax 的出现,我们又多了一种向服务器端获取数据的方法,这些其实都是基于 HTTP 协议的。同样到了移动互联网时代,我们页面可以跑在手机端浏览器里面,但是和 PC 相比,手机端的网络情况更加复杂,这使得我们开始了不得不对 HTTP 进行深入理解并不断优化过程中。
HTTP的基本优化
影响一个 HTTP 网络请求的因素主要有两个:带宽和延迟。
-
带宽:如果说我们还停留在拨号上网的阶段,带宽可能会成为一个比较严重影响请求的问题,但是现在网络基础建设已经使得带宽得到极大的提升,我们不再会担心由带宽而影响网速,那么就只剩下延迟了。
-
延迟:
-
浏览器阻塞(HOL blocking):浏览器会因为一些原因阻塞请求。浏览器对于同一个域名,同时只能有 6 个tcp连接(这个根据浏览器内核不同可能会有所差异),超过浏览器最大连接数限制,后续请求就会被阻塞
-
DNS 查询(DNS Lookup):浏览器需要知道目标服务器的 IP 才能建立连接。将域名解析为 IP 的这个系统就是 DNS。这个通常可以利用DNS缓存结果来达到减少这个时间的目的。
-
建立连接(Initial connection):HTTP 是基于 TCP 协议的,浏览器最快也要在第三次握手时才能捎带 HTTP 请求报文,达到真正的建立连接,但是这些连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大。
-
HTTP1.1 对比 HTTP1.0
-
缓存处理,在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
-
带宽优化及网络连接的使用,HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
-
错误通知的管理,在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
-
Host头处理,在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。
-
长连接,HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。
[
http请求响应完成之后怎么办?TCP 连接就断开了吗?
不一定。这时候要判断Connection
字段, 如果请求头或响应头中包含Connection: Keep-Alive,表示建立了持久连接,这样TCP
连接会一直保持,之后请求统一站点的资源会复用这个连接。
否则断开TCP
连接, 请求-响应流程结束。]
HTTP2.0和HTTP1.X相比的新特性
-
新的二进制格式(Binary Format),HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。
-
多路复用(MultiPlexing),即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。
-
header压缩,如上文中所言,对前面提到过HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。
-
服务端推送(server push),同SPDY一样,HTTP2.0也具有server push功能。
HTTPS与HTTP的一些区别
-
HTTPS协议需要到CA申请证书,一般免费证书很少,需要交费。
-
HTTP协议运行在TCP之上,所有传输的内容都是明文,HTTPS运行在SSL/TLS之上,SSL/TLS运行在TCP之上,所有传输的内容都经过加密的。
-
HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
-
HTTPS可以有效的防止运营商劫持,解决了防劫持的一个大问题。
服务器推送是什么
服务端推送能把客户端所需要的资源伴随着index.html一起发送到客户端,省去了客户端重复请求的步骤。正因为没有发起请求,建立连接等操作,所以静态资源通过服务端推送的方式可以极大地提升速度。具体如下:
-
普通的客户端请求过程:
-
服务端推送的过程:
HTTP存在的位置
处于 TCP/IP 网络分层模型中的第一层「应用层」。
应用层的其它协议还有:
-
FTP:文件传输协议,用来在客户机和FTP服务器之间传输文件。
-
DNS域名系统:提供域名到IP地址之间的解析服务。
-
SMTP:邮件发送协议,用户通过SMTP服务器发送邮件。
- 等等
HTTP特点
常问知识点,重要指数:🌟🌟🌟🌟🌟
-
HTTP协议支持客户端/服务端模式,也是一种请求/响应模式的协议。
-
灵活可扩展:一个是语义上的自由,只规定了基本格式,其它的各部分没有严格的限制;第二个它允许传输任意类型的数据对象,例如文本、图片、音频等,传输的类型由Content-Type加以标记。
-
可靠传输,HTTP 基于 TCP/IP,因此把这一特性继承了下来。
-
无状态,也就是说HTTP请求不具备保存之前发送过的请求或响应的功能,每一次请求都是独立无关的。
-
概念:建立一次TCP连接即可进行多次请求或响应的交互
-
产生原因:HTTP的初始版本是每进行一次HTTP通信就要断开一次TCP连接,下次再进行的时候又要重新连接断开。再如今请求的资源越来越大,每次请求如果都有无谓TCP连接和断开是很大的开销。
-
特点:只要有一方没有明确的提出断开连接,则保持TCP连接状态。
-
优点:减少了TCP连接和断开的造成的额外开销,减轻了服务端的负载,Web页面加载变快
-
注意点:在HTTP/1.1中所有的连接默认都是持久连接的(也就是首部字段 Connection: keep-alive,若是想要关闭则将值设置为 close),但是HTTP/1.0并未标准化
HTTP的缺点
常问知识点,重要指数:🌟🌟🌟🌟🌟
简单来说:
-
明文传输(不加密),内容可能被窃听。
-
无法验证报文的完整性,内容可能被篡改。
-
不验证通信方的身份,有可能遭遇伪装。
-
无状态,它是缺点也是优点吧,分不同的场景。
-
队头阻塞。
详细来说:
-
明文传输(不加密),内容可能被窃听。协议里的报文不使用二进制数据,而是文本形式
-
无法验证报文的完整性,内容可能被篡改。这里说的完整性也就是指信息的准确度 因为接收方或者发送方没有办法确认对方发送过来的数据在中间有没有被篡改
-
不验证通信方的身份,有可能遭遇伪装。因为HTTP协议中不会对通信方进行确认 任何人都可以发送请求,而且服务器它对收到的请求也不会进行确认,只要收到了请求就会返回一个响应(当然这个只是在发送端的IP地址或者端口号没被Web服务器设定限制访问的前提下)
- 无状态,不具备保存之前发送过的请求或响应的功能。它是缺点也是优点吧:
-
对于一些长连接的场景需要保存上下文信息,以免传输重复的数据。
-
对于一些应用只是为了获取数据不需要保存上下文信息,无状态减少了网络开销。
-
- 队头阻塞:
-
其根本原因在于HTTP是基于 请求-响应 的模型,在同一个TCP长连接中,前一个请求没有得到响应,后面的请求就会被阻塞。
-
用并发连接 和 域名分片 来解决了这个问题。但并不是从HTTP本身的层面来解决的,只是增加了 TCP 连接,分摊风险而已。
-
HTTP/2中的多路复用从HTTP本身的层面解决了这个问题
-
和TCP队头阻塞的区别:TCP传输的单位是数据包,它的队头阻塞表示的是前一个报文没有收到便不会将下一个报文上传给HTTP。而HTTP队头阻塞是在 请求-响应 层面,前一个请求还没有处理完,后面的请求就被阻塞。
-
方法种类
常问知识点,重要指数:🌟🌟🌟🌟🌟
-
GET:获取资源,幂等操作
-
HEAD:获取报文首部,和GET很像但是不返回报文主体,幂等操作
-
POST: 创建或更新资源,非幂等操作
-
PUT: 创建或更新资源本身,幂等操作
-
PATCH:对资源进行局部更新,非幂等操作
-
DELETE:删除资源,和PUT功能相反,幂等操作
-
OPTIONS:查询服务器端支持的HTTP方法种类(幂等操作):
GET和POST的区别
(这里我用的是三元总结的一份答案+自己的一些理解)
-
从缓存的角度上说,GET会被浏览器主动缓存下来,留下历史记录,但是POST不会。
-
从编码的角度上说,GET只能进行URL编码,它只能接收ASCII字符,但是POST没有限制。
-
从参数的角度上说,GET一般放在URL上传递参数,POST放在请求体里,更适合传递敏感信息。
-
从幂等的角度上说,GET是幂等的,而POST不是。
-
不过据我了解的,其实GET和POST本质上都是TCP连接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致它们在应用过程中体现出一些不同。
-
还有可以从TCP的角度上说,GET请求会把请求报文一次性发出去,但是POST会分为两个TCP数据包。首先发送的是header部分,若是服务器响应100(continue),则会发送body部分,当然「火狐」浏览器除外,它的 POST 请求只发一个 TCP 包。
(这时候面试官可能还会追加着问你:既然POST要分为两个TCP数据包发送,那GET是不是会比POST更有效啊)
你可以这样回答:
-
首先,GET和POST都有它们自己的语义的,最好不要混用
-
另外,虽然说POST会分为两个数据包发送,但是其实在网络条件好的情况下,发一次包和发两次包的相差的时间基本可以被无视了。并且在网络条件差的情况下,两次包的TCP在验证数据包的完整性上还有更大的优点。
-
再者,也并不是所有的浏览器的POST请求都会发送两次TCP数据包的,比如火狐就不会。
服务端收到不支持的方法会如何处理
当服务端收到不支持的方法时,会返回 405 Method Not Allowed
,并且会把所有支持的方法写入响应报文首部字段Allow
中返回。
HTTP状态码
重要指数:🌟🌟🌟🌟🌟
1xx 信息性
「请求已经接收到,需要进一步处理才能完成,但是HTTP/1.0 不支持。」
-
101 Switching Protocols
:在HTTP升级为WebSocket时,如果服务器同意变更,则返回 101。
2xx 成功状态
「成功处理请求。」
-
200 OK
:请求成功,通常返回的数据中带有响应体。 -
204 No Content
:意思和200
一样,不过返回的数据中不带有响应体。 -
206 Partial Content
:客户端进行了范围请求且服务端正常处理,响应报文的首部应该还有Content-Range
字段指定实体的范围。使用场景为HTTP分块下载和断点续传。
3xx 重定向
「重定向状态,资源位置发生变动,需要重新请求。」
-
301 Moved Permanently
:永久重定向,最新的URI为响应报文首部的Location
字段。场景是:例如你的网站换了地址了,之前的地址不用了,若用户还是从之前的地址进的话则会返回301
且在Location
中带上最新的URI。且浏览器默认会做缓存优化,减少服务器压力,在第二次访问的时候自动访问重定向的那个地址。 -
302 Found
:临时重定向,和301
不同,它表示请求的资源临时被移动到了别的URI上,因为是暂时的,所以不会被缓存。 -
303 See Other
:临时重定向,请求的资源临时被移动到了别的URI上,但是明确表示客户端应该使用GET方法获取资源。 -
304 Not Modefied
:客户端带条件请求时虽未满足条件但是也允许返回该资源,它虽然被划分在3xx
中,但其实和重定向没有关系。场景例如:协商缓存成功就会返回304 Not Modefied
,表示请求的资源在服务器上并未发送改变,告诉请求者可以使用缓存。 -
307 Temprary Redirect
:临时重定向,但是比302
更加明确,重定向的请求方法和实体都不允许变动。场景例如:HSTS
协议,强制客户端使用https
建立连接,比如你的网站从HTTP
升级到了HTTPS
,而你还是通过http://xxx
访问的话,就会返回307 Internal Redirect
。
三种临时重定向简单比较:
-
302 Found
,基本的临时重定向 -
303 See Other
,明确表示客户端应该使用GET
方法 -
307 Temprary Redirect
,请求方法和实体都不允许变动
4xx 客户端错误
「客户端出现错误。」
-
400 Bad Request
:请求报文中存在语法错误,但是没有具体指出是哪里。 -
401 Unauthorized
:需要有通过HTTP认证的认证信息或者表示用户认证失败。 -
403 Forbidden
:请求资源被拒绝,原因是:比如法律禁止、信息敏感。 -
404 Not Found
:请求资源未找到,表示没在服务器上找到相应的资源。
5xx 服务端出现错误
「服务端出现错误。」
-
500 Internal Server Error
:服务器内部错误,但是没有具体指出是哪里,和400
有点像。 -
501 Not Implemented
:表示客户端请求的功能还不支持 -
502 Bad GateWay
:服务器自身是正常的,但是代理服务器无法获取到合法响应(点外卖时外卖小哥没送) -
503 Service Unavailable
:服务器内部处于超负载状态或进行停机维护(就像是本店今天不开张)
keep-alive断开
说一下 keep-alive 来判断异常断开的原理,其实 keep-alive 的原理就是 TCP 内嵌的一个心跳包。
以服务器端为例,如果当前 server 端检测到超过一定时间(默认是 7,200,000 milliseconds ,也就是 2 个小时)没有数据传输,那么会 向client 端发送一个 keep-alive packet (该 keep-alive packet 就是 ACK 和当前 TCP 序列号减一的组合),此时 client 端应该为以下三种情况之一:
1. client 端仍然存在,网络连接状况良好。此时 client 端会返回一个 ACK 。 server 端接收到 ACK 后重置计时器,在 2 小时后再发送探测。如果 2 小时内连接上有数据传输,那么在该时间基础上向后推延 2 个小时。
2. 客户端异常关闭,或是网络断开。在这两种情况下, client 端都不会响应。服务器没有收到对其发出探测的响应,并且在一定时间(系统默认为
1000 ms )后重复发送 keep-alive packet ,并且重复发送一定次数( 2000 XP 2003 系统默认为 5 次 , Vista 后的系统默认为 10 次)。
3. 客户端曾经崩溃,但已经重启。这种情况下,服务器将会收到对其存活探测的响应,但该响应是一个复位,从而引起服务器对连接的终止。