Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Aplica-se a: .NET Core 2.1, .NET Core 3.1, .NET 5
Este artigo apresenta depuradores e despejos de memória e as ferramentas para capturar e analisar arquivos de despejo de memória no Linux.
Pré-requisitos
Como nas partes anteriores, esta parte está estruturada para colocar mais ênfase na teoria e nos princípios a serem seguidos quando você começar a solucionar problemas. Não tem nenhum pré-requisito. No entanto, você deve ter os seguintes itens já configurados se tiver seguido todas as etapas deste treinamento até agora:
- O Nginx tem dois sites:
- O primeiro site escuta solicitações usando o cabeçalho de host myfirstwebsite (
http://myfirstwebsite
) e roteia as solicitações para o aplicativo ASP.NET Core de demonstração que está escutando na porta 5000. - O segundo site escuta solicitações usando o cabeçalho de host buggyamb (
http://buggyamb
) e roteia as solicitações para o segundo aplicativo com bugs de amostra do ASP.NET Core que está escutando na porta 5001.
- O primeiro site escuta solicitações usando o cabeçalho de host myfirstwebsite (
- Ambos os aplicativos ASP.NET Core estão sendo executados como serviços que reiniciam automaticamente quando o servidor é reinicializado ou os aplicativos param de responder ou falham.
- Um firewall local do Linux é habilitado e configurado para permitir tráfego SSH e HTTP.
Objetivo desta parte
Esta parte apresenta o conceito de despejos de memória e depuradores de memória e as ferramentas que você pode usar para capturar e analisar arquivos de despejo de memória. A maioria das técnicas e ferramentas descritas nesta parte será usada nos próximos laboratórios de solução de problemas.
Despejo de memória
Assim como um despejo de memória no modo de usuário no Windows, um despejo de memória é um instantâneo da memória de um processo. Os despejos de memória são frequentemente necessários para solucionar problemas de desempenho no Linux.
Um despejo de memória pode ser gerado sob demanda por um depurador (coleta manual de despejo) ou pode ser configurado para ser coletado automaticamente após uma falha de processo.
O que acontece quando um processo falha no Linux?
A maioria dos sistemas Linux tem despejos de memória habilitados por padrão. O sistema gera um despejo de memória para qualquer processo que seja encerrado inesperadamente. Isso é semelhante à maneira pela qual o WER (Relatório de Erros do Windows) gera despejos para processos que terminam de forma anormal.
Aqui estão alguns aspectos-chave de como um sistema Linux se comporta em relação à geração de arquivos de dump principal:
- Por padrão, um arquivo de despejo principal é gerado quando um processo é encerrado inesperadamente.
- O arquivo de despejo principal é denominado "core" e é criado no diretório de trabalho atual ou no /var/lib/systemd/coredump diretório.
- Embora o comportamento padrão seja que o sistema operacional gere um arquivo de despejo principal, essa configuração pode ser substituída para /proc/sys/kernel/core_pattern canalizar diretamente a saída do arquivo de despejo principal para outro aplicativo.
Essas configurações padrão e algumas outras, como os limites de tamanho, podem ser definidas em arquivos de configuração. Os seguintes recursos se aprofundam sobre este assunto:
Apport: a maneira do Ubuntu de gerenciar despejos de memória
No Ubuntu, o serviço apport system gerencia a geração de dump principal. Mesmo que a geração de dump principal do sistema operacional esteja desabilitada, o apport ainda criará arquivos de dump principal.
O Apport usa /proc/sys/kernel/core_pattern para canalizar diretamente o arquivo de dump principal para o apport. Se você executar o comando enquanto o cat /proc/sys/kernel/core_pattern
apport estiver em execução, deverá ver o seguinte resultado.
Se você desabilitar o apport, isso não impedirá a geração de despejo de memória após o encerramento do processo. Em vez disso, ele simplesmente interrompe o aporte. Em seguida, o sistema reverterá para seu comportamento padrão gerando despejos de memória. Se você executar o mesmo cat /proc/sys/kernel/core_pattern
depois que o apport for interrompido, verá o seguinte comportamento padrão do sistema.
Desativar a geração automática de despejo de memória
Para desabilitar a geração automática de arquivos de dump principal, execute as seguintes etapas:
- Pare e desative o apport.
- Desative a ação padrão do sistema.
O Apport pode ser interrompido e desativado da mesma forma que qualquer outro serviço. Use o sudo systemctl stop apport
comando e o sudo systemctl disable apport
comando para interromper o serviço e, em seguida, desative-o para impedir que ele seja reiniciado.
Para desabilitar a geração automática de arquivos de despejo do sistema operacional para todos os processos que estão sendo executados em todas as contas de usuário no computador, você deve executar as etapas fornecidas em artigos como este.
Capturar despejo de memória e depuradores
Várias ferramentas estão disponíveis para capturar um arquivo de despejo principal, como gcore, gdb, e várias ferramentas para analisar um arquivo de despejo principal, como objdump, kdump, gdb e lldb.
No entanto, você encontrará algumas dificuldades significativas ao trabalhar com essas ferramentas para tentar fazer a depuração do .NET:
- A configuração pode ser difícil em comparação com o processo de configuração de símbolos para o depurador WinDbg no Windows.
- Os arquivos de despejo de memória são grandes porque essas ferramentas não sabem qual região de memória é usada em um processo do .NET Core e não podem cortar as informações de memória apenas para o que é necessário.
- Os arquivos de despejo não são portáteis. Você terá que analisar os arquivos de despejo no computador Linux no qual eles foram gerados. Se você quiser analisar os arquivos de despejo em um computador Linux diferente, etapas extras serão necessárias para configurar o computador host para a sessão de depuração.
lldb
Lldb é a ferramenta recomendada para analisar o despejo do .NET Core. O SDK do .NET inclui ferramentas úteis para configurar o lldb corretamente. No entanto, você precisa instalar pelo menos a versão 3.9 para poder fazer essa análise de depuração para o .NET Core.
Para instalar o lldb 3.9 ou uma versão posterior, use o Gerenciador de Pacotes (por exemplo: sudo apt install lldb
).
Ferramentas e comandos disponíveis no runtime e no SDK do .NET Core
Várias ferramentas úteis estão incluídas junto com o runtime do .NET Core. Por exemplo, createdump
é instalado como parte de cada instalação de runtime do .NET Core.
Você também pode desenvolver suas próprias ferramentas ou optar por usar várias ferramentas de terceiros. A plataforma Microsoft .NET Core também inclui algumas ferramentas do .NET Core que são úteis para depurar problemas do .NET Core. Elas incluem o seguinte:
- dotnet-dump
- dotnet-gcdump
- dotnet-symbol
Para instalar essas ferramentas junto com as outras, você precisa ter o SDK do .NET Core instalado. Para obter mais informações sobre o SDK do .NET Core, consulte: Visão geral do SDK do .NET.
Observação
O Procdump também é digno de menção, embora não faça parte do SDK. Uma discussão aprofundada sobre as opções de ProcDump pode ser encontrada no final desta parte.
Despejo de criação
O Createdump é instalado em todas as versões do .NET Core. Para obter mais informações, consulte os detalhes da implementação.
Createdump é a melhor maneira de gerar um arquivo de dump principal no Linux. Isso ocorre porque os arquivos de despejo gerados automaticamente pelo sistema podem não incluir todos os estados gerenciados. Além disso, alguns comandos SOS ou dotnet-dump podem exibir "UNKNOWN" para nomes de tipo e função.
Da mesma forma, os arquivos de despejo manual criados usando gdb ou gcore não incluirão todas as informações de estado gerenciado e alguns comandos SOS ou dotnet-dump também podem exibir "UNKNOWN" para nomes de tipo e função. A maneira recomendada de capturar arquivos de despejo manual é usando createdump ou alguma outra ferramenta do .NET Core, como procdump.
Aqui estão alguns recursos importantes do createdump:
- Minidespejos de tamanho mínimo são gerados automaticamente.
- É fácil de configurar com um usuário não root.
- Você pode usá-lo para capturar arquivos de despejo principal sob demanda (manual) ou de falha do sistema.
- A maioria das falhas de estouro de pilha é detectada.
Você precisa usar lldb 3.9 ou uma versão posterior para analisar os arquivos de despejo principais capturados usando createdump.
Você pode encontrar createdump no diretório de instalação do .NET Core. Para localizar esse diretório, execute o dotnet --list-runtimes
comando. Conforme mostrado na captura de tela a seguir, um arquivo createdump separado foi criado para as duas versões de runtimes ativos.
dotnet-dump
Você precisa ter o SDK do .NET Core instalado para poder instalar essa ferramenta. O dotnet-dump foi introduzido no SDK do .NET Core 3.0. Ele ajuda a coletar e analisar arquivos de despejo de memória sem a necessidade de nenhum depurador nativo. Ele permite que você execute comandos SOS para analisar falhas e saída do coletor de lixo (GC).
Observação
Dotnet-dump não é um depurador nativo. Portanto, alguns recursos, como exibir os quadros de pilha nativos, não estão disponíveis. O arquivo de despejo gerado não é portátil e você não pode abri-lo no Windows.
Para instalar esta ferramenta, execute o seguinte comando:
dotnet tool install -g dotnet-dump
Você usará essa ferramenta para capturar e analisar arquivos de despejo de memória nas próximas seções do laboratório.
dotnet-gcdump
Essa é outra ferramenta que requer o SDK do .NET Core. Dotnet-gcdump está disponível no .NET Core 3.1 ou versões posteriores.
Essa é uma abordagem interessante para analisar heaps de GC. A ideia por trás dessa ferramenta é que um arquivo de despejo de processo completo não é necessário para investigações em muitos cenários. Portanto, a ferramenta captura apenas as informações de heap gerenciadas e gera um relatório com base nelas.
Mais importante ainda, os arquivos de despejo gerados por essa ferramenta são portáteis e podem ser analisados no PerfView ou no Visual Studio no Windows.
Conforme explicado brevemente aqui, uma coleta de lixo completa é disparada por essa ferramenta para transmitir as informações para um "pipe de evento" para gerar o arquivo de despejo.
Observação
Como uma coleta de lixo completa da Geração 2 é disparada no processo de destino, as características de desempenho do aplicativo podem ser alteradas. Como você pode esperar, enquanto as informações são gravadas no arquivo de despejo principal, os threads serão suspensos. Quanto maior o tamanho do heap, mais longas são as pausas para gravar as informações no arquivo e mais tempo os threads permanecerão pausados.
As informações contidas nesses arquivos de despejo principal serão úteis nas seguintes circunstâncias:
- Comparando o número de objetos por tipo no heap gerenciado
- Analisando raízes de objetos
- Determinando quais objetos têm uma referência a qual tipo
- Outras análises estatísticas sobre objetos no heap
Depois que os dados são gerados, o arquivo pode ser exportado para fora do computador no qual foi criado e pode ser analisado no PerfView ou no Visual Studio.
Para instalar esta ferramenta, execute o seguinte comando:
dotnet tool install -g dotnet-gcdump
Você usará esse comando para gerar alguns relatórios para heaps do .NET Core nas próximas seções do laboratório.
dotnet-symbol
Dotnet-symbol é uma ferramenta útil para obter símbolos para depuração gerenciada. Ele foi introduzido no .NET Core 2.1. Quanto às duas outras ferramentas mencionadas anteriormente, essas ferramentas também exigem que o SDK do .NET Core seja instalado.
Dotnet-symbol
baixa todos os arquivos necessários para depuração (símbolos, módulos, SOS e DAC para o módulo coreclr) para qualquer arquivo de despejo de memória fornecido.
Para instalar esta ferramenta, execute o seguinte comando:
dotnet tool install -g dotnet-symbol
Você usará essa ferramenta para configurar o depurador nas próximas seções de laboratório.
despejo de vídeo
Uma versão linux do ProcDump também está disponível. Ele tem alguns conjuntos de recursos limitados em comparação com sua contraparte do Windows. Ele não suporta todos os recursos que a versão do Windows oferece. Por exemplo, ele não pode ser configurado para coletar arquivos de despejo principal quando o processo falha ou lança uma exceção de primeira chance. No entanto, ainda é uma ferramenta poderosa.
As opções de linha de comando a seguir para ProcDump disparam a geração de arquivos de despejo principal nas condições especificadas.
-C: CPU exceeds or equals a specified value (0 to 100 * nCPU)
-c: CPU is less than a specified value (0 to 100 * nCPU)
-M: The memory commit exceeds or equals a specified value (MB)
-m: The memory commit is less than a specified value (MB)
-T: The thread count exceeds or equals a specified value
-F: The filedescriptor count exceeds or equals a specified value
Siga as instruções de instalação para instalar o ProcDump em seu ambiente.
Você usará essa ferramenta para capturar um arquivo de despejo principal baseado no uso da CPU nas próximas seções de laboratório.
Uma observação sobre como selecionar a versão do SDK
Por padrão, o SDK é instalado em uma configuração "lado a lado". Isso significa que várias versões podem ser executadas juntas em um único computador. A maneira como a versão é escolhida quando você está executando comandos da CLI é explicada mais detalhadamente no artigo Selecionar a versão do .NET Core a usar. No entanto, o processo para selecionar uma versão do SDK pode ser resumido da seguinte maneira:
- O .NET Core procura um arquivo global.json iterativamente navegando inversamente no caminho para cima do diretório de trabalho atual.
- O .NET Core usa o SDK especificado no primeiro global.json encontrado.
- O .NET Core usará o SDK instalado mais recente se nenhuma instância global.json for encontrada.
Por exemplo, na máquina virtual Linux de teste, você deve ter os SDKs do .NET Core 3.1 e 5.0 instalados. Se você executar o .NET Core incluindo a --version
opção, deverá ver que a versão mais recente é usada.
Agora, crie um arquivo global.json no diretório atual (seu diretório inicial) e defina a versão explicitamente usando a ferramenta cat, conforme mostrado. Em seguida, verifique a versão novamente. Agora ele está mostrando a versão exata do SDK que você colocou dentro do arquivo global.json .
É importante saber quando você executa alguns comandos do SDK, como criar um aplicativo usando o comando .NET Core new
. No entanto, você não precisará fazer isso ao usar as ferramentas dotnet-dump e dotnet-gcdump.
O SDK do .NET Core instala a versão mais recente das ferramentas, independentemente de qual SDK você selecionou. Por exemplo, se você executou os comandos para instalar as ferramentas dotnet-dump, dotnet-gcdump e dotnet-symbol para o SDK do .NET Core 3.1, as versões mais recentes dessas ferramentas serão baixadas e instaladas, conforme mostrado na captura de tela a seguir (em que a versão 5 das ferramentas para dotnet-dump e dotnet-gcdump foi instalada).
Os artigos a seguir são ótimos recursos para obter mais informações sobre as ferramentas do .NET Core:
Observação
Selecionar a versão do runtime a ser usada é diferente de selecionar a versão do SDK. Se você quiser usar uma versão específica do runtime do .NET, use a opção --fx-version <VERSION>, conforme explicado neste artigo.
Próximas etapas
Agora você está pronto para começar os laboratórios de solução de problemas. Nos laboratórios, você aprenderá a usar as ferramentas discutidas aqui para solucionar problemas.
Laboratório 1.1 Reproduzir e solucionar um problema de falha