有效监控每个进程的 Open FD 数量?

有效监控每个进程的 Open FD 数量?

我希望能够监控Linux中打开文件的数量。目前我正在计算/proc/<pid>/fd和中的文件数量fdinfo

我的负载均衡器有大约一百万个 FD。所以这最终需要大约 20 秒来执行。

然而,这会导致 CPU 使用率高:47.18% [kernel] [k] __d_lookup

有没有更有效的方法来获取这个数字?

答案1

对于专用的负载均衡器,我会跟踪系统中打开的文件总数,而不是浪费 I/O 和 CPU 资源按进程对它们进行计数。不需要的进程剩余的打开文件对于预期结果来说应该是无意义的值。

要了解Linux系统全局打开的文件数,无需统计; Linux 内核会跟踪它打开的文件数量。

要知道这一点,请运行:

cat /proc/sys/fs/file-nr | awk ' { print $1 } '

或者

sysctl fs.file-nr | awk ' { print $1 } '

这比计算使用 的输出打开的所有文件要高效得多lsof,后者会遍历所有/proc/$PID/fd目录,并对系统 I/O / CPU 资源产生负面影响。

答案2

简单的:

lsof | wc -l

将告诉您系统中打开的文件数量。

答案3

此 SystemTap 代码对于您的用例来说效率如何?这不是一个完美的视图,因为它只跟踪从开始时开始的变化(因此在开始之前打开的任何内容都会被错过),并且需要额外的工作以使输出更清晰或更合适。

global procfdcount

probe begin {
    printf("begin trace...\n\n")
}

probe syscall.open {
    procfdcount[pid()]++
}

probe syscall.close {
    p = pid()
    procfdcount[p]--
    if (procfdcount[p] < 0) {
        procfdcount[p] = 0
    }
}

probe kprocess.exit {
    p = pid()
    if (p in procfdcount) {
        delete procfdcount[p]
    }
}

probe timer.s(60) {
    foreach (p in procfdcount- limit 20) {
        printf("%d %lu\n", p, procfdcount[p])
    }
    printf("\n")
}

通过类似的方式运行:

... (install systemtap here) ...
# stap-prep
... (fix any reported systemtap issues here) ...
# stap procfdcount.stp

这种方法的缺点是需要识别所有“打开的文件”(套接字等),然后通过适当的系统调用挂钩(如果可用)调整计数;以上仅跟踪文件文件。另一种选择是调用task_open_file_handles进入 CPU 的任务,并定期显示最新的计数。

global taskopenfh

probe begin {
    printf("begin trace...\n\n");
}

probe scheduler.cpu_on {
    p = pid();
    if (p == 0) next;
    taskopenfh[p] = task_open_file_handles(pid2task(p));
}

probe timer.s(60) {
    foreach (p in taskopenfh-) {
        printf("%d %lu\n", p, taskopenfh[p]);
    }
    delete taskopenfh;
    printf("\n");
}

但这会错过任何不在 CPU 上的东西;完整的列表需要完整的流程和任务,尽管如果您有数百万个 FD,这可能会太慢或太昂贵。

而且这些探针似乎不稳定,所以也许将来会使用 eBPF 或其他东西?例如 Centos 7 上的第二个在一段时间后爆炸了

ERROR: read fault [man error::fault] at 0x0000000000000008 (((&(fs->fdt))))
near identifier 'task_open_file_handles' at
/usr/share/systemtap/tapset/linux/task.stp:602:10

相关内容