对于http/http2的一些总结

<article data-v-3f24c1de="" itemscope="itemscope" itemtype="http://schema.org/Article" class="article" data-v-73cfe9db="">

http是前端面试当中经常会被问到的,虽然前端对http的运用不是很多,但是对于前端来说,http的优化,http的调试,看懂一些http的原理还是很有必要的

http缓存

http的缓存,是前端优化的一种很有效的方式,通过设置http缓存,可以做到不需要去服务器请求资源,做到减少http请求的效果,从而达到提高网站响应速度的优化。http缓存中,存在强制缓存和协商缓存。其实这两种缓存都是需要在服务器端设置的,但是前端也需要了解这方面的知识,所以略做了解。

强制缓存

强制缓存服务器的response告诉浏览器,这个资源到什么时候为止/过多久才过期,在这段时间内,不需要到我这里来获取,如果我们的资源很少改变的情况下,建议在服务器这边设置过期时间长点。
expires: 在http1.0的,可以通过expires设置过期时间(具体时间),告诉浏览器缓存到什么时候为止。缺点是服务器时间和浏览器时间可能不同步,或者一方时间不准,那么缓存设置的时间就不对了。
cache-control: max-age,在http1.1中,通过设置response的cache-control的max-age告诉浏览器,过多久才过期,是基于浏览器的时间的,所以缓存过期时间始终是对的。
强制缓存能命中的话,浏览器会返回200(from disk cache)的状态码。

<figure>[图片上传中...(image-87163b-1542967619282-8)]

<figcaption></figcaption>

</figure>

<figure>[图片上传中...(image-f73143-1542967619282-7)]

<figcaption></figcaption>

</figure>

这里多说一句,如果你想要避免浏览器缓存的话,可以改变请求资源的url,比如加上哈希值,这也是现在用的很多的方式。

<script src="http://..../detail.build.469ee1c5.js"></script>
复制代码

协商缓存

协商缓存,是服务器告诉浏览器一些唯一的标识(ETag)或者文件最后修改时间(Last-Modified),来让浏览器判断资源是否在服务器端改变了,从而决定读取的资源是从缓存中还是从浏览器返回的response中读取。

last-modified/if-since-last-modified,浏览器第一次请求服务器资源的时候,服务器会通过response返回返回资源最新的修改时间(last-modified)给浏览器,浏览器保存这个时间,然后下次请求的时候,在请求头部中将该时间设置到if-since-last-modified中,服务器接收到这个请求,发现有if-since-last-modified的缓存验证时,验证缓存的新鲜度(通过判断服务器上的资源的最后更新时间与if-since-last-modified的时间对比),如果新鲜,则返回304的状态码。浏览器解析到304的状态码,直接读取缓存。

<figure>[图片上传中...(image-bb2814-1542967619282-6)]

<figcaption></figcaption>

</figure>

etag/if-none-match,浏览器第一次请求服务器资源时,服务器会在通过response返回该资源内容对应的哈希值(etag),浏览器保存这个值,下次请求的时候,将请求头if-none-match设置为该值,服务器接收到这个请求,发现有if-none-match的缓存验证时,验证缓存的新鲜度(通过判断服务器上的资源内容的哈希值和if-none-match的进行对比),如果新鲜,则返回304的状态码。浏览器解析到304的状态码,直接读取缓存。

<figure>[图片上传中...(image-82183b-1542967619282-5)]

<figcaption></figcaption>

</figure>

last-modified vs etag

last-modified是基于时间的,只能精确到秒,如果资源修改得很频繁,那么有可能内容已经修改了,但是秒数还没更新到,那么浏览器就会误以为没有更新,直接读取缓存了。还有一点,如果资源的内容没有改变,但是最后修改时间改变了,那么浏览器也会误以为资源没更新。而etag正好克服了last-modified的缺点。因此,建立开启etag的协商缓存。

http验证的流程图:

<figure>[图片上传中...(image-5a1119-1542967619282-4)]

<figcaption></figcaption>

</figure>

http1.0和http1.1

我们知道,http是建立在TCP连接上的,即先要通过三次握手建立TCP连接,然后再发送http请求。在http1.0中,一个http当中只能一个request和一个response,然后TCP就关闭,下次再发送http,需要再建立TCP连接,所以http请求一多,TCP建立和关闭就会很频繁,很浪费资源。所以,在http1.1当中,通过connection: keep-alive可以实现一个TCP连接中,可以发送多个http请求,这样浏览器可以继续通过相同的TCP连接发送多次请求,可以避免多次建立/释放tcp带来的损耗。

优点:一次TCP连接中可以发送多次http请求,所以避节省每次发送http都要建立TCP连接的时间和宽带。
缺点:TCP长时间的连接,容易导致系统的资源的无效占用,浪费系统资源。

网上有个总结:
1、当你的Server内存充足时,KeepAlive =On还是Off对系统性能影响不大。
2、当你的Server上静态网页(Html、图片、Css、Js)居多时,建议打开KeepAlive 。
3、当你的Server多为动态请求(连接数据库,对文件系统访问较多),KeepAlive 关掉,会节省一定的内存,节省的内存正好可以作为文件系统的Cache(vmstat命令中cache一列),降低I/O压力。

还有一点,http1.1添加了Cache-Control的max-age来进行http的强缓存,使用想对时间,单位是s,克服了http1.0中的expired的使用具体时间,如果时间表示出错或者没有转换到正确的时区都可能造成缓存生命周期出错问题。

http2.0和http1.0

1、http2是采用二进制进行传输数据的,而http1是文本传输,对比起来二进制传输的解析和优化上更具有优势,什么优势下面会讲到(可以分帧,并行请求)。
2、http2对头部进行的压缩,能够减少头部占用的网络流量。
3、http2实现了多路复用,同一域名不管发送多少请求,也只建立一路连接,这样就突破了浏览器对同一域名并发数的限制了。
4、http2支出服务器端推送。

http1.1 keep-alive和http2多路复用的区别

我们很容易混淆这两者的区别,会误以为两者都是在一个TCP中,可以发送多次http请求/接受http响应的,但实际上,两者存在着本质上的区别,看网上的一张图:

<figure>[图片上传中...(image-b904bd-1542967619282-3)]

<figcaption></figcaption>

</figure>

从图中大家应该能分清楚差别了吧。keep-alive虽然能够使得一次TCP连接发送多次http请求,但是因为http1是基于文本传输的,是串行的文件传输,所以必须保证传输的顺序,因此一个请求必须等待另一个请求完成以后才能继续,请求是串行的。

http1.1的keep-alive只是避免在每次请求当中,都重新开启一个TCP连接,避免TCP连接所带来的时间和宽带的消耗,但每个http请求还是串行发送的,很容易造成堵塞。所以为了提高页面响应速度,于是有了并发开启多个TCP连接的优化,并行建立多个TCP连接,但基于开启TCP连接需要消耗CPU和内存等系统资源,所以浏览器都对TCP的并发有限制,一般限制为6个,服务器也对TCP的连接数也是有限制的。
回到http2,我们知道http2是二进制传输数据的,数据是以帧为单位发送的(当然每个帧都是有顺序标识的,确保服务器接收后能恢复顺序),一个请求(消息)被分为一块一块的帧进行发送,这些帧可以交错发送,不管是哪个请求的帧都可以交错发送(http2中的帧包含的http头部信息等,确保帧最后能够恢复成消息),因此可以做到并行发送请求,避免拥堵。

关于两者在一个tcp连接中能发送多少个http请求的问题,http1.1当中是按时间来算的,一定时间内,同一域名只建立一次TCP连接,这段时间的http请求在这个TCP连接的基础上发送和响应,以达到提高请求效率的问题。而http2的请求是基于流的,即所有的请求都共用一个tcp连接,一个http请求就是一个流,一个 TCP 连接成,可以承载任意数量的数据流。

<figure>[图片上传中...(image-5889f5-1542967619282-2)]

<figcaption></figcaption>

</figure>

最后我们通过网上的两张图查看下区别:

<figure>[图片上传中...(image-797b3-1542967619282-1)]

<figcaption></figcaption>

</figure>

htt1,串行请求,一个请求的发送,必须等待一个请求响应后才能开始。

<figure>[图片上传中...(image-a586e4-1542967619282-0)]

<figcaption></figcaption>

</figure>

http2,并行请求,所有请求被划分为一个一个的帧一次性全部发出去。

关于http post和get请求的区别

GET在浏览器回退时是无害的,而POST会再次提交请求。
GET产生的URL地址可以被Bookmark,而POST不可以。
GET请求会被浏览器主动cache,而POST不会,除非手动设置。
GET请求只能进行url编码,而POST支持多种编码方式。
GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
GET请求在URL中传送的参数是有长度限制的,而POST么有。
对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
GET参数通过URL传递,POST放在Request body中。
(本标准答案参考自w3schools)

状态码

100 继续,http POST请求有时会发送两次tcp包,一次header一次body,第一次服务器会返回100的状态码,告诉浏览器可以发送body了
101 协议升级,比如升级为websocket

200 ok,也可以是缓存命中返回的状态码

301 暂时重定向 302 永久重定向 304 协商缓存,服务器告诉浏览器从缓存中读取

400 请求无效,和服务器端没对应起来
401 需要用户验证
403 服务器端已接收到,但拒绝执行

500 服务器错误

从浏览器输入url到显示页面的整个流程

1、查看有缓存,有缓存且未过期,直接读取缓存
2、浏览器解析url,组装成一个http报文
3、解析域名下的ip地址(DNS查询)
4、打开一个socket与目标ip、端口建立tcp连接
5、发送http请求到服务器
6、服务器解析请求,并将请求转发到对应的处理程序当中
7、服务器检查http中是否有缓存验证信息,判断缓存是否新鲜,如果新鲜返回304状态码
8、处理程序处理完数据,准备http响应
9、服务器将http响应报文通过tcp连接发送回浏览器
10、浏览器接收http响应,根据情况关闭tcp连接或者保留重用(keep-alive)
11、浏览器检查http状态码
12、判断资源是否可以缓存,可以的话进行缓存
13、对响应进行解码(gzip解码)
14、根据资源类型决定如何处理,如果是js的话,则下载执行,如果是html的话,则交给浏览器进行渲染显示

websocket的实现原理

websocket的实现是基于http的,用http实现握手,然后使用TCP的全双工通讯的协议,这样就可以实现客户端和服务器端的长连接,实现实时通讯。要支持websocket必须在http1.1中使用以下两个属性:
Connection: upgrade
Upgrade: websocket

Connection为upgrade告诉服务器,我不在使用http了,要升级协议了,服务器不需要转发upgrade所在的域;upgrade告诉服务器,客户端希望使用建立好的TCP连接,切换到websocket协议(http/websocket都是基于tcp的)。

这边文章是通过阅读网上关于http的一个总结,加上自己的理解写成的,如果有什么不对的,欢迎在评论中指正。
参考链接:
developers.google.com/web/fundame…
web.jobbole.com/92773/
segmentfault.com/a/119000001…

</article>

作者:大雄没了哆啦A梦
链接:https://juejin.im/post/5b80ecc36fb9a019cd4e5d99
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

猜你喜欢

转载自blog.csdn.net/sinat_17775997/article/details/84401662
今日推荐