• 本网豪情赞助商

  • 微信小程序开发:各种页面特效集合
  • 小程序直播组件协议
  • 微信小程序之特殊效果及功能
  • MySql数据库备份与恢复——使用mysqldump 导
  • 宝塔面板mysql恢复
  • Python3+Selenium 配置Chrome选项
  • MySQL执行外部sql脚本文件命令报错:unknown
  • Win10系统左键点击开始菜单左键没反应,点右
  • Linux下安装Oracle出现的一些错误,以及解决
  • mysql-bin请出log
  • h3>

    time_wait太多导致[error] (99)Cannot assign requested address


    文章摘要: time_wait太多导致[error] (99)Cannot assign requested address: proxy 2012-10-15 17:05:35 |分类: rhel_apache | 字号 订阅 问题是80的apache转发到8080的apache时失败: [error] (99)Cannot assign requested address: proxy: HTTP: attempt to connect


    文章TAG: linux time_wait

    time_wait太多导致[error] (99)Cannot assign requested address: proxy  

    2012-10-15 17:05:35|  分类: rhel_apache |字号 订阅

     

    问题是80的apache转发到8080的apache时失败:
    [error] (99)Cannot assign requested address: proxy: HTTP: attempt to connect to 127.0.0.1:8080 (*) failed


    netstat里time wait太多导致了[error] (99)Cannot assign requested address


    sysctl -w net.ipv4.tcp_tw_recycle=1 表示开启TCP连接中TIME-WAIT sockets的快速回收

    改了这个参数在观察:apache不报错了,time wait数也降了


    net.ipv4.tcp_syncookies = 1
    表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
      net.ipv4.tcp_tw_reuse = 1
    表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
      net.ipv4.tcp_tw_recycle = 1
    表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
      net.ipv4.tcp_fin_timeout = 30
    表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。
      net.ipv4.tcp_keepalive_time = 1200
    表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。
      net.ipv4.ip_local_port_range = 1024 ? ?65000
    表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为1024到65000。
      net.ipv4.tcp_max_syn_backlog = 8192
    表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
      net.ipv4.tcp_max_tw_buckets = 5000
    表 示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。默认为180000,改为 5000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,但是对于Squid,效果却不大。此项参数 可以控制TIME_WAIT套接字的最大数量,避免Squid服务器被大量的TIME_WAIT套接字拖死。..


    对于处理并发量较高的Server,统计会发现本机tcp的time_wait状态的连接非常多

    netstat -nat | awk '{++S[$NF]} END {for(a in S) print a, S[a]}'

    TIME_WAIT 24413

    established) 1

    SYN_SENT 1

    FIN_WAIT1 1

    State 1

    ESTABLISHED 15

    LAST_ACK 1

    LISTEN 7

    该time_wait的默认值为2*MSL,MSL即max segment lifetime,是一个tcp包的最大生存时间

    MSL值在Linux上好像默认是30秒,所以从time_wait状态变化到CLOSED大约需要60s时间

    另外一方面,本机可用的发起连接的socket端口是有限的,可通过以下命令查看

    cat /proc/sys/net/ipv4/ip_local_port_range

    32768 61000

    也即大约只有2万多个端口可用,如果处于 time_wait状态的连接很多

    很有可能会影响本机向外发起的连接(比如说nginx的proxy服务器),出现端口不够用的情况

    可以通过以下参数去减少time_wait的连接

    vi /etc/sysctl.conf

    #开启time_wait状态的socket重用

    net.ipv4.tcp_tw_reuse = 1

    #开启time_wait状态的socket快速回收

    net.ipv4.tcp_tw_recycle = 1

    /sbin/sysctl -p

    或者直接修改time_wait的等待时间

    echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout

    更多的Linux内核优化可参见

    http://performancewiki.com/linux-tuning.html


    今天检查了一下基本一台服务器,发现TIME_WAIT高到3k多.TIME_WAIT本身并不会占用很大资源的,除非受到攻击.但太多服务器还是有可能挂掉.
    TIME_WAIT 3699
    CLOSE_WAIT 52
    FIN_WAIT1 32
    SYN_SENT 1
    FIN_WAIT2 2
    ESTABLISHED 17
    SYN_RECV 45
    CLOSING 6

    根据《TCP/IP详解》中的TCP的建立和终止中有关"TCP的终止"的讲解

    TCP的终止通过双方的四次握手实现.发起终止的一方执行主动关闭,响应的另一方执行被动关闭.

    1. 发起方更改状态为FIN_WAIT_1,关闭应用程序进程,发出一个TCP的FIN段;
    2. 接收方收到FIN段,返回一个带确认序号的ACK,同时向自己对应的进程发送一个文件结束符EOF,同时更改状态为CLOSE_WAIT,发起方接到ACK后状态更改为FIN_WAIT_2;
    3. 接收方关闭应用程序进程,更改状态为LAST_ACK,并向对方发出一个TCP的FIN段;
    4. 发起方接到FIN后状态更改为TIME_WAIT,并发出这个FIN的ACK确认.ACK发送成功后(2MSL内)双方TCP状态变为CLOSED.

    我们不难看出上面的显示的结果的意思.根据TCP协议,主动发起关闭的一方,会进入TIME_WAIT状态(TCP实现必须可靠地终止连接的两个方向(全双工关闭)),持续2*MSL(Max Segment Lifetime),缺省为240秒.

    为什么 TIME_WAIT 状态需要保持 2MSL 这么长的时间?

    TIME_WAIT 的等待时间为2MSL,即最大段生存时间.如果 TIME_WAIT 状态保持时间不足够长(比如小于2MSL),第一个连接就正常终止了.第二个拥有相同相关五元组的连接出现(因为连接终止前发起的一方可能需要重发 ACK,所以停留在该状态的时间必须为MSL的2倍.),而第一个连接的重复报文到达,干扰了第二个连接.TCP实现必须防止某个连接的重复报文在连接终 止后出现,所以让TIME_WAIT态保持时间足够长(2MSL),连接相应方向上的TCP报文要么完全响应完毕,要么被丢弃.建立第二个连接的时候,不 会混淆.

    注:MSL(最 大分段生存期)指明TCP报文在Internet上最长生存时间,每个具体的TCP实现都必须选择一个确定的MSL值.RFC 1122建议是2分钟,但BSD传统实现采用了30秒.TIME_WAIT 状态最大保持时间是2 * MSL,也就是1-4分钟.

    对apache的操作
    HTTP 协议1.1版规定default行为是Keep-Alive,也就是会重用TCP连接传输多个request/response.所以我打开 http中的keepalive On,发现TIME_WAIT就立刻少了下来.只有300的样子.总结一下.我认为有二个原因.

    1.keepalive 没有开,导致每次请求都要建立新的tcp连接,请求完成以后关闭,增加了很多time_wait的状态,没有重 用,KeepAlive我认为它指的是保持连接活跃,类似于Mysql的永久连接.如果将KeepAlive设置为On,那么来自同一客户端的请求就不需 要再一次连接,避免每次请求都要新建一个连接而加重服务器的负担.
    2.然后keepalive在系统中本身的值很高.默认空闲连接 7200 秒(2 小时)内没有活动.才会断开.

    我们开启KeepAlive

    KeepAlive On
    MaxKeepAliveRequests 120
    KeepAliveTimeout 15

    这样每个连接可以发送100次请求,超时时间为15秒(如果第二次请求和第一次请求之间超过KeepAliveTimeOut的时间的话,第一次连接就会中断,再新建第二个连接).

    有关内核级别的keepalive和time_wait的优化调整

    vi /etc/sysctl

    net.ipv4.tcp_tw_reuse = 1
    net.ipv4.tcp_tw_recycle = 1
    net.ipv4.tcp_keepalive_time = 1800
    net.ipv4.tcp_fin_timeout = 30
    net.core.netdev_max_backlog =8096

    修改完记的使用sysctl -p 让它生效

    以上参数的注解
    /proc/sys/net/ipv4/tcp_tw_reuse
    该文件表示是否允许重新应用处于TIME-WAIT状态的socket用于新的TCP连接.

    /proc/sys/net/ipv4/tcp_tw_recycle
    recyse是加速TIME-WAIT sockets回收

    对 tcp_tw_reuse和tcp_tw_recycle的修改,可能会出现.warning, got duplicate tcp line warning, got BOGUS tcp line.上面这二个参数指的是存在这两个完全一样的TCP连接,这会发生在一个连接被迅速的断开并且重新连接的情况,而且使用的端口和地址相同.但基本 上这样的事情不会发生,无论如何,使能上述设置会增加重现机会.这个提示不会有人和危害,而且也不会降低系统性能,目前正在进行工作

    /proc/sys/net/ipv4/tcp_keepalive_time
    表示当keepalive起用的时候,TCP发送keepalive消息的频度.缺省是2小时

    /proc/sys/net/ipv4/tcp_fin_timeout   最佳值和BSD一样为30
    fin_wait1状态是在发起端主动要求关闭tcp连接,并且主动发送fin以后,等待接收端回复ack时候的状态.对于本端断开的socket连接,TCP保持在FIN-WAIT-2状态的时间.对方可能会断开连接或一直不结束连接或不可预料的进程死亡.

    /proc/sys/net/core/netdev_max_backlog
    该文件指定了,在接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目.

    tcp状态

    LISTEN:侦听来自远方的TCP端口 的连接请求
    SYN-SENT:再发送连接请求后等待匹配的连接请求
    SYN-RECEIVED:再收到和发送一个连接请求后等待对方对连接 请求的确认
    ESTABLISHED:代表一个打开的连接
    FIN-WAIT-1:等待远程TCP连接中断请求,或先前的连接中断请求的确认
    FIN- WAIT-2:从远程TCP等待连接中断请求
    CLOSE-WAIT:等待从本地用户发来的连接中断请求
    CLOSING:等待远程TCP对 连接中断的确认
    LAST-ACK:等待原来的发向远程TCP的连接中断请求的确认
    TIME-WAIT:等待足够的时间以确保远程TCP接 收到连接中断请求的确认
    CLOSED:没有任何连接状态


     

    对tcp_fin_timeout的错误理解

    来源: 张家军的日志

    查询秀岭邮件提到的tcp_retrans_collapse时,意外发现了一段文档
    按照文档的说法,貌似长久以来我对于tcp_fin_timeout的理解都是错误的

    先备份在这里,再验证

    文档来源:
    http://www.pgsqldb.org/mwiki/index.php/Linux%E5%86%85%E6%A0%B8%E5%8F%82%E6%95%B0

    文档内容:

    提高Linux应对短连接的负载能力

    在存在大量短连接的情况下,Linux的TCP栈一般都会生成大量的 TIME_WAIT 状态的socket。你可以用下面的命令看到:

    netstat -ant| grep -i time_wait 

    有时候,这个数目是惊人的:

    netstat -ant|grep -i time_wait |wc -l

    可 能会超过三四万。这个时候,我们需要修改 linux kernel 的 tcp time wait的时间,缩短之,有个 sysctl 参数貌似可以使用,它是 /proc/sys/net/ipv4/tcp_fin_timeout,缺省值是 60,也就是60秒,很多网上的资料都说将这个数值设置低一些就可以减少netstat 里面的TIME_WAIT状态,但是这个说法是错误的。经过认真阅读Linux的内核源代码,我们发现这个数值其实是输出用的,修改之后并没有真正的读回 内核中进行使用,而内核中真正管用的是一个宏定义,在 $KERNEL/include/net/tcp.h里面,有下面的行:

    #define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to destroy TIME-WAIT
    * state, about 60 seconds */

    而这个宏是真正控制 TCP TIME_WAIT 状态的超时时间的。如果我们希望减少 TIME_WAIT 状态的数目(从而节省一点点内核操作时间),那么可以把这个数值设置低一些,根据我们的测试,设置为 10 秒比较合适,也就是把上面的修改为:

    #define TCP_TIMEWAIT_LEN (10*HZ) /* how long to wait to destroy TIME-WAIT
    * state, about 60 seconds */

    然后重新编译内核,重启系统即可发现短连接造成的TIME_WAIT状态大大减少:

    netstat -ant | grep -i time_wait |wc -l

    一般情况都可以至少减少2/3。也能相应提高系统应对短连接的速度。 

    然后重新编译内核,重启系统即可发现短连接造成的TIME_WAIT状态大大减少:

    netstat -ant | grep -i time_wait |wc -l

    一般情况都可以至少减少2/3。也能相应提高系统应对短连接的速度。


     
      net.ipv4.tcp_fin_timeout = 30 
      # Decrease the time default value for tcp_keepalive_time connection 
      net.ipv4.tcp_keepalive_time = 1800 
      # Turn off tcp_window_scaling 
      net.ipv4.tcp_window_scaling = 0 
      # Turn off the tcp_sack 
      net.ipv4.tcp_sack = 0 
      #Turn off tcp_timestamps 
      net.ipv4.tcp_timestamps = 0
      加到/etc/rc.local
      代码:
      echo "30">/proc/sys/net/ipv4/tcp_fin_timeout
      echo "1800">/proc/sys/net/ipv4/tcp_keepalive_time 
      echo "0">/proc/sys/net/ipv4/tcp_window_scaling
      echo "0">/proc/sys/net/ipv4/tcp_sack 
      echo "0">/proc/sys/net/ipv4/tcp_timestamps
      通过以上修改,TIME_WAIT明显减少!