zoukankan      html  css  js  c++  java
  • HTTP权威指南----连接管理

    一、TCP过程:

    1、浏览器解析出主机名
    2、浏览器查询主机名的IP地址
    3、浏览器获得端口号(80)
    4、浏览器发起到相应主机的端口的连接
    5、发送HTTP GET请求
    6、读取HTTP响应
    7、浏览器关闭TCP连接

    通过以上描述,浏览器的一次TCP的生命周期仅有GET和接收响应的这么一个过程,TCP连接不会一直建立。而且,TCP会按序、无差错的承载HTTP数据。

    TCP流是分段的、由IP分组传送。协议栈为:HTTP over TCP over IP

    而HTTPS(443)的协议栈为:HTTP ---> TLS or SSL(密码加密层) ----> TCP ----->IP ----> 网络接口

    二、HTTP延迟的产生原因

    1、DNS的解析过程。     ------如果没有缓存,最多可能达到数十秒
    2、TCP建立连接的时延    -----一条TCP连接本身不会造成过多的麻烦,但是在高并发面前,这是最严峻的问题
    3、传输产生的时延
    4、服务器处理报文产生的时延

    三、对TCP性能的考虑

    1、TCP慢启动拥塞控制
    2、Nagle算法
    3、用于捎带确认的TCP延迟确认算法
    4、TIME_WAIT时延和端口耗尽
    5、TCP连接的握手时延

    用wireshark可以非常方便的分析HTTP在TCP层面的网络通信过程,下面是访问百度过程的抓包:

    首先用ip.src==192.168.0.104&&http ------>过滤出百度的IP地址,然后用

    ip.addr==104.75.250.62&&tcp -------> 查询TCP的建立过程

    对于TCP的慢启动拥塞控制:发送方打开拥塞窗口,接收方打开通告窗口,只有分组被确认后,拥塞窗口才会扩 大一倍,因此分组的发送是以2的N次方的形式增长的。具体可以回忆TCP/IP详解内容。

          ----->好处:这是TCP的机制,可以防止网络的突然过载与拥塞。

      ----->带来的问题:新建立的连接的传输速度会比较慢。因此需要在HTTP层面建立持久连接。

    对于Nagle算法:Nagle算法希望客户端发送全尺寸的IP分组(1500字节),否则,会把那些微小分组缓存起来,等把所有的全尺寸的IP分组发送完毕,再把绑定的多个微小IP分组一起发送。实际上,在HTTP应用程序中,大多数还是把Nagle算法关闭掉的,尤其在现有的网络中,原因:可能一直无法填满这个IP分组,而产生了很严重的延时,让用户无法容忍。通常设置参数TCP_NODELAY禁用Nagle算法。

    对于延迟确认算法:ACK消息一般会延迟发送(100~200毫秒),等待其他分组,也同样可能会引发严重的延迟。因此系统一般可能会关闭或者进行调整,不过要保障应用程序不会对网络造成破坏。

    对于TIME_WAIT积累与端口耗尽:这个问题主要出现在TCP连接结束之后,系统中,在TCP连接结束之后,会有一个2MSL的时间(通常为2分钟),这段时间内,之前的这个TCP连接占用的端口号不会分配给新的TCP连接,而系统中一共就有60000多个端口,假如同时有那么多个应用程序在2MSL时间内发送请求,那么会把系统的端口拖垮耗尽。这里可以大概算一下:假设端口数60000,2MSL时间为120秒,那么连接率为60000/120=500秒/次,我们无法保证客户端一定会在这个范围之内。所以我们可以调大客户端的负载生成机器的数量,或者调小2MSL的数值,以增加连接率。

    四、HTTP连接处理

    HTTP对于连接的处理主要表现在首部的connection字段,我们在Firefox或者Google浏览器中抓包可以看到,请求头和大部分的响应头中的connection字段基本都是 "keep-alive" ,这里对HTTP的连接方式进行说明:

    1、串行连接处理事务:这肯定是最慢的一种连接方式,我们以请求一个包含3个图片的网页为例,每一步请求独立开来,先要请求页面,再依次请求三张图片资源,而且每一次请求的TCP都要重新建立连接与断开,不科学不合理,pass掉。

    2、并行连接:还以上面的例子说明,这种方式还是先建立TCP连接请求html页面,断开连接,然后同时建立三个TCP连接请求三张图片资源,在现在我们的带宽来看,应该是没什么问题,不过这有可能会把客户端系统的内存资源带来很大的压力,假如要请求的资源非常多的话。同时,服务器也要同时处理更多的连接请求,对于服务器处理高并发的压力也是指数型的增长。因此,在客户端上做出了相应的限制,把并行连接数限制为4个,而且服务端可以任意关闭承受不了的过量的连接。但是,这种方法依然不好。

    3、持久连接:这也就是我们现在看到的keep-alive的字段,但是它在HTTP/1.0中广泛使用,它的好处在于:a、它只建立一次连接,减少了这部分的连接和时延。b、由于慢启动的存在,可以让连接建立之后传输的后面的IP分组更快的传输到客户端。c、这也减少了打开过多TCP连接的潜在威胁,对于客户端和服务器都是有好处的。

    在持久连接中,web服务器有权利随时关闭TCP的连接,然后客户端发现连接断了,除非是非幂等的请求(如以POST的方式向服务器提交购物的订单),它都应该主动重新向服务器发起请求。

    缺点:客户端和服务器之间可能出现大量的空闲连接,这需要服务器监测,把不必要的空闲连接FIN掉

    在HTTP/1.1中,默认所有的连接都是持久的,如果想要结束连接,需要在首部加上connection:close字段。注意:这里不发送该字段并不意味着永远不断开,两端都是可以随时关闭连接的。虽然http/1.1中默认的连接都是持久的,但是在实际的服务端和客户端的设计中,还是会加上connection:keep-alive字段的,为了防止某一段只支持http/1.0 。

    限制:a、每个持久连接都只适用于一跳传输,即http的代理需要能分别管理客户端和服务器的持久连接。

            b、一个客户端对任何服务器或代理最多只能维护两条持久连接,以防服务器过载。

            c、服务器不应该在试图传输报文的过程中关闭连接,而且在关闭之前至少应该响应一条请求。但是很有可能客户端就在服务器认为空闲连接可以终止的一瞬间发了连接,这种情况不能避免,这就要求客户端能够对于幂等的方法(GET、PUT、HEAD、OPTIONS、DELETE等)请求发送RET,重新建立连接发送请求。

    (如果一个事务,不管是执行一次还是很多次,得到的结果都相同(未必),准确的说,一次和N次具有相同的副作用,这个事务就是幂等的,如get、put等,而POST就是非幂等的。要发送一条非幂等的请求,就需要等待来自前一条请求的响应状态)幂等性详述:http://www.cnblogs.com/weidagang2046/archive/2011/06/04/2063696.html
    2017/1/3添加:
    目前,使用的是持久连接和并行连接相互配合的方法,web浏览器可以打开少量的并行连接,并且每一个都是持久连接。作为web浏览器,他并不知道哪个连接应该设为持久的连接,所以通过抓新浪的http包我们发现:web浏览器会在每个发送的http请求头上加入connection:keep-alive字段,把问题抛给服务器,服务器会在多数的响应头中加入字段connection:close,以此来拒绝掉客户端的长连接请求,或者有的响应头没加这个字段也表示拒绝,但是在有的响应头中加入了connection:keep-alive字段,这说明这条tcp连接被服务器端允许了进行保持持久连接。


    4、管道化连接:就个人理解,这个相当于上面所提到的并行连接和持久连接的组合,属于对keep-alive的一次优化。差异在于:当客户端的第一条请求到达服务器时,第二条第三条的请求也通过这个管道开始发送了,这也是并行的特点。这里要注意,http报文是没有序列号标签的,所以如果响应失序了,会产生很大的影响,所以服务端必须按照接收报文的顺序发送响应报文。

    五、关闭连接

    1、非正常关闭:在任何情况下,客户端和服务器都有随时关闭连接的可能。因此,上面已经提到过,客户端要能够有针对幂等的请求重新发送机制。

    2、正常关闭:这里我觉得类似于系统进程中管道的概念,这里相当于一个协同进程产生的双向管道。客户端和服务器分别有一个输入一个输出,用于接收和发送http报文。与IPC中一样,首先关闭连接的输出信道总是安全的,因为连接的另一端可以从管道的缓冲区中读取数据,这里面会包含一个FIN包,结束这个TCP流;那如果服务端先关闭了输入信道的话,客户端发现对端的输入信道被关闭,它就要先发送RST的TCP重置报文,重新建立连接。

    这里还有一个完全关闭和半关闭的概念,和TCP结束连接的四次握手机制很像。

    完全关闭 就是同时关闭一端的输入和输出,这要调用close()方法;

    半关闭 就是单独先关闭输入或者输出,这要调用shutdown()方法。

  • 相关阅读:
    数据结构(四十)平衡二叉树(AVL树)
    数据结构(三十九)二叉排序树
    数据结构(三十八)静态查找表(顺序查找、二分查找、插值查找、斐波那契查找、线性索引查找)
    数据结构(三十七)查找的基本概念
    数据结构(三十六)关键路径
    数据结构(三十五)拓扑排序
    数据结构(三十四)最短路径(Dijkstra、Floyd)
    数据结构(三十三)最小生成树(Prim、Kruskal)
    字符串匹配算法之KMP
    最长公共子序列(Longest common subsequence)
  • 原文地址:https://www.cnblogs.com/webber1992/p/5912652.html
Copyright © 2011-2022 走看看