面试题:从 URL 在浏览器被输入到页面展现的过程中发生了什么?
延伸:
- 现代浏览器在与服务器建立了一个 TCP 连接后是否会在一个 HTTP 请求完成后断开?什么情况下会断开?
- 一个 TCP 连接可以对应几个 HTTP 请求?
- 一个 TCP 连接中 HTTP 请求发送可以一起发送么(比如一起发三个请求,再三个响应一起接收)?
- 为什么有的时候刷新页面不需要重新建立 SSL 连接?
- 浏览器对同一 Host 建立 TCP 连接到数量有没有限制?
| HTTP/1.0 | HTTP/1.1 | HTTP/2 |
浏览器在与服务器建立了一个 TCP 连接,并完成一个 HTTP 请求后,TCP 连接的状态 | 服务器在发送完一个 HTTP 响应后,会断开 TCP 连接;浏览器与服务器只保持短暂的连接,连接无法复用 | TCP连接默认不会断开(Connection: keep-alive);除非在请求报头中声明 Connection: close 才会在请求完成后关闭连接。HTTP/1.1把 Connection 头写进标准,并且默认开启持久连接 |
|
一个 TCP 连接可以对应的 HTTP 请求的个数 | 一个 | 单个 TCP 连接在同一时刻只能处理一个请求,但如果维持连接,是可以发送多个 HTTP 请求的;任意两个 HTTP 请求从开始到结束的时间在同一个 TCP 连接里不能重叠;虽然 HTTP/1.1 规范中规定了 Pipelining 来试图解决这个问题,但是这个功能在浏览器中默认是关闭的 | HTTP/2提供了 Multiplexing 多路传输特性,可以在一个 TCP 连接中同时并行完成多个 HTTP 请求 |
打开图片非常多的网页的过程 | 默认一个TCP 连接进行一次HTTP请求。但是也可以像HTTP/1.1那样;虽然标准中没有设定,但某些服务器对 Connection: keep-alive 的 Header 进行了支持 | 开多个TCP连接顺序下载; Chrome 最多允许对同一个 Host 建立六个 TCP 连接。不同的浏览器有一些区别。 | 多路复用允许同时通过单一的 HTTP/2 连接发起多重的“请求-响应”消息;如果图片都是 HTTPS 连接并且在同一个域名下,那么浏览器在 SSL 握手之后会和服务器商量能不能用 HTTP/2,如果能的话就使用 Multiplexing 功能在这个连接上进行多路传输。未必所有挂在这个域名的资源都会使用一个TCP连接去获取,但是可以确定的是Multiplexing 很可能会被用到。 |
备注:
Pipelining
在 HTTP/1.1 存在 Pipelining 技术可以完成这个多个请求同时发送,但是浏览器默认关闭。
先来看一下 Pipelining 是什么,RFC 2616 中规定了:
A client that supports persistent connections MAY "pipeline" its requests (i.e., send multiple requests without waiting for each response). A server MUST send its responses to those requests in the same order that the requests were received.
一个支持持久连接的客户端可以在一个连接中发送多个请求(不需要等待任意请求的响应)。收到请求的服务器必须按照请求收到的顺序发送响应。
至于标准为什么这么设定,我们可以大概推测一个原因:由于 HTTP/1.1 是个文本协议,同时返回的内容也并不能区分对应于哪个发送的请求,所以顺序必须维持一致。比如你向服务器发送了两个请求 GET/query?q=A 和 GET/query?q=B,服务器返回了两个结果,浏览器是没有办法根据响应结果来判断响应对应于哪一个请求的。
Pipelining 这种设想看起来比较美好,但是在实践中会出现许多问题:
- 一些代理服务器不能正确的处理 HTTP Pipelining。
- 正确的流水线实现是复杂的。
- Head-of-line Blocking 连接头阻塞:在建立起一个 TCP 连接之后,假设客户端在这个连接连续向服务器发送了几个请求。按照标准,服务器应该按照收到请求的顺序返回结果,假设服务器在处理首个请求时花费了大量时间,那么后面所有的请求都需要等着首个请求结束才能响应。
所以现代浏览器默认是不开启 HTTP Pipelining 的。
HTTP
超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式、协作式和超媒体信息系统的应用层协议。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。通过HTTP或者HTTPS协议请求的资源由统一资源标识符(Uniform Resource Identifiers,URI)来标识。
HTTP 协议是以 ASCII 码传输,基于请求与响应模式的、无状态的,建立在 TCP/IP 协议之上的应用层规范。
HTTP协议主要的版本有3个,分别是HTTP/1.0、HTTP/1.1和HTTP/2。HTTPS是另外一个协议,简单讲是HTTP的安全版。
短暂连接和持久连接图(左HTTP/1.0,右HTTP/1.1)
HTTP/2
- 二进制分帧:在HTTP/2中,在应用层(HTTP2.0)和传输层(TCP或者UDP)之间加了一层:二进制分帧层。在二进制分帧层中, HTTP/2 会将所有传输的信息分割为更小的消息和帧(frame),并对它们采用二进制格式的编码。
- 多路复用:多路复用允许同时通过单一的HTTP/2.0连接发起多重的请求-响应消息。
HTTP2的请求的TCP的connection一旦建立,后续请求以stream的方式发送。每个stream的基本组成单位是frame(二进制帧)。客户端和服务器可以把 HTTP 消息分解为互不依赖的帧,然后乱序发送,最后再在另一端把它们重新组合起来。
HTTP2.0 通信都在一个连接上完成,这个连接可以承载任意数量的双向数据流。
- header压缩:HTTP/1.1的header带有大量信息,而且每次都要重复发送。HTTP/2 为了减少这部分开销,采用了HPACK 头部压缩算法对Header进行压缩。
- 服务端推送:简单来讲就是当用户的浏览器和服务器在建立连接后,服务器主动将一些资源推送给浏览器并缓存起来的机制。
参考:
1. 夺命连环问:一个 TCP 连接可以发多少个 HTTP 请求?
2 Java 9和Spring Boot 2.0纷纷宣布支持的HTTP/2到底是什么?