Monitorando o número de Open FDs por processo de forma eficiente?

2

Eu quero poder monitorar o número de arquivos abertos no Linux. Atualmente, estou contando o número de arquivos em /proc/<pid>/fd e fdinfo .

Meu balanceador de carga tem cerca de um milhão de FDs. Então, isso acaba levando cerca de 20 segundos para ser executado.

No entanto, isso resulta em alto uso da CPU: 47.18% [kernel] [k] __d_lookup

Existe uma maneira mais eficiente de obter esse número?

    
por Kyle Brandt 18.05.2017 / 19:56

3 respostas

0

O simples:

lsof | wc -l

informará o número de arquivos abertos no sistema.

    
por 18.05.2017 / 20:21
0

Qual é a eficiência desse código do SystemTap para seu caso de uso? Não é uma visão perfeita, uma vez que só rastreia as alterações de quando começa (então qualquer coisa aberta antes do início seria perdida) e precisará de trabalho adicional para tornar a saída mais legível ou adequada.

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")
}

Execute via algo como:

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

A desvantagem deste método é a necessidade de identificar todos os "arquivos abertos" (soquetes, etc) e, em seguida, ajustar a contagem através de ganchos de chamada de sistema apropriados (se disponíveis); o acima apenas rastreia arquivos de arquivos. Outra opção seria chamar task_open_file_handles para tarefas que chegam à CPU e exibir as mais recentes dessas contagens periodicamente.

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");
}

Isso, no entanto, seria perder qualquer coisa que não estivesse na CPU; uma caminhada completa dos processos e, em seguida, tarefas seriam necessárias para uma lista completa, embora isso possa ser muito lento ou muito caro se você tiver milhões de FDs.

Além disso, esses probes não parecem ser estáveis, então talvez o eBPF ou algo no futuro? Por exemplo. o segundo no Centos 7 explodiu depois de algum tempo em

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
    
por 18.05.2017 / 23:47
0

Para um balanceador de carga dedicado, eu controlaria o total de arquivos abertos no sistema, em vez de gastar os recursos de E / S e CPU contando-os por processo. Os arquivos abertos restantes por processos não desejados devem ser um valor sem sentido para o resultado pretendido.

Para conhecer os arquivos abertos globais pelo sistema Linux, não há necessidade de contá-los; o kernel do Linux registra quantos arquivos ele abriu.

Para saber isso, execute:

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

ou

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

Isso é muito mais eficiente do que contar todos os arquivos abertos com a saída de lsof , que percorrerá todos os diretórios /proc/$PID/fd e afetará negativamente os recursos de I / O / CPU do sistema.

    
por 20.05.2017 / 05:47

Tags