tcp连接
可以看这篇文章。
运输层
tcp性能考虑
http的事务是存在时延的,主要包括连接、传播、处理时延。
延迟确认,捎带处理。确认算法会在一个特定的窗口时间(通常是100~200ms)内将输出确认存放在缓存中,以寻找能够捎带它的输出数据分组。如果在那个时间端没有输出数据分组,就将确认信息放在单独的分组中传送。
tcp慢启动。其实就是拥塞控制,tcp连接会随着时间进行自我‘调谐’,起初会限制连接的最大速度,如果数据成功传输,会随着时间的推移提高传输的速度。
Nagle算法。试图在发送一个分组之前,将大量小的tcp数据绑定在一起,提高网络效率。不过,由于小的http报文可能填满一个分组,可能会因为等待哪些永远不会到来的额外数据而产生时延。可用设置TCP_NODELAY
来禁用Nagle算法。
TIME_WAIT累积与端口耗尽。当某个tcp端点关闭tcp连接时,会在内存总维护一个小的控制块,用来记录最近所关闭连接的ip地址与端口号。为什么有这个TIME_WAIT,可用参考 运输层
http连接的处理
常被误解的Connection首部。http允许在客户端与最终的源端服务器之间存在一串Http中间实体(代理、高速缓存)。可以从客户端开始,逐跳地将HTTP报文经过这些中间设备,转发到源端服务器上。Connection首部可以承载三种不通类型的标签:
- Http首部字段名,列出了只与此连接有关的首部
- 任意标签值,用于描述此连接的非标准选项。
- 值close,说明操作完成之后需关闭这条持久连接
** 串行事务处理时延**。串行建立连接,那么连接时延与慢启动时延就会叠加起来。
目前有几种方法可以提高http的连接性能。
- 并行连接。通过多条tcp连接发起并发的http请求。
- 持久连接。重用tcp连接,以消除连接及关闭时延。
- 管道化连接。通过共享的tcp连接发起并发的http请求。
- 复用的连接。交替传送请求和响应报文
并行连接
本节将介绍下面几个问题:
- 并行连接可能会提高页面的加载速度
- 并行连接不一定更快
- 并行连接可能让人“感觉”更快一些
并行连接可能会提高页面的加载速度。
并行连接不一定更快。在客户端网络带宽不足的情况下,如果同时加载多个对象,这些对象会竞争有限的带宽。并且打开大量的连接会消耗很多内存。实际上,浏览器确实使用了并行连接,不过并行连接的总数有一个限制(通常为4个)。
并行连接可能会让人"感觉"更快一些。由于页面上同时有多个对象出现,所以用户会感觉快了一些。即使实际上整个网页被下载下来的时间可能更长了。
持久连接
本节将介绍
- keep-alive(http/1.0+)与http/1.1 persistent 两种持久连接的
初始化了对某服务器http请求的应用程序可能会在不久的将来对那台服务器发起更多的http请求。这种性质被称为站点的局限性。
持久连接。在事务处理结束之后仍然保持在打开状态的TCP连接被称为持久连接。
并行连接与持久连接搭配起来使用可能是最高效的方式。
keep-alive选项 | 含义 |
---|---|
timeout | 它估计了服务器希望将连接保持在活跃状态的时间。这并不是一个承诺值 |
max | 它估计了服务器还希望为多少个事务保持此连接的活跃状态。这并不是一个承诺值。 |
keep-alive连接的规则与限制:
- keep-alive首部必须随所有希望保持持久连接的报文一起发送。
- 代理和网关必须执行connection的首部规则。
- 不应该与无法确定是否支持Connection首部的代理服务器建立keep-alive连接
哑代理及解决方案。
在(e)这一步,客户端在keep-alive的连接上发送的第二条请求keep-alive会被挂起,直到客户端或服务器端将连接超时,并将其关闭为止。
netscape的浏览器采用了Proxy-connection
来解决这个问题。如果代理是盲中继,它会将无意义的Proxy-connection首部转发给web服务器,服务器会忽略此首部,不会带来任何问题。但如果代理是个聪明的代理,就用一个Connection首部来取代无意义的Proxy-connection首部,然后将其发送给服务器,以收到预期的效果。
在客户端和服务器之间只有一个代理时可以用这种方案来解决。不过当在哑代理的任意一侧有一个聪明的代理时,这个问题又会出现。
persistent connection,与http/1.0+不同,http/1.1持久连接在默认情况下是激活的,要在事务处理结束之前将连接关闭,http/1.1应用程序必须向报文中显示地添加一个Connection:close
首部
管道化连接
当第一条请求通过网络流向地球另一端的服务器时,第二条第三条请求也可以开始发送。
关闭连接的奥秘
任意解除链接。所有的http客户端\服务器端或代理都可以在任意时刻关闭一条tcp传输链接。不过,服务器永远都无法确定在它关闭连接的那一刻,在线路那一头的客户端有没有数据要发送。如果出现这种情况,客户端就会在写入半截请求报文时发现出现了连接错误。
Content-Length及截尾操作。每条http响应都应该有精确的Content-length首部,用以描述响应主体的尺寸。
事务的幂等性。如果一个事务,不管执行一次还是多次,得到的结果都相同,这个事务就是幂等的。如get,head,put,delete,trace,options。而post就是非幂等性的。
完全关闭与半关闭。应用程序可以关闭tcp输入和信道中的任意一个,或者两者都关闭。套接字调用close()
会将tcp连接的输入和输出信道都关闭了,这被称为完全关闭。也可以用套接字shutdown()
单独关闭输入或输出信道。这被称为半关闭。
关闭输入信道是比较危险的,如果另一端向你已经关闭的输入信道发送数据,操作系统将想另一端会送一条tcp 连接被对端重置的报文。
正常关闭。想要正常关闭连接的应用程序应该先关闭其输出信道,然后周期性地检查其输入信道的状态。如果一定时间区间内对端没有关闭输入信道,应用程序可以强制关闭连接,以节省资源。
总结
- tcp的连接要考虑性能问题。tcp的慢启动,拥塞控制,捎带处理,TIME_WAIT累积与端口耗尽
- tcp并行连接
- keeep-alive持久连接
- 管道化连接允许第一条请求发送给服务器时,后面的请求也可以开始发送
- 任意解除连接,可能会造成连接被对端重置