前言
上一篇 HTTP 讲到了第3章。这次我们讲第4章。有太多要学,不是科班出生的表示压力有点大,需要赶紧学,幸运的是我现在这家公司每个人我都能在他们身上学到东西。
TCP 是啥
HTTP的上一层,传输层用的是TCP ,书中简单的说了下TCP,建议大家还是去看看 《TCP/IP 详解一卷》。那个说的详细。
HTTP 事务的时延
我们发送一个请求,其实在服务器处理的时间一般都不长,时间上的花费是在传输数据的路上。见下图:
TCP连接的握手时延
握手需要发送三个TCP数据,这些是发送HTTP数据的准备工作花费了很多时间,原本在发送3个TCP包前是不会发送HTTP请求的,但是后来发现在TCP握手的最后一个数据包可以利用发送数据,这种技术叫做捎带。请求就变成这个样子:
延迟确认
书中表面:TCP传输的时候都要接收方回发一个已收到的确认信息(确认报文),来告诉发送方,信息已经收到,不需要再发送。
一个确认报文是很小的,如果单独作为一个TCP包发送显得太浪费,所以操作系统会使用延时确认技术,简单的说就是在确认收到信息的时候,不立马发送确认报文,而是等待一小段时间,等待有同地址的报文,并将其合并一起发送。类比现实生活很是形象。
TCP慢启动
简单的说就是: 开始发送TCP请求时不会立马发送多个TCP报文,而是慢慢的并行的发送数量。比如成功发送一个之后,一次发送两个,两个成功之后。。。这样是有好处的,比如可以避免多个TCP报文因为同一个原因发送失败的而引发的性能浪费。
Connection
- 以上简单的说了下TCP,我想看HTTP权威指南也不知道他想表达啥。建议看 TCP/IP详解来了解TCP 这块吧,后期我会边玩我的MAC ,边看书边学这本书。
Connection 是HTTP的一个首部字段。
特点一:在Connection中包含的字段,不能被转出到下一个地址。比如 Connection: name .那么name 这个首部就只能到下一个地址,活不到被下一个转出。
请求方式
下面我们来聊聊web怎么玩HTTP
串行
这是最原始的时代,估计比我还老。这种方式就是发送一个HTTP请求等其全部完成之后再发送下一个请求。(stupid)
直接上图吧,不哔哔:
并行
谁动能行到能并行,计算机本来就用的特性。
上例🌰的情况,我们分析,可以发现,1. 一次只发一个请求,浪费带宽。2. 事务之间的联系不一定要有先后关系,可以同时请求相互不影响。
模型图:( 书中给的例子是一个HTML 和 3个图片)
并行的问题:
- 带宽可能有限,带宽让我们不可能高效的并行多个请求。
- 性能,切换进程是需要花费性能的。
- 服务器拒绝,你的机子牛逼了,服务器不干了。大家都一次发这么多请求,服务器撑不住的。你慢点。😈
持久连接
并行连接其实并没有本质的提高连接的速度。它只是利用了计算机的进程功能,并没有利用网络知识。
非持续连接的问题:每次完成HTTP请求之后都要关闭TCP连接,但是我们的网站可能对同一个服务器发送多个请求,所以花费了很多时间在开启关闭TCP连接的过程中。
HTTP1.1 就通过网络知识本质的提升了性能。
持续连接:在一个HTTP请求完成之后一段时间内不关闭TCP的连接。
HTTP持久连接解决的问题:
- 减少建立TCP连接的时延
- 减少慢启动的时延
上图:
http1.0 持久连接 - Keep-alive
http1.0 如果想使用持久连接,会在请求报文中加入 Connection:keep-Alive ,如果服务器同意就会回发Connection:keep-alive .
一般 Connection:keep-alive 会和 keep-alive 首部一起使用 。如
Connection: Keep-Alive
Keep-Alive: max=5, timeout=120 ### 服务器还能支持保留多少个连接, 希望保持120秒的连接
keep-alive 的规则与限制
- 持久连接建立起来之后,如果在这条连接上没有在继续发 Connection:Keep-Alive 那么持久连接就会断开。
- 实体的主题部分必须代用正确的Content-Length,这样就能让另一端知道是报文的结束还是新报文的开始。
占坑不是太懂
- 哑代理问题
哑代理
哑代理的问题会出现在我们的网络路线中出现一个不懂Keep-Alive机制又盲目转发的代理
的情况。
首先我们主机发送一份Keep-Alive的报文,代理接受到这样一份报文,它不懂客户端要保持连接,然后又转发请求给服务器,服务器懂啊,就回了一份Connection:Keep-Alive的报文表示同意保持连接,中间代理又接受到了这样的报文,还是不懂啊,再转发给客户端。这是客户端和服务端都懂对方😝。那么客户端下一次就不会再发TCP握手数据啦,直接发请求。但是这时代理就不干了,你不发建立连接的请求,不符合规矩,直接无视。尴尬的哑代理情况就出现了。
这种尴尬的情况书中没有给出完备的解决方案。
HTTP1.1 默认持续连接
HTTP1.1 持久连接的规章制度
- HTTP1.1 不用发送Connection:keep-Alive 也是持久连接的
- 只有在发送Connection: close 时才能断开持久连接
- 实体主体部分的长度与相应的Content-Length一致,或者使用分块出函数编码方式。连接才能持久保持。
占坑
- HTTP1.1 代理必须能够分别管理客户端和服务器的持久连接
- 一个客户端最多只能与服务器或代理保持最多两个持久连接
管道化连接
管道化在我的理解就是并行版的持久化连接请求。
就是在建立持久化连接后,在不等待上一条请求成功返回前就发送下一条请求。就是这么简单。
上图:
书中说了4点管道化的注意事项,但我感觉太过啰嗦,都是些开发者自己应该注意的问题,不在我们的知识学习范围内不说了。
关于关闭连接
书中建议我们不适用管道化来发一些非幂等的请求,因为如果中间断开了很难判断是否服务端处理了请求,还是还没收到就已经断开了连接。
记录生活
我又恋爱了,又是那个女孩。异地恋。反而让我觉得我应该更快的成熟。原本想着毕业第一年好好的善待自己,看来还是要规划下那少的可怜的薪水。