大家常提起 HTTP 协议是无状态的,其指代的“无状态”是什么?常见的观点有:
- 无状态代表相同的请求参数总是能返回相同的结果
- HTTP 本身的设计是无状态的,增加了有状态协议头(Cookie/Session)后变成了有状态协议
对于第一个观点显而易见是错误的,它的表示更倾向于“幂等性”,这往往无法由协议本身保证,还需要服务器进行“有状态”的响应(若服务器不进行状态的持久化,当然无法做到幂等);而第二个观点听起来就靠谱很多,通过 Cookie/Session 进行状态维护从而保证了有状态。但我们可以考虑下 Cookie 或 Session 保证的是谁的状态?一般情况下,它们保证了后端服务器的状态,而非 HTTP 协议的状态。因此对于最初的问题 HTTP 协议的”无状态“,我们是不是应该从协议的本身出发呢?
什么是”无状态“协议
对于”有状态“协议来说,多次请求间往往包含关联,就比如之前提到的服务端依赖 Cookie/Session 进行状态维护来保证关联,但区别在于有状态协议的状态维护应由协议本身来保证,换句话说,“有状态”协议本身存在会话(Session),一般和连接绑定的
。比如 TCP 连接,传输双方是需要进行”有状态“交互(双方在三次握手后均进行状态信息的保存),且会话会随着连接断开而结束。反过来说,“无状态”协议本身不存在会话概念,其每个请求无论在哪个连接都是完全独立且正确的(即不会和先前的请求产生关联)
。
Cookie/Session 所带来的会话不属于协议本身的状态,协议本身也无法应用这些状态。这种状态可以理解为应用程序基于协议实现的”有状态“应用
众所周知 HTTP 协议是利用 TCP 进行数据传输的,那么是否利用 TCP 进行数据传输的协议都是”有状态“协议呢?当然不是,因为它们本身并没有强关联,HTTP 并不是基于 TCP 的协议,它们处于 OSI 的不同层次(HTTP 协议属于应用层协议,TCP 协议属于传输层协议),如果你想的话,也通过命名管道提供 HTTP 服务,因此即使 TCP 协议是“有状态”的,也不能以此判断 HTTP 协议也是“有状态”的
。
HTTPS 协议本质上是在应用层和传输层中间加入了 SSL 协议(严格来说,HTTPS 协议不算单独的协议),SSL 协议本身也需要通过握手(身份验证)来保持会话,因此 SSL 协议也是”有状态“协议
HTTP 协议是”无状态“协议吗?
分清楚”有状态“/”无状态“协议后,我们可以分析一下 HTTP 协议是否为”无状态“协议:
HTTP/1.0 时代每个 TCP 连接只能发送一个请求,因此无法在连接中产生会话的概念,显而易见
HTTP/1.0 协议属于“无状态”协议
。HTTP/1.1 时代引入了持久连接,即 TCP 连接默认不关闭,可以被多个请求复用。但此时的连接复用仅仅是为了提高传输效率,keep-alive 的默认情况下,它的若干个请求会排队串行化单线程处理,即后面的请求等待前面请求的返回才能获得执行机会,除此之外没有任何优化,因此
HTTP/1.1 协议也属于“无状态”协议
。HTTP/1.1 实际上还支持 pipeline,即连续发送一组没有相互依赖的请求而不必等到上一个请求先结束,但它仍然存在线头阻塞的问题(响应仍然得串行化),使用这项特性需要浏览器支持,且仍然没有对会话的支持
HTTP/2.0 时代的报头压缩(HPACK,即客户端和服务器都维护之前看见的标头字段的列表),GOAWAY 帧或流控的特性都标志着会话的诞生,因此
HTTP/2.0 协议属于“有状态”协议
。