HTTP缓存和连接

99 阅读6分钟

如果有的资源更新频率不高,并且体量比较大的话,那直接取缓存的数据效率就会高很多。

主要存在客户端缓存、服务器缓存。

客户端缓存

Cache-Control

在请求头中,缓存是通过Cache-Control字段来控制的。

image.png

no-cache

顾明思议,没有缓存。它会去服务器校验是否过期,并且是否有最新的资源。如果有,则获取最新的。

max-age

是个相对值,单位是,优先级高于Expires,表示的是Cookie的有效时间。

在HTTP缓存中,它的用法类似,表示的是缓存的有效时间,如:

Cache-Control:max-age=6

从报文请求开始算,6秒后缓存会失效。如果max-age=0,则缓存立即失效,请求服务器会重新请求最新的数据。

no-cachemax-age=0来说,效果基本相同,都是要请求服务器的最新数据。

服务器缓存

在响应头中,其实也是通过Cache-Control来控制缓存,常用的属性值有:

no-cache

和客户端用法基本是一样的。

max-age

表示的是响应报文创建之后的时间,不是客户端接收到报文的时间,也就是说响应报文创建后,离开服务器开始的时间算起,如果此时网速传输速度很慢,需要5s,而max-age=4,那就仅剩下1s缓存时间,甚至客户端接收到的时间超过了max-age的值,那缓存基本就超时了。

no-store

不允许缓存。对于更新很频繁的页面或数据,就不需要缓存,例如秒杀、抢购页面,分秒必争,缓存就会坏大事。

must-revalidate

和no-cache有一定的类似,缓存没过期就可以继续使用,但如果过期了,需要认证,认证成功后仍可以继续使用,这是和no-cache不一样的地方。

短连接

在HTTP早期,短连接也可以称为无连接。之所以叫短连接,指的是连接时间非常短,当客户端发起请求时连接打开,然后服务器响应后,连接即关闭。

在我们现在开发中,动辄十几二十个请求,如果每个请求都是打开连接 -> 发送请求 -> 响应 -> 关闭请求这种操作顺序的话,效率可想而知,每次请求的连接开关实在是多余的操作,严重影响效率。为了解决这个问题,长连接应运而生。

长连接

长连接就是为了解决短连接出现的短板,它与短连接不同的是仅在开始时打开连接,然后到最后才会关闭请求,中间可以发送多个请求和响应,请求和响应越多,则长连接相对短连接的效率则越高。

长连接也存在一个问题,长究竟有多长,什么时候关闭呢?如果一直不关闭,那服务器时刻都在等待着,也是一种资源的损失和浪费。

HTTP/1.1版本协议中,默认使用长连接,也可以在请求头字段中加入Connection:keep-alive,明确表示服务器要支持长连接,服务器也可以在响应中返回Connection:keep-alive来表示支持。如果需要关闭的话,在请求头中发送Connection:close,服务器接收到会调用Socket API关闭TCP连接。

对头阻塞

对头阻塞,也可以称为对首阻塞。顾名思义,就是被对头请求阻塞了,后面的请求一直在等待中。

为什么会出现对头阻塞呢?

因为HTTP协议的请求-响应模型遵循的是一收一发的先进先出模式,对头的请求未收到响应,则不会往后继续,是同步的操作。

并发连接

为了解决对头阻塞的问题,不能让一个请求把后面所有请求都卡死。HTTP规定可以对同一个域名发起多个长连接,这就是并发连接,虽然可以并发多个,但不能滥用,要不然服务器很快就会崩溃,所以RFC2616规定每个客户端最多只能发送2个并发请求,在实践中证明2个远不够,被众多浏览器所忽视,主流浏览器一般都在6-8个,后来RFC7230就顺势取消了2的限制。

域名分片

还是为了提高并发数而产生了,刚说了并发连接是说:同一个域名同一个客户端可以并发的数量,那如果请求的多个域名指向的是同一个服务器,这样是不是变相的增加了并发数了,这就是域名分片。

Cookie机制

我们知道,长连接在多个请求期间不会主动关闭连接通道,但请求服务器资源是需要有权限控制的,资源不能随便共享。多个请求间怎么证明是同一个客户端用户发出的,就需要用到Cookie。因为HTTP是无状态的,多个请求间它是不会记住你的,上个请求告诉它我是小明,哪怕1毫秒后再次请求,你仍需要证明你是小明。

Cookie有时候被翻译为原始的小甜饼,其实是不对的,它指的是不透明数据。

工作过程

客户端第一次访问服务器时,服务器并不知道它是谁,响应后会在响应头中加入Set-Cookie字段,把Cookie信息传递到客户端,由客户端保存,当客户端下次再发请求的时候,会把Cookie字段带上,这样服务器就知道它是谁了。

响应头中Set-Cookie可能存在多个,但在请求头中不会有多个Cookie字段,而是把多个Set-Cookie值合并,用;分号隔开放入Cooike中。

有效期

描述Cookie有效期有两个属性值:ExpiresMax-Age

Expires是个绝对值,相当于截止日期,到期就会结束,Max-Age是个相对值,单位是秒,表示的是浏览器收到Cookie报文开始算,再加上Max-Age的时间,就是最终的失效时间。

这两个字段可以同时出现,最终值也可以不同,优先取Max-Age的值。

作用域

作用域的设置也是两个字段,DomainPath,里面的值分别是域名和请求路径,在发送请求时,客户端会根据请求的URI和请求头中这两个字段进行对比,如果不一致,则不会发送Cookie信息。

安全性

像浏览器会提供获取Cookie的API:document.cookie,这样就会带来风险,大家都听说过跨站脚本攻击(XSS)就是这样的。

所以就定义出了HttpOnly字段:只能通过HTTP协议传输Cookie,其他方式禁止。

其实Cookie,特别是在浏览器中都能看到明文Cookie,几乎都是没有安全性可言的,现在的用户信息认证就很少会直接用Cookie来认证了。