Too many file open 问题排查记录

本贴最后更新于 1444 天前,其中的信息可能已经东海扬尘

Too many file open 问题排查记录

环境

  • Tocmat 8.0
  • CentOS6.4
  • JDK 8

问题描述

系统部署到云环境后,当天工作正常,第二天就无法正常工作,看了 Tomcat 日志,日志中频繁出现 Too many file open 的报错,重启项目后,可以恢复正常。

问题排查记录

  1. 问题已产生,且未重启 Tomcat 服务
  2. 查看 Tomcat 进程的 PID
ps -ef | grep tomcat

获取到 TomcatPID 用于查看 Tomcat 进程的连接句柄

  1. 使用 lsof 命令,查看了 Tomcat 进程的连接句柄数
# 按TYPE降序查看连接句柄数量
lsof -n | grep PID | awk '{print $5}' | sort | uniq -c | sort -nr | head -n 10
# 按NAME降序查看连接句柄数量
lsof -n | grep PID | awk '{print $9" "$10}' | sort | uniq -c | sort -nr | head -n 10

查看后发现句柄数量最多的是

  • TYPEsocket
  • NAMEcan't identify protocol

经过度娘之后,得知这种 can't identify protocol 的 socket 句柄,通常是 socket 流使用后,没有关闭 socket 流导致,于是开始着手定位代码问题。

  1. 找到问题接口
    找一个同样的环境且没有干扰情况下,需要准备一个小脚本,时刻监控 NAMEcan't identify protocol 的连接句柄数量
    test.sh

    #!/bin/sh
    while [ true ]; do
    lsof -n | grep $1 | awk '{print $9" "$10}' | sort | uniq -c | sort -nr | head -n 10
    sleep 1
    done
    
    chmod +x test.sh
    ./test.sh tomcat_pid
    

    启动后就可以每秒刷新一次,监控 Tomcat 进程 NAMEcan't identify protocol 的连接句柄数量。

    开始逐一测试线上接口,定位问题,每调用接口前后,观察 NAME can't identify protocol` 的连接句柄数量的增长情况,找到问题接口。

  2. 定位代码问题
    找到问题接口后,开启 Tomcat 远程调试功能
    修改 $TOMCAT_HOME/bin/catalina.sh 中 JPDA_ADDRESS 这一项,将内容改为需要绑定的远程调试端口

     268 if [ "$1" = "jpda" ] ; then
     269   if [ -z "$JPDA_TRANSPORT" ]; then
     270     JPDA_TRANSPORT="dt_socket"
     271   fi
     272   if [ -z "$JPDA_ADDRESS" ]; then
     273     JPDA_ADDRESS="5050"
     274   fi
     275   if [ -z "$JPDA_SUSPEND" ]; then
     276     JPDA_SUSPEND="n"
     277   fi
     278   if [ -z "$JPDA_OPTS" ]; then
     279     JPDA_OPTS="-agentlib:jdwp=transport=$JPDA_TRANSPORT,address=$JPDA_ADDRESS,server=y,suspend=$JPDA_SUSPEND"
     280   fi
     281   CATALINA_OPTS="$CATALINA_OPTS $JPDA_OPTS"
     282   shift
     283 fi
    
    

    修改TOMCAT_HOME/bin/startup.sh中`exec "PRGDIR"/"EXECUTABLE" start "@"改为 exec "PRGDIR"/"EXECUTABLE" jpda start "$@"`

    42 EXECUTABLE=catalina.sh
    43
    44 # Check that target executable exists
    45 if $os400; then
    46   # -x will Only work on the os400 if the files are:
    47   # 1. owned by the user
    48   # 2. owned by the PRIMARY group of the user
    49   # this will not work if the user belongs in secondary groups
    50   eval
    51 else
    52   if [ ! -x "$PRGDIR"/"$EXECUTABLE" ]; then
    53     echo "Cannot find $PRGDIR/$EXECUTABLE"
    54     echo "The file is absent or does not have execute permission"
    55     echo "This file is needed to run this program"
    56     exit 1
    57   fi
    58 fi
    59
    60 exec "$PRGDIR"/"$EXECUTABLE" jpda start "$@"
    
    

    开放防火墙的远程调试端口

    /sbin/iptables -I INPUT -p tcp --dport 5050 -j ACCEPT
    /etc/rc.d/init.d/iptables save
    /etc/rc.d/init.d/iptables restart
    

    重启 Tomcat 服务

    使用 IDEA 远程调试 Tomcat(需要本地代码与线上代码完全一致,否则不会进入断点)

    请求接口,逐行调试,观察 NAME can't identify protocol` 的连接句柄数量的增长情况,找到问题代码,并修改

  • Tomcat

    Tomcat 最早是由 Sun Microsystems 开发的一个 Servlet 容器,在 1999 年被捐献给 ASF(Apache Software Foundation),隶属于 Jakarta 项目,现在已经独立为一个顶级项目。Tomcat 主要实现了 JavaEE 中的 Servlet、JSP 规范,同时也提供 HTTP 服务,是市场上非常流行的 Java Web 容器。

    162 引用 • 529 回帖 • 6 关注
  • CentOS

    CentOS(Community Enterprise Operating System)是 Linux 发行版之一,它是来自于 Red Hat Enterprise Linux 依照开放源代码规定释出的源代码所编译而成。由于出自同样的源代码,因此有些要求高度稳定的服务器以 CentOS 替代商业版的 Red Hat Enterprise Linux 使用。两者的不同在于 CentOS 并不包含封闭源代码软件。

    238 引用 • 224 回帖
  • Q&A

    提问之前请先看《提问的智慧》,好的问题比好的答案更有价值。

    7935 引用 • 36291 回帖 • 168 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...