为什么 sshfs 和 fuse 会为 Java 进程创建数千个文件描述符(无限增长)?

为什么 sshfs 和 fuse 会为 Java 进程创建数千个文件描述符(无限增长)?

/proc/PID/fd我试图理解为什么我会在进程的目录中看到成千上万个如下所示的新文件描述符java

$ sudo ls -lt /proc/585/fd | head
total 0
lr-x------ 1 crate crate 64 Jan 14 09:45 3036 -> /sys/fs/cgroup
lr-x------ 1 crate crate 64 Jan 14 09:45 3037 -> /sys/fs/cgroup/sys-fs-fuse-connections.mount
lr-x------ 1 crate crate 64 Jan 14 09:45 3038 -> /sys/fs/cgroup/sys-fs-fuse-connections.mount
lr-x------ 1 crate crate 64 Jan 14 09:45 3035 -> /sys/fs/cgroup
lr-x------ 1 crate crate 64 Jan 14 09:45 3032 -> /sys/fs/cgroup
lr-x------ 1 crate crate 64 Jan 14 09:45 3033 -> /sys/fs/cgroup/sys-fs-fuse-connections.mount
lr-x------ 1 crate crate 64 Jan 14 09:45 3034 -> /sys/fs/cgroup/sys-fs-fuse-connections.mount
lr-x------ 1 crate crate 64 Jan 14 09:45 3028 -> /sys/fs/cgroup
lr-x------ 1 crate crate 64 Jan 14 09:45 3029 -> /sys/fs/cgroup/sys-fs-fuse-connections.mount

这是来自 Debian GNU/Linux 服务器(版本 11.1)。此机器用作分布式数据库的节点之一(板条箱数据库, 版本4.6.6,用 Java 编程)。

sshfs最近,我在该机器上安装了:

$ dpkg -l | egrep "(fuse)|(sshf)"
ii  fuse3                      3.10.3-2                       amd64        Filesystem in Userspace (3.x version)
ii  libfuse2:amd64             2.9.9-5                        amd64        Filesystem in Userspace (library)
ii  libfuse3-3:amd64           3.10.3-2                       amd64        Filesystem in Userspace (library) (3.x version)
ii  sshfs                      3.7.1+repack-2                 amd64        filesystem client based on SSH File Transfer Protocol

但我sshfs安装该软件包后从未使用或配置过。换句话说,我没有通过sshfs另一台服务器创建挂载等。

目前/etc/mtab该服务器上有:

$ cat /etc/mtab | column -t
sysfs       /sys                      sysfs       rw,nosuid,nodev,noexec,relatime                                                      0  0
proc        /proc                     proc        rw,nosuid,nodev,noexec,relatime                                                      0  0
udev        /dev                      devtmpfs    rw,nosuid,relatime,size=32885744k,nr_inodes=8221436,mode=755                         0  0
devpts      /dev/pts                  devpts      rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000                                0  0
tmpfs       /run                      tmpfs       rw,nosuid,nodev,noexec,relatime,size=6580424k,mode=755                               0  0
/dev/sda1   /                         ext4        rw,relatime,errors=remount-ro,stripe=256                                             0  0
securityfs  /sys/kernel/security      securityfs  rw,nosuid,nodev,noexec,relatime                                                      0  0
tmpfs       /dev/shm                  tmpfs       rw,nosuid,nodev                                                                      0  0
tmpfs       /run/lock                 tmpfs       rw,nosuid,nodev,noexec,relatime,size=5120k                                           0  0
cgroup2     /sys/fs/cgroup            cgroup2     rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot                      0  0
pstore      /sys/fs/pstore            pstore      rw,nosuid,nodev,noexec,relatime                                                      0  0
none        /sys/fs/bpf               bpf         rw,nosuid,nodev,noexec,relatime,mode=700                                             0  0
systemd-1   /proc/sys/fs/binfmt_misc  autofs      rw,relatime,fd=30,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=30739       0  0
mqueue      /dev/mqueue               mqueue      rw,nosuid,nodev,noexec,relatime                                                      0  0
tracefs     /sys/kernel/tracing       tracefs     rw,nosuid,nodev,noexec,relatime                                                      0  0
debugfs     /sys/kernel/debug         debugfs     rw,nosuid,nodev,noexec,relatime                                                      0  0
fusectl     /sys/fs/fuse/connections  fusectl     rw,nosuid,nodev,noexec,relatime                                                      0  0
hugetlbfs   /dev/hugepages            hugetlbfs   rw,relatime,pagesize=2M                                                              0  0
configfs    /sys/kernel/config        configfs    rw,nosuid,nodev,noexec,relatime                                                      0  0
/dev/sdb1   /data                     ext4        rw,relatime,stripe=256                                                               0  0
tmpfs       /run/user/1000            tmpfs       rw,nosuid,nodev,relatime,size=6580420k,nr_inodes=1645105,mode=700,uid=1000,gid=1000  0  0

几天后,我在 CrateDB 系统的 Web UI 上遇到了“打开的文件太多”的情况。

最终,我重新启动该服务器,然后开始仔细监视它。

现在,当我检查具有最多文件描述符的进程时,我发现它是该java进程:

$ sudo lsof +c 0 | awk '{ print $2 " " $1; }' | sort -rn | uniq -c | sort -rn | head -n5 | column -t
360126  585   java
136     558   rsyslogd
96      472   systemd-timesyn
87      1     systemd
61      3106  sshd

当我访问( )fd的 PID 目录时,我看到最近创建的文件描述符如下:585java

lr-x------ 1 crate crate 64 Jan 14 09:45 3036 -> /sys/fs/cgroup
lr-x------ 1 crate crate 64 Jan 14 09:45 3037 -> /sys/fs/cgroup/sys-fs-fuse-connections.mount
lr-x------ 1 crate crate 64 Jan 14 09:45 3038 -> /sys/fs/cgroup/sys-fs-fuse-connections.mount
lr-x------ 1 crate crate 64 Jan 14 09:45 3035 -> /sys/fs/cgroup
lr-x------ 1 crate crate 64 Jan 14 09:45 3032 -> /sys/fs/cgroup

cgroup当我计算与或相关的文件描述符的数量时fuse,我看到了数千个:

$ sudo ls -l /proc/585/fd | egrep "(cgroup)|(fuse)" | wc -l
2752

我还观察到文件描述符的数量因为java(CrateDB) 进程开始增加当我与 CrateDB 的基于 Web 的管理 UI 交互时。

文件描述符的数量相关cgroupsys-fs-fuse-connections.mount持续增加。

我正在尝试理解这一点无限增长在数量上文件描述符与Java 进程相关cgroup且针对 Java 进程。sys-fs-fuse-connections.mount

额外信息:我有另一组服务器在 Debian GNU/Linux(版本 10.x)上运行完全相同的 Java 应用程序 (CrateDB),它们没有sshfs安装,这是主要区别。当我监视fdJava 进程目录中的文件描述符时,我没有看到任何cgroup相关sys-fs-fuse-connections.mount的文件描述符,而且我从未遇到过“打开太多文件”的问题。

我不知何故怀疑这个问题不是由 CrateDB 直接引起的,而是由sshfs和(可能是间接的?)fuse引起的,因此我的问题是:我该如何测试这个问题?

更新(2022-02-17):我在新的 Debian GNU/Linux 11.2 虚拟机上测试了以下内容:

步骤1:通过 安装 CrateDB 的最新稳定版本 (4.7.0) apt。CrateDB 使用的 Java 虚拟机报告如下:

$ /usr/share/crate/jdk/bin/java --version
openjdk 17.0.1 2021-10-19
OpenJDK Runtime Environment Temurin-17.0.1+12 (build 17.0.1+12)
OpenJDK 64-Bit Server VM Temurin-17.0.1+12 (build 17.0.1+12, mixed mode, sharing)

第2步:列出打开文件数最多的进程:

echo -e "cntFiles PID Process Name" && echo "========================" && sudo lsof -e /run/user/1000/gvfs +c 0 | awk '{ print $2 " " $1; }' | sort -rn | uniq -c | sort -rn | head -n5

cntFiles PID Process Name    
========================
   7439 484 java
   6876 1493 gnome-shell
   1776 1799 gsd-xsettings
   1566 1620 evolution-alarm
   1463 1817 ibus-x11

然后启动straceforjava进程并关注该java进程及其所有线程的相关内容/sys/fs/cgroup

 $ sudo strace --decode-fds=all --trace-path=/sys/fs/cgroup --follow-forks --attach 484
strace: Process 484 attached with 37 threads

在此阶段,strace不打印任何内容。

步骤3:运行 Firefox 并查看 CrateDB 管理 Web UI网址:http://localhost:4200/#!/

当我访问 CrateDB 的 Web 管理 UI 时,strace开始报告很多

$ sudo strace --decode-fds=all --trace-path=/sys/fs/cgroup --follow-forks --attach 484
strace: Process 484 attached with 37 threads
strace: Process 2697 attached
strace: Process 2698 attached
strace: Process 2699 attached
strace: Process 2700 attached
[pid  2698] --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0xc} ---
strace: Process 2701 attached
[pid  1325] lstat("/sys/fs/cgroup", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid  1325] openat(AT_FDCWD, "/sys/fs/cgroup", O_RDONLY) = 151</sys/fs/cgroup>
[pid  1325] dup(151</sys/fs/cgroup>)    = 152</sys/fs/cgroup>
[pid  1325] fstat(151</sys/fs/cgroup>, {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid  1325] fcntl(151</sys/fs/cgroup>, F_GETFL) = 0x8000 (flags O_RDONLY|O_LARGEFILE)
[pid  1325] fcntl(151</sys/fs/cgroup>, F_SETFD, FD_CLOEXEC) = 0
[pid  1325] getdents64(151</sys/fs/cgroup>, 0x7f6e9c01bc90 /* 29 entries */, 32768) = 1112
[pid  2400] lstat("/sys/fs/cgroup", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid  2400] openat(AT_FDCWD, "/sys/fs/cgroup", O_RDONLY) = 155</sys/fs/cgroup>
[pid  2400] dup(155</sys/fs/cgroup>)    = 156</sys/fs/cgroup>
[pid  2400] fstat(155</sys/fs/cgroup>, {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid  2400] fcntl(155</sys/fs/cgroup>, F_GETFL) = 0x8000 (flags O_RDONLY|O_LARGEFILE)
[pid  2400] fcntl(155</sys/fs/cgroup>, F_SETFD, FD_CLOEXEC) = 0
[pid  2400] getdents64(155</sys/fs/cgroup>, 0x7f6ec09507d0 /* 29 entries */, 32768) = 1112
[pid  1325] lstat("/sys/fs/cgroup", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid  1325] openat(AT_FDCWD, "/sys/fs/cgroup", O_RDONLY) = 159</sys/fs/cgroup>
[pid  1325] dup(159</sys/fs/cgroup>)    = 162</sys/fs/cgroup>
[pid  1325] fstat(159</sys/fs/cgroup>, {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid  1325] fcntl(159</sys/fs/cgroup>, F_GETFL) = 0x8000 (flags O_RDONLY|O_LARGEFILE)
[pid  1325] fcntl(159</sys/fs/cgroup>, F_SETFD, FD_CLOEXEC) = 0
[pid  1325] getdents64(159</sys/fs/cgroup>, 0x7f6e9c02bd10 /* 29 entries */, 32768) = 1112
[pid  2400] lstat("/sys/fs/cgroup", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid  2400] openat(AT_FDCWD, "/sys/fs/cgroup", O_RDONLY) = 163</sys/fs/cgroup>
[pid  2400] dup(163</sys/fs/cgroup>)    = 164</sys/fs/cgroup>
[pid  2400] fstat(163</sys/fs/cgroup>, {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid  2400] fcntl(163</sys/fs/cgroup>, F_GETFL) = 0x8000 (flags O_RDONLY|O_LARGEFILE)
[pid  2400] fcntl(163</sys/fs/cgroup>, F_SETFD, FD_CLOEXEC) = 0
[pid  2400] getdents64(163</sys/fs/cgroup>, 0x7f6ec0dd90e0 /* 29 entries */, 32768) = 1112
[pid  1325] lstat("/sys/fs/cgroup", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid  1325] openat(AT_FDCWD, "/sys/fs/cgroup", O_RDONLY) = 167</sys/fs/cgroup>
[pid  1325] dup(167</sys/fs/cgroup>)    = 168</sys/fs/cgroup>
[pid  1325] fstat(167</sys/fs/cgroup>, {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid  1325] fcntl(167</sys/fs/cgroup>, F_GETFL) = 0x8000 (flags O_RDONLY|O_LARGEFILE)
[pid  1325] fcntl(167</sys/fs/cgroup>, F_SETFD, FD_CLOEXEC) = 0
[pid  1325] getdents64(167</sys/fs/cgroup>, 0x7f6e9c03bd90 /* 29 entries */, 32768) = 1112
[pid  2400] lstat("/sys/fs/cgroup", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid  2400] openat(AT_FDCWD, "/sys/fs/cgroup", O_RDONLY) = 171</sys/fs/cgroup>
[pid  2400] dup(171</sys/fs/cgroup>)    = 172</sys/fs/cgroup>
[pid  2400] fstat(171</sys/fs/cgroup>, {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid  2400] fcntl(171</sys/fs/cgroup>, F_GETFL) = 0x8000 (flags O_RDONLY|O_LARGEFILE)
[pid  2400] fcntl(171</sys/fs/cgroup>, F_SETFD, FD_CLOEXEC) = 0
[pid  2400] getdents64(171</sys/fs/cgroup>, 0x7f6ec06baa20 /* 29 entries */, 32768) = 1112
[pid  1325] lstat("/sys/fs/cgroup", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid  1325] openat(AT_FDCWD, "/sys/fs/cgroup", O_RDONLY) = 175</sys/fs/cgroup>
[pid  1325] dup(175</sys/fs/cgroup>)    = 176</sys/fs/cgroup>
[pid  1325] fstat(175</sys/fs/cgroup>, {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid  1325] fcntl(175</sys/fs/cgroup>, F_GETFL) = 0x8000 (flags O_RDONLY|O_LARGEFILE)
[pid  1325] fcntl(175</sys/fs/cgroup>, F_SETFD, FD_CLOEXEC) = 0
[pid  1325] getdents64(175</sys/fs/cgroup>, 0x7f6e9c04be10 /* 29 entries */, 32768) = 1112
[pid  2400] lstat("/sys/fs/cgroup", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid  2400] openat(AT_FDCWD, "/sys/fs/cgroup", O_RDONLY) = 179</sys/fs/cgroup>
[pid  2400] dup(179</sys/fs/cgroup>)    = 180</sys/fs/cgroup>
[pid  2400] fstat(179</sys/fs/cgroup>, {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid  2400] fcntl(179</sys/fs/cgroup>, F_GETFL) = 0x8000 (flags O_RDONLY|O_LARGEFILE)
[pid  2400] fcntl(179</sys/fs/cgroup>, F_SETFD, FD_CLOEXEC) = 0
[pid  2400] getdents64(179</sys/fs/cgroup>, 0x7f6ec15347f0 /* 29 entries */, 32768) = 1112
strace: Process 2738 attached
[pid  2738] +++ exited with 0 +++
strace: Process 2739 attached
[pid  2739] +++ exited with 0 +++

步骤4:我退出 Firefox,不再与 CrateDB 的 Web 管理 UI 进行交互,并立即strace停止报告与 相关的任何内容/sys/fs/cgroup

步骤5:我检查了进程的打开文件数java,现在这个数字是 8778。如果我继续使用 Web 管理 UI,这个数字就会无限增长。

答案1

显然,问题是不相关的sshfsfuse而是关于使用 CrateDB (用 Java 编写) 和 GNU/Linux 发行版的交互cgroup v2, 作为由 CrateDB 团队确定

我们再次遇到了这个问题,最终可以将其归结为 CrateDB 与使用 cgroup v2 的发行版结合使用时的一个错误。修复程序已合并并已发布到版本 4.8.4 的测试渠道。我预计 5.0.2 很快就会发布。

更多详情请参阅:

相关内容