segunda-feira, 12 de fevereiro de 2007

Diagnosticando Aplicações .Net (Performance e Exceptions)

Por Mauricio Medina e Paulo Barros

Muito raramente se encontra uma equipe de desenvolvimento que realmente se preocupe com a saúde da aplicação ao longo do tempo. O que comumente se vê é o ciclo: desenvolvimento, testes/homologação e deployment (suprimimos aqui as fases de concepção). Depois de algum tempo de implantada, geralmente de 1 a 3 meses, a aplicação é dada como finalizada e estável. Nada está mais longe da verdade.

Existem uma série de fatores internos e externos que “conspiram” para desestabilizar a aplicação. Por exemplo: a aplicação está constantemente sofrendo modificações em seus dados, que podem crescer rapidamente afetando o desempenho, o ambiente no qual a aplicação está não é de modo algum estático, o tráfego de rede pode aumentar devido a um maior número de usuários, a performance de resposta do banco de dados pode ser afetada por outras aplicações que agora utilizam o mesmo servidor, uma nova aplicação está demandando mais CPU, um novo componente instalado no servidor está interferindo e assim vai. As possibilidades são inúmeras para que uma aplicação entregue como OK venha a dar pau meses depois e isso acontece com maior frequência do que imaginamos. Até aqui nenhuma novidade.


Quais são então as boas práticas que deveríamos adotar afim de minimizar os possíveis problemas que uma solução venha a apresentar durante a sua vida?
Este artigo mostrará algumas dicas úteis.

Procurando uma agulha num palheiro

Uma difícil tarefa sempre que se fala que uma aplicação “está lenta” é responder às seguintes perguntas:
· O quão lenta está?
· Lenta em relação a quê?
· O que exatamente está causando o gargalo?
O problema reside muitas vezes na falta de um baseline, ou métricas básicas de referência, que serviriam pra dizer o que é aceitável para cada aplicação. Sem algo em que nos basear, teremos apenas o usuário que na semana passada usou a mesma funcionalidade e “percebeu” que agora está muito pior. Como argumentar com ele? Como dizer que está tudo bem e que ele está vendo coisas? E se ele tiver razão? (por mais incrível que pareça, às vezes esses espécimes estão certos) Bem, se você não tem um baseline fica sem parâmetros.
Outro fator preocupante é a maneira como a maioria realiza os testes a fim de diagnosticar os defeitos da aplicação. Sem ferramentas automatizadas os testes são no mínimo imprecisos e fornecem pouca ou nenhuma informação para se chegar ao cerne da questão. A saída é usar gambiarras paliativas que mascaram a situação. Sem os instrumentos apropriados, identificar o verdadeiro culpado (sistêmico, não humano) fica tão difícil quanto encontrar uma agulha num palheiro.


Acertando o passo

Para irmos na direção certa é preciso criar uma cultura organizacional que envolve disciplina e encontra muita resistência por parte das equipes de TI, mas que tem-se provado benéfica a longo prazo.
O primeiro passo é ter em mente que a aplicação é passível de mudanças mesmo que seu código fonte permaneça inalterado durante meses (desejo utópico dos desenvolvedores) devido aos fatores já citados. Daí temos que estabelecer um baseline para cada aplicação.
A cada mudança de qualquer natureza devemos refazer os testes para verificar preventivamente como está a saúde da aplicação. Isso tem um custo e por isso muitas vezes é descartado como sendo desnecessário. No entanto corrigir um problema imprevisto em produção pode sair muito mais caro.


Preparando os testes

Neste artigo demonstraremos como testes de performance e de tratamento de exceções em aplicações .Net podem nos ajudar a cuidar bem das aplicações das nossas empresas, preparando-nos para as mudanças inevitáveis com um mínimo impacto. Para isso usaremos o Intercept Studio da
AVICode.

Testes de performance

Sem entrar em detalhes sobre a instalação e configuração da ferramenta no ambiente, vamos direto à preparação do agente para capturar problemas de performance numa aplicação web específica. Definimos o que consideramos aceitável e habilitamos o monitor. Todas as ações que excederem o tempo configurado serão interceptadas, analisadas e enviadas para um banco de dados central (Access ou SQL Server).




Poderíamos detalhar melhor o que desejamos monitorar como um método, namespace, assembly, etc:


No módulo de visualização filtramos o tipo de problema que queremos analisar, em que máquina, qual aplicação e em qual período. Vemos no exemplo abaixo páginas aspx com problemas de performance na execução de stored procedures SQL Server:



Podemos visualizar os detalhes de cada ocorrência como erro de SQL, tipo de acesso (neste caso um DataReader), parâmetros usados, tempo de resposta:




Comparar com outros eventos similares:



Verificar os pontos mais críticos do sistema e compará-los com outras aplicações:



Ou ver os tipos de origem do erro por aplicação e quanto isto representa em percentual:




Desta forma temos informações suficientemente precisas de onde está a raiz do problema e portanto não sairemos atirando pra todo lado sem ter certeza do sucesso. No caso exemplificado o problema estava na execução da procedure, foge do escopo deste artigo descer nesse nível, que poderia envolver uma modelagem mal-feita, problemas de rede, hardware, ou o estagiário de infra que mexeu no agendamento do job de reindexão do banco. O ponto é: sabemos agora onde cavar.

A ferramenta já vem por default configurada para capturar os principais vilões responsáveis por problemas de performance como providers de acesso a dados, serviços de mensagem, chamadas remotas de procedimentos, entre outros. Além disso é possível customizar seu alvo:



Capturando erros inesperados

Da mesma forma configuramos o agente para capturar erros da aplicação, entradas no event log ou manipuladores customizados de erro criados pelo desenvolvedor.

Visualizamos a lista filtrada:


E os detalhes:

Podemos identificar onde exatamente no código o erro aconteceu e com o auxílio do plug in para o Visual Studio já abrir o fonte para a correção:

Vimos aqui que é possível com um mínimo esforço conseguir diagnosticar problemas muitas vezes complexos. Se tomarmos por alvo desenvolver e manter aplicações que sobrevivam às intempéries do dia-a-dia começaremos hoje mesmo a medir e periodicamente testar como andam nossas “crianças” para que não virem “monstrengos”.




Nenhum comentário: