Quando o servidor web IIS 6.0 para de aceitar qualquer requisição

Quando o servidor web IIS 6.0 para de aceitar qualquer requisição

Por: João Carlos Delinger de Souza

O blog de hoje é relacionado a um caso que foi aberto conosco aqui na Microsoft há um tempo atrás. Era um servidor Windows 2003 com IIS6 mais OWA instalado. O sintoma era o seguinte: qualquer requisição feita nesse servidor nos emitia o seguinte erro:

“Page cannot be displayed”.

Esses foram os testes feitos durante os primeiros minutos:

- qualquer página ASP de qualquer web site dava o erro;
- qualquer página ASP (de Application Pools diferentes) dava o erro;
- (se não estou enganado), TELNET na porta 80 funcionava ok;
- netstat –an mostrava o status “Listening” nas devidas portas;
- não haviam erros no event viewer;
- criou-se uma página ASP de teste simples e tivemos o mesmo problema;
- criou-se uma página HTM de teste e tivemos o mesmo erro;
- criou-se um novo web site num Application Pool novo também e tivemos o mesmo erro;

Enfim, creio que fizemos mais testes, checamos o básico mas sempre tinhamos o mesmo erro. Por um momento voce pensa se vale a pena tirar um dump de memória do processo para ver o status das threads mas esse não era o caso pois não tinhamos ninguem conectado nas aplicações! (de acordo com logs do Performance Monitor) e mesmo após um “Recycle” no processo sempre tinhamos o mesmo erro. Não era falta de threads no processo w3wp.exe e nem problema de permissão.

Bom, continuando com o troubleshooting você começa a checar o que foi logado nos logs do IIS..... e para minha felicidade NADA foi logado.
Digo felicidade porque isso era um indicio de que as requisições não estavam passando pelo driver HTTP.SYS (na versão IIS6 somente) antes de serem logadas no log do IIS. Isso significa que algo estava acontecendo nessa camada desse componente.

Então o próximo passo, era checar o log “HTTP error”, localizado por default, na pasta %systemroot%\system32\logfiles\httperr.

Em todas as requisições nós viamos a seguinte string “Connections_Refused” . Bom, agora você me pergunta, mas porque as requisições estavam sendo recusadas?
Procurando por essa string no nosso banco de dados você irá encontrar o artigo abaixo:

820729 Error logging in HTTP API: https://support.microsoft.com/default.aspx?scid=kb;EN-US;820729

Que diz o seguinte:

“Connections_Refused - The kernel NonPagedPool memory has dropped below 20MB and http.sys has stopped receiving new connections”.

Ollhando no Task Manager desse servidor via-se realmente que o Kernel Memory(NonPaged) estava relativamente alto; em torno de 118,000 enquanto que outros servidores OWA que o cliente tinha no mesmo ambiente mostravam apenas 30,000.
Bom, o que temos aqui? Fato: o HTTP.SYS não irá mais receber nenhuma requisição se o valor de memória disponível para o NonPagedPool for menor do que 20 MB.

Mas porque isso acontece? Bom, primeiro porque o sistema operacional estabelece certos limites dependendo da quantidade de memória RAM da máquina.
No caso desse servidor em que trabalhavamos (2GB RAM), nós teriamos os seguinte valores:

2GB Default:
------------
*** Virtual Memory Usage ***
Physical Memory: 524173 ( 2096692 Kb)
Free System PTEs: 196423 ( 785692 Kb)
NonPagedPool Max: 65536 ( 262144 Kb) - esse seria o valor máximo do NonPagedPool
PagedPool Maximum: 90112 ( 360448 Kb)

No entanto esse cliente estava usando o parametro 3GB no arquivo boot.ini o que diminui o nosso “address space” na área de kernel:

2GB + /3GB switch:
------------------
*** Virtual Memory Usage ***
Physical Memory: 524173 ( 2096692 Kb)
Free System PTEs: 16034 ( 64136 Kb)
NonPagedPool Max: 32767 ( 131068 Kb) - esse seria o valor máximo do NonPagedPool
PagedPool Maximum: 65536 ( 262144 Kb)

Agora faça as contas: 131,068 - 118,000 nos dá em torno de 13,000 Kb sobrando para o NonPagedPool, o que é menor do que os 20 MB citado acima.

Workaround:

Se você adicionar a chave abaixo, você consegue mudar o limite para 8 MB, ou seja, o HTTP.SYS para de responder as requisições quando tivermos menos do que 8 MB de memória sobrando para o NonPagedPool.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP\Parameters\EnableAggressiveMemoryUsage = 1

Solução:

Não usar o switch /3GB para aumentar o ‘address space’ da area de kernel ou investigar quem/qual kernel driver está consumindo tanto o NonPagedPool.
Talvez tenhamos um ‘kernel leak’, e nesse caso precisariamos usar uma ferramenta chamada “Poolmon” para monitorar o servidor:

177415 How to Use Memory Pool Monitor (Poolmon.exe) to Troubleshoot Kernel Mode Memory Leaks
https://support.microsoft.com/default.aspx?scid=kb;EN-US;177415

É isso aí pessoal. Até a próxima!

--João Carlos Delinger de Souza