{"id":1342,"date":"2017-08-10T13:32:31","date_gmt":"2017-08-10T16:32:31","guid":{"rendered":"http:\/\/gianfratti.com\/?p=1342"},"modified":"2017-08-10T15:15:40","modified_gmt":"2017-08-10T18:15:40","slug":"asp-net-troubleshooting-identificando-requisicoes-web-que-nao-respondem","status":"publish","type":"post","link":"https:\/\/gianfratti.com\/index.php\/asp-net-troubleshooting-identificando-requisicoes-web-que-nao-respondem\/","title":{"rendered":"ASP.NET Troubleshooting \u2013 identificando requisi\u00e7\u00f5es web que n\u00e3o respondem"},"content":{"rendered":"<p>Mais um post de troubleshooting baseado em fatos reais.<\/p>\n<p>Recentemente atuei na resolu\u00e7\u00e3o de um problema \u201cmisterioso\u201d em um ambiente de cliente.<!--more--><\/p>\n<h1>Sintoma<\/h1>\n<p>Um usu\u00e1rio ao acessar o aplicativo web reportava que em determinados momentos o sistema n\u00e3o respondia (requisi\u00e7\u00e3o web n\u00e3o retornava). Por exemplo, o browser envia uma requisi\u00e7\u00e3o (POST) para o servidor web mas n\u00e3o recebe resposta, ficando a ampulheta durante um longo per\u00edodo de tempo sem completar com sucesso a execu\u00e7\u00e3o.<\/p>\n<h1>Cen\u00e1rio<\/h1>\n<ul>\n<li>Aplicativo web (ASP.NET WebForms) em apenas um servidor web com IIS7 e .NET Framework 4.0;<\/li>\n<li>Aplicativo web acessa banco de dados SQL Server 2012 em outro servidor;<\/li>\n<li>Aplicativo web acessa outros servi\u00e7os de neg\u00f3cio em servidores diferentes na intranet via TCP e via HTTP;<\/li>\n<li>Nenhum log de problema foi encontrado no Event Viewer ou do aplicativo web (instrumenta\u00e7\u00e3o).<\/li>\n<\/ul>\n<h1>Investiga\u00e7\u00e3o<\/h1>\n<p>A seguir detalho alguns procedimentos realizados para isolar, entender e corrigir o problema.<\/p>\n<h3>Passo 1 \u2013 descartar problemas de rede<\/h3>\n<p>Com as ferramentas de desenvolvimento do browser (F12) identificamos que as requisi\u00e7\u00f5es eram enviadas e ficavam aguardando resposta por um longo per\u00edodo. Ao acessar o mesmo sistema em outra janela an\u00f4nima quase ao mesmo tempo, tudo funcionava.<\/p>\n<p><a href=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/6GNw72C.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" title=\"Browser\" src=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/6GNw72C.png\" alt=\"\" width=\"611\" height=\"364\" \/><\/a>A suspeita de problema de conectividade foi deixada de lado, pelo menos at\u00e9 novos ind\u00edcios.<\/p>\n<h3>Passo 2 \u2013 garantir que a requisi\u00e7\u00e3o misteriosa est\u00e1 chegando no servidor web<\/h3>\n<p>O primeiro foco \u00e9 descartar totalmente o problema de conex\u00e3o do cliente e garantir que o servidor web recebeu a requisi\u00e7\u00e3o que n\u00e3o responde e ent\u00e3o identificar o que est\u00e1 acontecendo com ela dentro do servidor.<\/p>\n<p>Com o recurso de \u201c<a title=\"Request Monitor do IIS 7\" href=\"http:\/\/gianfratti.com\/index.php\/identificando-requisicoes-demoradas-no-iis-7-ou-superior\/\" target=\"_blank\" rel=\"noopener\">Request Monitor<\/a>\u201d do IIS7 foi poss\u00edvel detectar que determinadas requisi\u00e7\u00f5es estavam com um tempo de execu\u00e7\u00e3o bastante alto (\u201cTempo Decorrido\u201d), ou seja, a requisi\u00e7\u00e3o chegou para o IIS e n\u00e3o retornou para o cliente pois ainda estava sendo processada.<\/p>\n<p><a href=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/eWA30HN.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" title=\"Request Monitor do IIS\" src=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/eWA30HN.png\" alt=\"\" width=\"789\" height=\"430\" \/><\/a><\/p>\n<h3>Passo 3 \u2013 Verificando o consumo de recursos do IIS<\/h3>\n<p>Como h\u00e1 uma requisi\u00e7\u00e3o em execu\u00e7\u00e3o por um longo per\u00edodo a investiga\u00e7\u00e3o passou a ser sobre a l\u00f3gica de neg\u00f3cio, a qual poderia estar fazendo algum processamento pesado e demorado. Desta forma, \u00e9 poss\u00edvel utilizar o pr\u00f3prio gerenciador de tarefas para verificar o consumo de recursos como mem\u00f3ria, CPU, rede, etc. (obs: <em>como alternativa poderia ser utilizado o perfmon.exe e os contadores de performance<\/em>)<\/p>\n<p><a href=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/wBCI2bw.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" title=\"Gerenciador de Tarefas\" src=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/wBCI2bw.png\" alt=\"\" width=\"415\" height=\"348\" \/><\/a><\/p>\n<p>Conforme a imagem anterior, o consumo de recursos est\u00e1 bastante baixo ent\u00e3o at\u00e9 novos ind\u00edcios descarta-se qualquer l\u00f3gica pesada de processamento do aplicativo.<\/p>\n<h3>Passo 4 \u2013 Verificando locks<\/h3>\n<p>Como o consumo de CPU apresentou ser p\u00edfio, a desconfian\u00e7a passa para algum lock de recurso ou depend\u00eancia de servi\u00e7os externos acionados pela requisi\u00e7\u00e3o.<br \/>\nPor exemplo, a requisi\u00e7\u00e3o poderia acionar alguma l\u00f3gica de neg\u00f3cio que por sua vez acessa o banco de dados que pode estar sobrecarregado e demorando para responder ou em lock. Outro exemplo de possibilidade \u00e9 o consumo de algum servi\u00e7os externo durante o processamento da requisi\u00e7\u00e3o, por exemplo, algum web service de terceiros.<\/p>\n<p>Como poderia ter muitos cen\u00e1rios diferentes para analisar, uma forma de ir direto ao ponto \u00e9 tirar um dump (fotografia) do processo do servidor web (w3wp.exe) e ver o que ele anda fazendo.<\/p>\n<p><a href=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/afAxoai.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" title=\"Tirando um dump\" src=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/afAxoai.png\" alt=\"\" width=\"389\" height=\"385\" \/><\/a><\/p>\n<h3>Passo 5 \u2013 Analisar o dump<\/h3>\n<p>Para analisar o dump uso o ntsd.exe, ajusto os s\u00edmbolos e carrego as bibliotecas de an\u00e1lise de c\u00f3digo gerenciado. Estes tr\u00eas passos explico em mais detalhes em outro artigo: \u201c<a title=\"ntsd.exe\" href=\"http:\/\/gianfratti.com\/index.php\/identificando-a-causa-de-um-alto-e-crescente-consumo-de-memoria-em-producao\/\" target=\"_blank\" rel=\"noopener\">Identificando a causa de um alto e crescente consumo de mem\u00f3ria em produ\u00e7\u00e3o<\/a>\u201d \u2013 item Passo 3.<\/p>\n<p>Neste momento o interesse est\u00e1 em obter informa\u00e7\u00f5es sobre a pilha de execu\u00e7\u00e3o (stack trace) do processo (w3wp.exe), ou seja, o que cada thread est\u00e1 fazendo.<br \/>\nPara obter esta informa\u00e7\u00e3o utilizo o comando !EEStack -short, que lista a stack trace de todas as threads do processo (<a title=\"sos.dll\" href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/bb190764.aspx\" target=\"_blank\" rel=\"noopener\">refer\u00eancia<\/a>).<\/p>\n<p><a href=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/QYXhyiv.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" title=\"EESTack\" src=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/QYXhyiv.png\" alt=\"\" width=\"742\" height=\"410\" \/><\/a><\/p>\n<p>Uma das threads listadas parece bastante suspeita, pois cont\u00e9m rastro de execu\u00e7\u00e3o de uma requisi\u00e7\u00e3o web do ASP.NET e poderia ser a requisi\u00e7\u00e3o demorada.<\/p>\n<p><a href=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/R41Lra1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" title=\"Thread do ASP.NET\" src=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/R41Lra1.png\" alt=\"\" width=\"742\" height=\"410\" \/><\/a><\/p>\n<p>Olhando em mais detalhes esta stacktrace \u00e9 poss\u00edvel identificar que ela aciona uma rotina de neg\u00f3cio do aplicativo (m\u00e9todo ValidateUser) que por sua vez faz alguma comunica\u00e7\u00e3o via Socket. Ou seja, acessou algum servi\u00e7o externo via TCP e est\u00e1 aguardando uma resposta.<\/p>\n<p>Isto se encaixa com o cen\u00e1rio at\u00e9 aqui investigado.<\/p>\n<p><a href=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/l4OIz0l.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" title=\"Socket.Receive\" src=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/l4OIz0l.png\" alt=\"\" width=\"742\" height=\"410\" \/><\/a><\/p>\n<p>A suspeita de que a requisi\u00e7\u00e3o est\u00e1 aguardando algo est\u00e1 se comprovando v\u00e1lida, falta descobrir qual \u00e9 o servi\u00e7o externo acessado e porque est\u00e1 demorando em responder.<\/p>\n<p>A thread 57 \u00e9 a que cont\u00e9m o poss\u00edvel problema, ent\u00e3o alterno o contexto para investigar apenas ela. Para isto, uso o comando ~57s.<\/p>\n<p><a href=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/2dc9LR2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" title=\"Investigando a thread 57\" src=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/2dc9LR2.png\" alt=\"\" width=\"516\" height=\"307\" \/><\/a><\/p>\n<p>Sabendo que o problema est\u00e1 em uma comunica\u00e7\u00e3o com Socket, investigo os objetos do tipo Socket que est\u00e3o em mem\u00f3ria.<br \/>\nEstes objetos poder\u00e3o dizer algo sobre onde est\u00e1 o servi\u00e7o remoto que est\u00e1 causando o problema.<\/p>\n<p><a href=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/4YYKT8u.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" title=\"Investigando objetos do tipo Socket\" src=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/4YYKT8u.png\" alt=\"\" width=\"474\" height=\"195\" \/><\/a><\/p>\n<p>No caso encontrou apenas um objeto, ent\u00e3o agora obt\u00eam-se mais detalhes sobre este objeto.<br \/>\nO objeto possui um campo do tipo EndPoint que pode dizer com quem est\u00e1 se comunicando.<\/p>\n<p><a href=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/AXaRjVw.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" title=\"Informa\u00e7\u00f5es sobre o objeto Socket\" src=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/AXaRjVw.png\" alt=\"\" width=\"577\" height=\"200\" \/><\/a><\/p>\n<p>Investigo o campo EndPoint para obter mais informa\u00e7\u00f5es.<\/p>\n<p><a href=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/ckXJKeC.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" title=\"Investigando o EndPoint\" src=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/ckXJKeC.png\" alt=\"\" width=\"573\" height=\"145\" \/><\/a><\/p>\n<p>O EndPoint possui um campo do tipo IPAddress e o n\u00famero da porta de comunica\u00e7\u00e3o, no caso da porta j\u00e1 \u00e9 poss\u00edvel saber o valor: 5337.<br \/>\nPara obter o IP \u00e9 necess\u00e1rio obter mais informa\u00e7\u00f5es sobre o objeto IPAddress.<\/p>\n<p><a href=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/6uKibKl.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" title=\"Investigando o objeto EndPoint\" src=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/6uKibKl.png\" alt=\"\" width=\"666\" height=\"283\" \/><\/a><\/p>\n<p>Obtenho mais informa\u00e7\u00f5es atrav\u00e9s do m_ToString e ent\u00e3o consigo ver o IP do servi\u00e7o externo.<\/p>\n<p><a href=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/BsKnk1H.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" title=\"Obtendo o IP do servi\u00e7o remoto\" src=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/BsKnk1H.png\" alt=\"\" width=\"664\" height=\"143\" \/><\/a><\/p>\n<h1>Conclus\u00e3o<\/h1>\n<p>Desfeito o mist\u00e9rio foi necess\u00e1rio explicar para a equipe do aplicativo o que estava acontecendo e tratar o motivo do servi\u00e7o externo n\u00e3o estar respondendo em alguns momentos. Al\u00e9m disso, recomendar ajustes no aplicativo web para melhor se comportar com esse cen\u00e1rio sem impactar em outras requisi\u00e7\u00f5es do aplicativo web.<\/p>\n<p>Segundo dados coletados pelo Dump foi poss\u00edvel identificar que: <em>o m\u00e9todo ValidateUser do MembershipProvider customizado pelo aplicativo est\u00e1 acessando um servi\u00e7o externo no IP 192.168.104.11 e porta 5337 e este servi\u00e7o n\u00e3o responde adequadamente<\/em>.<\/p>\n<p>Neste cen\u00e1rio caso n\u00e3o utiliz\u00e1ssemos o recurso de dump poder\u00edamos gastar minutos preciosos em suposi\u00e7\u00f5es de cen\u00e1rios de problema.<br \/>\nO dump permitiu atuar de forma r\u00e1pida e direta no problema em quest\u00e3o, sem perda de tempo.<\/p>\n<p>Fonte: <a href=\"http:\/\/www.rafaelleonhardt.com.br\/2013\/09\/26\/asp-net-troubleshooting-identificando-requisicoes-web-que-nao-respondem\/\" target=\"_blank\" rel=\"noopener\">Clique aqui<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Mais um post de troubleshooting baseado em fatos reais. Recentemente atuei na resolu\u00e7\u00e3o de um problema \u201cmisterioso\u201d em um ambiente de cliente.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[201,200],"tags":[],"class_list":["post-1342","post","type-post","status-publish","format-standard","hentry","category-net","category-troubleshooting"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/gianfratti.com\/index.php\/wp-json\/wp\/v2\/posts\/1342","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gianfratti.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gianfratti.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gianfratti.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/gianfratti.com\/index.php\/wp-json\/wp\/v2\/comments?post=1342"}],"version-history":[{"count":4,"href":"https:\/\/gianfratti.com\/index.php\/wp-json\/wp\/v2\/posts\/1342\/revisions"}],"predecessor-version":[{"id":1423,"href":"https:\/\/gianfratti.com\/index.php\/wp-json\/wp\/v2\/posts\/1342\/revisions\/1423"}],"wp:attachment":[{"href":"https:\/\/gianfratti.com\/index.php\/wp-json\/wp\/v2\/media?parent=1342"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gianfratti.com\/index.php\/wp-json\/wp\/v2\/categories?post=1342"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gianfratti.com\/index.php\/wp-json\/wp\/v2\/tags?post=1342"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}