【网络通信 -- 直播】IM 学习系列 -- 网络通信协议简介(HTTP 协议 四)

【网络通信 -- 直播】IM 学习系列 -- 网络通信协议简介(HTTP 协议 四)

【1】HTTP 的连接管理

【1.1】短连接与长连接

短连接 HTTP 协议最初(0.9/1.0)是个非常简单的协议,通信过程也采用了简单的“请求 - 应答”方式;
短连接底层的数据传输基于 TCP/IP,每次发送请求前需要先与服务器建立连接,收到响应报文后会立即关闭连接,早期的 HTTP 协议也被称为是“无连接”的协议;

短连接的缺点相当严重,因为在 TCP 协议里,建立连接和关闭连接都是非常“昂贵”的操作,TCP 建立连接要有“三次握手”,发送 3 个数据包,需要 1 个 RTT;关闭连接是“四次挥手”,4 个数据包需要 2 个 RTT,而 HTTP 的一次简单“请求 - 响应”通常只需要 4 个包,如果不算服务器内部的处理时间,最多是 2 个 RTT,这么算下来,浪费的时间就是“3÷5=60%”,有三分之二的时间被浪费掉了,传输效率低得惊人;

长连接也叫“持久连接”(persistent connections)、“连接保活”(keep alive)、“连接复用”(connection reuse),采用的就是“成本均摊”的思路,既然 TCP 的连接和关闭非常耗时间,那么就把这个时间成本由原来的一个“请求 - 应答”均摊到多个“请求 - 应答”上,这样虽然不能改善 TCP 的连接效率,但基于“分母效应”,每个“请求 - 应答”的无效时间就会降低不少,整体传输效率也就提高了;

【1.2】连接相关的头字段

长连接对性能的改善效果非常显著,在 HTTP/1.1 中的连接都会默认启用长连接,不需要用什么特殊的头字段指定,只要向服务器发送了第一次请求,后续的请求都会重复利用第一次打开的 TCP 连接,在这个连接上收发数据;同时可以在请求头里明确地要求使用长连接机制,使用的字段是 Connection,值是“keep-alive”,无论客户端是否显式要求长连接,如果服务器支持长连接,总会在响应报文里放一个“Connection: keep-alive”字段,告诉客户端“服务器支持长连接,此后便使用该 TCP 一直收发数据”;

服务器端通常不会主动关闭连接,可以使用一些策略;
拿 Nginx 来举例,它有两种方式:
1. 使用“keepalive_timeout”指令,设置长连接的超时时间,如果在一段时间内连接上没有任何数据收发就主动断开连接,避免空闲连接占用系统资源;
2. 使用“keepalive_requests”指令,设置长连接上可发送的最大请求次数,比如设置成 1000,那么当 Nginx 在这个连接上处理了 1000 个请求后,也会主动断开连接;

【1.3】队头阻塞

“队头阻塞”与短连接和长连接无关,而是由 HTTP 基本的“请求 - 应答”模型所导致的,因为 HTTP 规定报文必须是“一发一收”,这就形成了一个先进先出的“串行”队列,队列里的请求没有轻重缓急的优先级,只有入队的先后顺序,排在最前面的请求被最优先处理,如果队首的请求因为处理的太慢耽误了时间,那么队列里后面的所有请求也不得不跟着一起等待,结果就是其他的请求承担了不应有的时间成本;

队头阻塞性能优化
“并发连接”(concurrent connections)即同时对一个域名发起多个长连接,用数量来解决质量的问题;
“域名分片”(domain sharding)技术,多开几个域名,这些域名都指向同一台服务器,这样实际长连接的数量便增加了;

【2】HTTP 重定向

【2.1】重定向的过程

响应报文中具有“Location”字段,该字段配合 301/302 状态码才有意义,该字段标记了服务器要求重定向的 URI;浏览器收到 301/302 报文,会检查响应头里有没有“Location”字段,如果有,就从字段值里提取出 URI,发出新的 HTTP 请求,在“Location”里的 URI 既可以使用绝对 URI,也可以使用相对 URI;所谓“绝对 URI”,就是完整形式的 URI,包括 scheme、host:port、path 等,所谓“相对 URI”,就是省略了 scheme 和 host:port,只有 path 和 query 部分,是不完整的,但可以从请求上下文里计算得到;注意,在重定向时如果只是在站内跳转,可以放心地使用相对 URI,但如果要跳转到站外,就必须用绝对 URI;

【2.2】重定向状态码

301 即“永久重定向”(Moved Permanently),即原 URI 已经“永久”性地不存在了,今后的所有请求都必须改用新的 URI;浏览器看到 301,就知道原来的 URI“过时”了,就会做适当的优化;
302 即“临时重定向”(“Moved Temporarily”),即原 URI 处于“临时维护”状态,新的 URI 是起“顶包”作用的“临时工”,浏览器或者爬虫看到 302,会认为原来的 URI 仍然有效,但暂时不可用,所以只会执行简单的跳转页面,不记录新的 URI,也不会有其他的多余动作,下次访问还是用原 URI;
303 See Other,类似 302,但要求重定向后的请求改为 GET 方法,访问一个结果页面,避免 POST/PUT 重复操作;
307 Temporary Redirect,类似 302,但重定向后请求里的方法和实体不允许变动,含义比 302 更明确;
308 Permanent Redirect,类似 307,不允许重定向后的请求变动,但具有 301“永久重定向”的含义;

【2.3】重定向的应用场景

1. “资源不可用”需要用另一个新的 URI 来代替;
2. “避免重复”让多个网址都跳转到一个 URI,增加访问入口的同时还不会增加额外的工作量;

【2.4】重定向的相关问题

1. “性能损耗”,重定向的机制决定了一个跳转会有两次请求 - 应答,比正常的访问多了一次;
2. “循环跳转”,若重定向的策略设置欠考虑,可能会出现“A=>B=>C=>A”的无限循环,不停地在这个链路里循环;

参考致谢
本博客为博主的学习实践总结,并参考了众多博主的博文,在此表示感谢,博主若有不足之处,请批评指正。

【1】透视HTTP协议

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章