zoukankan      html  css  js  c++  java
  • TCP 长连接保活机制&HTTP长连接设置

    TCP KeepAlive

      Wireshark抓包分析机制

      --------------------------------

    如上图所示,TCP保活报文总是成对出现,包括TCP保活探测报文和TCP保活探测确认报文。
    TCP保活探测报文是将之前TCP报文的确认序列号减1,设置1个字节,内容为“00”的应用层数据,如下图所示:

    TCP保活探测报文

    TCP保活探测确认报文就是对保活探测报文的确认,其报文格式如下:

    因为Websocket通过Tcp Socket方式工作,现在考虑一个问题,在一次长连接中,服务器怎么知道消息的顺序呢?这就涉及到tcp的序列号(Sequence Number)和确认号(Acknowledgment Number)。我的理解是序列号是发送的数据长度;确认号是接收的数据长度。这样讲比较抽象,我们从TCP三次握手开始(结合下图)详细分析一下。

     

    包1:
      TCP会话的每一端的序列号都从0开始,同样的,确认号也从0开始,因为此时通话还未开始,没有通话的另一端需要确认
    包2:
      服务端响应客户端的请求,响应中附带序列号0(由于这是服务端在该次TCP会话中发送的第一个包,所以序列号为0)和相对确认号1(表明服务端收到了客户端发送的包1中的SYN)。需要注意的是,尽管客户端没有发送任何有效数据,确认号还是被加1,这是因为接收的包中包含SYN或FIN标志位。
    包3:
      和包2中一样,客户端使用确认号1响应服务端的序列号0,同时响应中也包含了客户端自己的序列号(由于服务端发送的包中确认收到了客户端发送的SYN,故客户端的序列号由0变为1)此时,通信的两端的序列号都为1。
    包4:客户端——>服务器
      这是流中第一个携带有效数据的包(确切的说,是客户端发送的HTTP请求),序列号依然为1,因为到上个包为止,还没有发送任何数据,确认号也保持1不变,因为客户端没有从服务端接收到任何数据。需要注意的是,包中有效数据的长度为505字节
    包5:客户端<-----服务器
      当上层处理HTTP请求时,服务端发送该包来确认客户端在包4中发来的数据,需要注意的是,确认号的值增加了505(505是包4中有效数据长度),变为506,简单来说,服务端以此来告知客户端端,目前为止,我总共收到了506字节的数据,服务端的序列号保持为1不变。
    包6:客户端<-----服务器
    这个包标志着服务端返回HTTP响应的开始,序列号依然为1,因为服务端在该包之前返回的包中都不带有有效数据,该包带有129字节的有效数据。
    包7:
      由于上个数据包的发送,TCP客户端的确认序列号增长至130,从服务端接收了129字节的数据,客户端的确认号由1增长至130
    理解了序列号和确认序列号是怎么工作的之后,我们也就知道“TCP保活探测报文是将之前TCP报文的确认序列号减1并设置1个字节数据”为什么要这么搞了。

      序列号减一再加一:是为了保证一次连接中keep alive不影响序列号和确认序列号。Keep alive 中的1byte 00的数据并不是真正要传递的数据,而是tcp keep alive约定俗称的规则。

    linux中TCP Keepalive 超时时长的配置

    [root@zmdsdkhost ~]# ls -l /proc/sys/net/ipv4/tcp_keepalive_*
    -rw-r--r-- 1 root root 0 May 18 11:27 /proc/sys/net/ipv4/tcp_keepalive_intvl
    -rw-r--r-- 1 root root 0 May 18 11:27 /proc/sys/net/ipv4/tcp_keepalive_probes
    -rw-r--r-- 1 root root 0 May  6 17:27 /proc/sys/net/ipv4/tcp_keepalive_time

    前两个参数以秒为单位,最后一个是纯数字。这意味着,在发送第一个Keepalive探针之前,Keepalive例程要等待两个小时(1200秒),然后每75秒重新发送一次。如果连续九次未收到ACK响应,则将该连接标记为断开。

    修改此值很简单:您需要将新值写入文件。假设您决定配置主机,以使保持活动状态在十分钟的通道不活动之后开始,然后每隔一分钟发送一次探测。由于网络干线的高度不稳定和间隔值较低,假设您还希望将探测数量增加到20个。

    这是我们更改设置的方法:

      # echo 600 > /proc/sys/net/ipv4/tcp_keepalive_time
    
      # echo 60 > /proc/sys/net/ipv4/tcp_keepalive_intvl
    
      # echo 20 > /proc/sys/net/ipv4/tcp_keepalive_probes
            

    sysctl 工具设置的方式:

    命令行查看:
    #sysctl     
    net.ipv4.tcp_keepalive_time 
    net.ipv4.tcp_keepalive_intvl    
    net.ipv4.tcp_keepalive_probes
    #输出
    net.ipv4.tcp_keepalive_time = 1200
    net.ipv4.tcp_keepalive_intvl = 75
    net.ipv4.tcp_keepalive_probes = 9
    
    #命令行设置
    # sysctl -w 
      net.ipv4.tcp_keepalive_time=600 
      net.ipv4.tcp_keepalive_intvl=60 
      net.ipv4.tcp_keepalive_probes=20
    
      net.ipv4.tcp_keepalive_time = 600
      net.ipv4.tcp_keepalive_intvl = 60
      net.ipv4.tcp_keepalive_probes = 20

    持久化配置方法

     编辑配置文件/etc/sysctl.conf 【vim】

    # vim /etc/sysctl.conf
    net.ipv4.tcp_keepalive_time = 600
    net.ipv4.tcp_keepalive_intvl = 60
    net.ipv4.tcp_keepalive_probes = 20
    
    :wq 保存退出
    
    #sysctl -p  刷新配置生效

    HTTP协议的长连接 Keep-Alive模式:

    我们知道Http协议采用“请求-应答”模式,当使用普通模式,即非Keep-Alive模式时,每个请求/应答,客户端和服务器都要新建一个连接,完成之后立即断开连接;当使用Keep-Alive模式时,Keep-Alive功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive功能避免了建立或者重新建立连接。
    http1.0中默认是关闭的,需要在http头加入”Connection: Keep-Alive”,才能启用Keep-Alive;
    http 1.1中默认启用Keep-Alive,如果加入”Connection: close “才关闭。目前大部分浏览器都是用http1.1协议,也就是说默认都会发起Keep-Alive的连接请求了,所以是否能完成一个完整的Keep- Alive连接就看服务器设置情况。下图是普通模式和长连接模式的请求对比:

    开启Keep-Alive的优缺点:

    优点:Keep-Alive模式更加高效,因为避免了连接建立和释放的开销。
    缺点:长时间的Tcp连接容易导致系统资源无效占用,浪费系统资源。

    Keep-Alive timeout设置: 

    Httpd守护进程,一般都提供了keep-alive timeout时间设置参数。比如nginx的keepalive_timeout,和Apache的KeepAliveTimeout。这个keepalive_timout时间值意味着:一个http产生的tcp连接在传送完最后一个响应后,还需要hold住keepalive_timeout秒后,才开始关闭这个连接。
    当httpd守护进程发送完一个响应后,理应马上主动关闭相应的tcp连接,设置 keepalive_timeout后,httpd守护进程会想说:”再等等吧,看看浏览器还有没有请求过来”,这一等,便是keepalive_timeout时间。如果守护进程在这个等待的时间里,一直没有收到浏览器发过来http请求,则关闭这个http连接【控制服务器,发送TCP协议断开请求:FIN数据包】。

    如下以nginx为例

    vim /etc/nginx/nginx.conf
    
    keepalive_timeout   65;

    抓包观察

    参考文档:

    http://www.tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/#configuringkernel

    https://www.cnblogs.com/zxmbky/p/10281152.html

  • 相关阅读:
    如何在 ASP.NET 中(服务器端)主动清除(HTTP内容响应时)浏览器中的 Cookies 数据
    修复 dji spark 的 micro sd/tf 存储卡里不能正常播放的视频文件
    在 Windows 7 中安装 .NET Framework 时遇到错误:无法建立到信任根颁发机构的证书链
    【转】在 Windows 10 下,配置 Kinect v2 可用于 Windows Hello 验证身份
    安装SQL Server提示“等待数据库引擎恢复句柄失败”
    [转]如何禁止 IIS 在 C:WindowsSystem32LogFilesHTTPERR 中生成日志文件
    Kinect v2 记录
    处理 ASP.NET 中的异常:无法在发送 HTTP 标头之后进行重定向。
    在 Windows Server 2008 中部署带 SignalR 的网站出错
    ( ̄▽ ̄)" 关于河北ETC记账卡的默认密码
  • 原文地址:https://www.cnblogs.com/zhangmingda/p/12680454.html
Copyright © 2011-2022 走看看