本文是学习中的一些简要记录,不能尽善尽美,如果有遗漏或错误的地方,恳请朋友指正,共同进步
不知道你是否有过下面这些疑问:
-
为什么通常在第一次访问一个站点时,打开速度很慢,当再次访问这个站点时,速度就很快了?
-
当登录过一个网站之后,下次再访问该站点,就已经处于登录状态了,这是怎么做到的呢?
这些问题都与HTTP请求流程有关,让我们先了解下HTTP的请求流程
浏览器端发起 HTTP 请求流程
如果你在浏览器地址栏里键入极客时间网站的地址:time.geekbang.org/index.html, 那么接下来,浏览器会完成哪些动作呢?下面我们就一步一步详细“追踪”下。
1.构建请求
首先,浏览器构建请求行,构建好后,浏览器准备发起网络请去
GET /index.html HTTP1.1
2.查找缓存
在真正发起网络请求之前,浏览器会查看浏览器缓存中是否有副本,如果副本有效,则会拦截请求,返回副本,直接结束请求,而不去请求服务器。
如果缓存失败,则会发起网络请求
3. 准备目标IP地址和端口号
因为HTTP使用的是TCP连接,所以需要服务器的IP和端口号,我们在浏览器中一般输入的是服务器域名,那么就需要域名到IP的转换,也就是DNS域名解析,所以发起网络请求的第一步是DNS域名解析,当然浏览器还提供了DNS缓存服务,如果这个域名已经解析过了,浏览器会缓存解析的结果,下一次就不需要重新发起网络请求了。 我们可以在URL上获取端口号,如果没有指定端口号,那么使用HTTP默认端口80
4. 等待TCP连接队列
现在我们已经准备好了目标IP地址和端口,是不是可以建立TCP连接了?
NO,Chrome浏览器允许为同一个域名同时最多建立6个连接,如果在同一个域名下同时有10个网络请求,那么后4条只能进入排队等候状态,直至队列中的请求完成。
这个现象也被称对HTTP对头阻塞。解决办法:1.流水线方式(事实是现代浏览器不支持)、2.域名分片
5.建立TCP连接
排队结束后,可以向服务器发起请求了
6.发起HTTP请求
服务器处理HTTP请求流程
1.返回请求
2.断开连接
通常情况下,服务器在返回请求后就会关闭TCP连接,不过HTTP/1.1默认是持久连接,浏览器或服务器在头信息中加入
Connection:Keep-Alive
3.重定向
到这里似乎请求流程快结束了,不过还有一种情况你需要了解下,比如当你在浏览器中打开 geekbang.org 后,你会发现最终打开的页面地址是 www.geekbang.org。
这两个 URL 之所以不一样,是因为涉及到了一个重定向操作。跟前面一样,你依然可以使用 curl 来查看下请求 geekbang.org 会返回什么内容?
curl -I geekbang.org
在控制台输入如下命令:
curl -I geekbang.org
注意这里输入的参数是-I,和-i不一样,-I表示只需要获取响应头和响应行数据,而不需要获取响应体的数据,最终返回的数据如下图所示:
服务器返回响应行和响应头(含重定向格式)从图中你可以看到,响应行返回的状态码是 301,状态 301 就是告诉浏览器,我需要重定向到另外一个网址,而需要重定向的网址正是包含在响应头的 Location 字段中,接下来,浏览器获取 Location 字段中的地址,并使用该地址重新导航,这就是一个完整重定向的执行流程。这也就解释了为什么输入的是 geekbang.org,最终打开的却是 www.geekbang.org 了。
不过也不要认为这种跳转是必然的。如果你打开 12306.cn,你会发现这个站点是打不开的。这是因为 12306 的服务器并没有处理跳转,所以必须要手动输入完整的 www.12306.cn 才能打开页面。
问题解答
1.为什么很多站点第二次打开速度会很快?
简要来说,很多网站第二次访问能够秒开,是因为这些网站把很多资源都缓存在了本地,浏览器缓存直接使用本地副本来回应请求,而不会产生真实的网络请求,从而节省了时间。同时,DNS 数据也被浏览器缓存了,这又省去了 DNS 查询环节。
2.登录状态是如何保持的?
简单地说,如果服务器端发送的响应头内有 Set-Cookie 的字段,那么浏览器就会将该字段的内容保持到本地。当下次客户端再往该服务器发送请求时,客户端会自动在请求头中加入 Cookie 值后再发送出去。服务器端发现客户端发送过来的 Cookie 后,会去检查究竟是从哪一个客户端发来的连接请求,然后对比服务器上的记录,最后得到该用户的状态信息。