theboyaply
theboyaply
发布于 2020-06-06 / 583 阅读
0
0

javaIO与open files

场景

javaWeb 应用放在服务器上的 tomcat 下运行,突然发生宕机,查看日志发现大量的错误信息,大概如下:

java.io.IOException: 打开的文件过多
    ......

上面日志是我从网上copy来的,具体的日志没有了,年代久远。。。大概意思就是程序中打开的句柄数目大于当前系统所允许的最大值,然后就报这个错了。

javaIO

之前在网上看到一篇文章大概意思如下:

public static void main(String[] args) {
        File file = new File("D:/a.txt");
        FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream(file);
            // todo something
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fileInputStream != null) {
                    fileInputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

代码中真正会打开/占用服务器句柄数的地方是 fileInputStream = new FileInputStream(file)

也就是说,不论你 new 了多少个 File,都不会打开/占用服务器句柄数,只有在创建一个 IO 流的时候才会真正的打开/占用一个句柄。

上面的写法可以替换为:

public static void main(String[] args) {
        File file = new File("D:/a.txt");
        try (FileInputStream fileInputStream = new FileInputStream(file);) {
            // todo something
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

这样写的作用是流会在程序结束后自动关闭。

open files

Linux中允许打开的句柄最大数,可使用 ulimit -a 查看,其中的 open files 就是。

[root@CentOS7 ~]# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 7270
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 65535
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 7270
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

下面的信息原文地址为:

https://www.cnblogs.com/conanwang/p/5818441.html

概要

linux系统默认open files数目为1024, 有时应用程序会报Too many open files的错误,是因为open files 数目不够。这就需要修改ulimit和file-max。特别是提供大量静态文件访问的web服务器,缓存服务器(如squid), 更要注意这个问题。
网上的教程,都只是简单说明要如何设置ulimit和file-max, 但这两者之间的关系差别,并没有仔细说明。

说明

  1. file-max

    man proc,可得到file-max的描述。

    /proc/sys/fs/file-max
    This file defines a system-wide limit on the number of open files for all processes. (See
    also setrlimit(2), which can be used by a process to set the per-process limit,
    RLIMIT_NOFILE, on the number of files it may open.) If you get lots of error messages
    about running out of file handles, try increasing this value:
    即file-max是设置 系统所有进程一共可以打开的文件数量 。同时一些程序可以通过setrlimit调用,设置每个进程的限制。如果得到大量使用完文件句柄的错误信息,是应该增加这个值。
    也就是说,这项参数是系统级别的。

  2. ulimit

    Provides control over the resources available to the shell and to processes started by it, on systems that allow such control.
    即设置当前shell以及由它启动的进程的资源限制。
    显然,对服务器来说,file-max, ulimit都需要设置,否则就可能出现文件描述符用尽的问题。

修改

  1. 修改file-max

    # echo  102400 > /proc/sys/fs/file-max 或者 sysctl -w "fs.file-max=102400"
    # 前面2种重启机器后会恢复为默认值
    # vim /etc/sysctl.conf, 加入以下内容,重启生效
    fs.file-max=102400
    
  2. 修改ulimit的open file,系统默认的ulimit对文件打开数量的限制是1024

    # 方法一,临时设置,只在当前终端有效。退出之后,open files又变为默认值。
    ulimit -HSn 102400
    
    # 方法二,将 ulimit -HSn 102400 写入 /etc/profile,因为每次登录终端时,都会自动执行/etc/profile
    vim /etc/profile
    source /etc/profile
    
    # 方法三,vim /etc/security/limits.conf,加入以下配置,重启即可生效
    * hard nofile 102400
    * soft nofile 102400
    
    # PS:个人觉得可以方法二和方法三一起进行,这样就不用重启了。
    

-- end --


评论