Desafio da Semana #11



DESAFIO DA SEMANA #11


 


 


Por: Roberto Alexis Farah


 


Olá pessoal!


O desafio dessa semana se baseia num incidente de suporte real que trabalhei recentemente.


 


Primeiro um pouco de história: o incidente era um sintoma de hang (100% de cpu) em quatro servidores IIS, três IIS 5 rodando em Windows 2000 e um IIS 6 rodando em Windows 2003. Todos os servidores acessavam quatro servidores SQL Server 2000 Enterprise rodando em máquinas Windows 2000 Advanced Server.


Como sempre a parte desafiante e que tomou tempo é de se isolar o problema. Uma vez isolado achar a solução é um desafio menor, muitas vezes é algo direto. Ainda algumas vezes alguém menciona algo do tipo: “Ah! Não acredito que era isso!”.


 


Nesse caso em específico o sintoma de alta CPU nos servidores IIS foi isolado para uma determinada página ASP e, posteriormente, para um fragmento de código nessa página ASP. Portanto, partindo-se de vários executáveis cheguei em um fragmento de código fonte; comprovadamente o culpado, embora aparentemente pareça um inofensivo fragmento de código. J


 


Durante a investigação me baseei, num primeiro instante, nos únicos dumps que tínhamos, que não foram coletados durante a ocorrência do sintoma. Ainda assim foi possível se criar uma hipótese inicial, onde suspeitei do banco de dados após a análise do dump. Entretanto, uma nova coleta de dumps durante a ocorrência do sintoma mostrou que as threads não seguiam um padrão quando comparadas com o dump anterior, com isso descartei a primeira hipótese e elaborei outra que se mostrou correta, uma vez que a informação, na segunda vez, foi coletada no momento do sintoma.


 


Aqui vale uma explicação sobre hipóteses: criar uma hipótese e tentar comprová-la é um modo de nos mantermos focados em uma direção. A grande vantagem disso é justamente de evitar força-bruta durante a investigação e agir estrategicamente, com um objetivo em mente. Quando a hipótese é comprovada isso significa muitas vezes que o problema foi isolado ou que estamos muito perto disso. Entretanto, quando a hipótese é descartada isso também é um bom resultado! Explico: quando você coleta informação suficiente para descartar uma hipótese baseada em fatos isso permite que você elimine um potencial problema que poderia explicar os sintomas , reduzindo a complexidade do seu problema já que algumas variáveis podem ser seguramente descartadas.


 


Outro fator importante é a percepção do cliente. Um engenheiro que tenta isolar um problema com base em ações sem propósito definido, ações aleatórias sem uma estratégia que faça sentido certamente não será bem visto pelo cliente, além de comprometer o tempo de resolução do problema. Qualquer cliente espera que o engenheiro saiba conduzir a investigação, portanto, é fundamental usar um (eu diria entre vários) ensinamento do xadrez: “todo movimento deve ter um propósito”, ou seja, toda ação deve ter um propósito, para isso as ações devem fazer parte de uma estratégia cujo objetivo é comprovar uma hipótese.


 


Voltando ao nosso problema, durante o início da investigação fiz várias perguntas que usualmente faço antes de tomar qualquer tipo de ação. Em situações reais adiciono outras relacionadas ao ambiente do cliente e as vezes removo algumas caso já tenha a informação. Eis algumas delas:


 


1- Por favor, descreva todos os sintomas que conseguiu identificar.


 


2- Qual o sistema operacional e service pack sendo utilizado?


 


3- Qual a versão de IIS, SQL Server e outros e os respectivos Service Pack?


 


4- Há componentes na solução?


 


5- Qual a linguagem de desenvolvimento utilizada?


 


6- Há alguma particularidade durante os sintomas?


 


7- O sintoma é facilmente reprodutível?


 


8- A ocorrência do sintoma obedece algum padrão?


 


9- O sintoma ocorre nos ambientes de desenvolvimento, homologação e produção?


 


10- O sintoma sempre ocorreu ou passou a ocorrer após alguma mudança?


 


11- Qual a frequência do sintoma? Ela tem se mantido estável?


 


12- O que foi tentado de modo a eliminar o sintoma ou para amenizar os sintomas?


 


13- Quais as mensagens de erro que ocorrem durante o sintoma?


 


 


Muitas vezes com as respostas das perguntas acima é possível se elaborar uma hipótese muito forte, digo, uma hipótese que na maioria das vezes se mostra verdadeira. Nesse incidente em particular me chamou a atenção o fato da aplicação ter funcionado bem desde aproximadamente 2 anos atrás quando foi criada e não ter sofrido alterações recentemente. Entretanto, gradativamente o sintoma de performance baixa e alta CPU começou a se manifestar.


 


Dica: Geralmente sintomas que não existiam algum tempo atrás e gradativamente passaram a se manifestar sem mudanças na aplicação deveriam colocar em True seu flag mental de bProblemasDeEscalabilidade. 😉


 


Abaixo apresento o código ASP causador do sintoma de alta CPU e algumas informações para que você possa deduzir o que poderia ter ocasionado o sintoma de alta CPU e resolver o problema.


 


 


CENÁRIO


 


Aplicação web feita em ASP apresenta alta CPU sempre que o fragmento script abaixo é executado:


 


Set objFso   = Server.CreateObject(“Scripting.FileSystemObject”)


Set objPasta = objFso.GetFolder(Server.MapPath(“/imagens/grande/” & left(rsProduto(“codigo”), 2)))


 


imagemGrande = false


 


For Each objArq in objPasta.Files


 


If ucase(objArq.Name) = ucase(rsProduto(“codigo”) & “.jpg”) then


imagemGrande = true


end if


Next


 


 


Sim… esse códigozinho acima foi o responsável por impactar severamente todos os servidores web do meu cliente! E justamente por isso resolvi criar esse desafio. Desse modo, temos mais exemplo de um problema simples que escapa de desenvolvimento/testes para produção tornando-se um monstro difícil de ser localizado e capaz de criar um impacto enorme nos usuários!


 


Várias threads estavam consumindo 100% de CPU há vários minutos quando executando o loop acima.


 


As imagens JPG de produtos ficavam em um diretório. Basicamente cada produto tinha várias imagens no mesmo diretório. Durante o passar dos anos a quantidade de produtos aumentou bastante… após algum tempo os sintomas começaram. (opa, bProblemasDeEscalabilidade = True J)


O loop não estava travado em uma única linha mas executando continuamente…


 


Nota: A rede estava ok. O diretório de imagens era local e o I/O também estava ok conforme comprovado por logs de Performance Monitor.


 


 


SINTOMA


 


100% de CPU em várias threads sempre quando executavam o fragmento de código acima. O sintoma persistia durante vários minutos.


 


 


OBJETIVO


 


Identifique o PROBLEMA e proponha uma SOLUÇÃO.


 


Dica: Se achar melhor crie um código VBScript ou JavaScript e tente criar a condição que causa o sintoma de alta cpu. Baseado no cenário acima será fácil deduzir…


 


 


Até semana que vem.

Comments (3)

  1. Rodrigo Strauss says:

    1 – O mapeamento de arquivos poderia estar no banco, pra ele não varrer o diretório toda vez. Quando o número de arquivos aumenta muito não existe Cache Manager que resolva

    2 – Precisa colocar um Exit For dentro de If, já que ele continua varrendo os arquivos mesmo se a condição foi encontrada.

    Ele poderia colocar um job de X em X minutos que varre a pasta e colocar em uma tabela com índice. Aí ele busca no banco. Até um Collection VB acho que melhoraria, mas só dá pra saber mensurando. Ele tb poderia separar os arquivos em pastas de acordo com um critério como os primeiros algarismos do código, pra reduzir o escopo da procura.

  2. Ricardo Bánffy says:

    O que esse código está fazendo? Não seria mais fácil simplesmente verificar se o arquivo existe diretamente em vez de loopar e comparar o nome de cada arquivo? Dúzias de threads loopando por milhares de arquivos arriariam qualquer servidor.

    Randal Schwartz disse certa vez que o PHP é um útil pára-raios, que evita que aqueles que não deviam programar progridam para linguagens "de verdade", permitindo que os programadores "de verdade" vivam mais tranquilos e felizes em suas listas de discussão e canais de IRC.

    O ASP/VBScript cumpre mais ou menos a mesma função.

    Cá pra nós, isso é material para um http://thedailywtf.com/

  3. Roberto A. Farah says:

    Olá Rodrigo e Ricardo,

    Nessa sexta colocarei a solução que utilizei. Continuem participando e se vocês tiverem sugestões de artigos nós adoraríamos saber!

    Obrigado