プロセスごとのオープンFDの数を効率的に監視しますか?

プロセスごとのオープンFDの数を効率的に監視しますか?

Linux で開いているファイルの数を監視できるようにしたいと考えています。現在、およびのファイル数をカウントしてい/proc/<pid>/fdますfdinfo

私のロード バランサーには約 100 万個の 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_handlesCPU に渡されるタスクを呼び出し、それらのカウントの最新のものを定期的に表示することが考えられます。

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の2番目のプローブは、しばらくすると爆発します。

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

関連情報