Quando efectua chamadas para serviços Web XML a partir de uma aplicação ASP.NET, poderá detectar problemas de contenção, desempenho fraco e bloqueios. Os clientes podem reportar que os pedidos deixaram de responder (ou "bloquearam") ou demoraram muito tempo a serem executados. Se suspeitar de um bloqueio, poderá reciclar o processo de trabalho. Poderá receber as seguintes mensagens no registo de eventos de aplicações.
- Se estiver a utilizar o Microsoft IIS 5.0 (Serviços de informação Internet - Internet Information Services), receberá as seguintes mensagens no registo de eventos de aplicações:
Tipo de evento: Erro
Origem do evento: ASP.NET 1.0.3705.0
Categoria do evento: Nenhuma
ID do evento: 1003
Data: 5/4/2003
Hora: 6:18:23 PM
Utilizador: N/D
Computador: <Nomedocomputador>
Descrição:
aspnet_wp.exe (PID: <xxx>) was recycled because it was suspected to be in a deadlocked state.
It did not send any responses for pending requests in the last 180 seconds. - Se estiver a utilizar o IIS 6.0, recebe as seguintes mensagens no registo de eventos de aplicações:
Tipo de evento: Aviso
Origem do evento: W3SVC-WP
Categoria do evento: Nenhuma
ID do evento: 2262
Data: 5/4/2003
Hora: 1:02:33 PM
Utilizador: N/D
Computador: <Nomedocomputador>
Descrição:
O ISAPI 'C:\Windows\Microsoft.net\Framework\v.1.1.4322\aspnet_isapi.dll' comunicou estar
danificado devido à seguinte razão: 'Bloqueio total detectado'. - Se estiver a utilizar o IIS 6.0, receberá as seguintes mensagens no registo de eventos do sistema:
Tipo de evento: Aviso
Origem do evento: W3SVC
Categoria do evento: Nenhuma
ID do evento: 1013
Data: 5/4/2003
Hora: 1:03:47 PM
Utilizador: N/D
Computador: <Nomedocomputador>
Descrição:
Um processo que fornecia serviços ao agrupamento de aplicações 'DefaultAppPool' excedeu os limites de tempo durante o encerramento.
ID do processo '<xxxx>'.
Também poderá receber a seguinte mensagem de erro de excepção quando efectua uma chamada para o método
HttpWebRequest.GetResponse:
?System.InvalidOperationException: There were not enough free threads in the ThreadPool object to complete the operation.?
Também poderá receber a seguinte mensagem de erro de excepção no browser:
?HttpException (0x80004005): Request timed out.?
Nota: este artigo aplica-se às aplicações que efectuam pedidos
HttpWebRequest directamente.
Este problema poderá ocorrer porque o ASP.NET limita o número de threads de trabalho e de threads de porta de conclusão que poderão ser utilizados por uma chamada para executar pedidos.
Normalmente, uma chamada para um serviço Web utiliza um thread de trabalho para executar o código que envia o pedido e um thread de porta de conclusão para receber a chamada de retorno do serviço Web. No entanto, se o pedido for redireccionado ou necessitar de autenticação, a chamada poderá utilizar até dois threads de trabalho e dois threads de porta de conclusão. Por conseguinte, poderá esgotar o ThreadPool gerido quando ocorrerem múltiplas chamadas de serviços Web ao mesmo tempo.
Por exemplo, suponha que o ThreadPool está limitado a 10 threads de trabalho e todos os 10 threads de trabalho estão actualmente a executar código que aguarda a execução de uma chamada de retorno. A chamada de retorno poderá nem ser executada porque os itens de trabalho em fila de espera para o ThreadPool são bloqueados até que um thread seja disponibilizado.
Outra origem possível de contenção é o parâmetro
maxconnection utilizado pelo espaço de nomes
System.Net para limitar o número de ligações. Geralmente, este limite funciona como previsto. No entanto, se muitas aplicações tentarem efectuar muitos pedidos para um único endereço IP ao mesmo tempo, os threads poderão ter de aguardar por uma ligação disponível.
Para resolver estes problemas, pode ajustar os seguintes parâmetros no ficheiro Machine.config, conforme a sua situação:
- maxWorkerThreads
- minWorkerThreads
- maxIoThreads
- minFreeThreads
- minLocalRequestFreeThreads
- maxconnection
- executionTimeout
Para resolver estes problemas com êxito, proceda da seguinte forma:
- Limite o número de pedidos ASP.NET que podem ser executados ao mesmo tempo para aproximadamente 12 por CPU.
- Permita que as chamadas de retorno de serviços Web utilizem threads livremente no ThreadPool.
- Seleccione um valor adequado para o parâmetro maxconnections. Baseie a sua selecção no número de endereços IP e AppDomains utilizados.
Nota: a recomendação para limitar o número de pedidos ASP.NET em 12 por CPU é um pouco arbitrária. No entanto, na maioria das aplicações este limite funcionou correctamente.
maxWorkerThreads e maxIoThreads
O ASP.NET utiliza as seguintes duas definições de configuração para limitar o número máximo de threads de trabalho e de threads de conclusão utilizados:
<processModel maxWorkerThreads="20" maxIoThreads="20">
O parâmetro
maxWorkerThreads e o parâmetro
maxIoThreads são multiplicados implicitamente pelo número de CPUs. Por exemplo, se tiver dois processadores, o número máximo de threads de trabalho é o seguinte:
2*maxWorkerThreads
minFreeThreads e minLocalRequestFreeThreads
O ASP.NET também contém as seguintes definições de configuração que determinam quantos threads de trabalho e threads de portas de conclusão têm de estar disponíveis para iniciar um pedido remoto ou um pedido local:
<httpRuntime minFreeThreads="8" minLocalRequestFreeThreads="8">
Se não existirem threads suficientes disponíveis, o pedido é colocado em fila de espera até que sejam disponibilizados threads suficientes para efectuarem o pedido. Por conseguinte, o ASP.NET não executará mais do que o seguinte número de pedidos ao mesmo tempo:
(maxWorkerThreads*número de CPUs)-minFreeThreads
Nota: os parâmetros
minFreeThreads e
minLocalRequestFreeThreads não são multiplicados implicitamente pelo número de CPUs.
minWorkerThreads
Como o ASP.NET 1.0 Service Pack 3 e o ASP.NET 1.1, o ASP.NET também contém a seguinte definição de configuração que determina quantos threads de trabalho poderão ser disponibilizados imediatamente para executar um pedido remoto.
<processModel minWorkerThreads="1">
Os threads que são controlados por esta definição podem ser criados mais rapidamente do que os threads de trabalho que são criados a partir de funcionalidades predefinidas de "ajuste de threads" de CLR. Esta definição permite que o ASP.NET execute pedidos que subitamente poderão estar a preencher a fila de pedidos ASP.NET em espera devido a um abrandamento num servidor back end, um súbito aumento de pedidos do lado do cliente, ou uma situação semelhante que poderá causar um aumento inesperado do número de pedidos em fila de espera. O valor predefinido do parâmetro
minWorkerThreads é 1. A Microsoft recomenda que defina o valor do parâmetro
minWorkerThreads com o seguinte valor.
minWorkerThreads = maxWorkerThreads / 2
Por predefinição, o parâmetro
minWorkerThreads não existe no ficheiro Web.config nem no ficheiro Machine.config. Esta definição é multiplicada implicitamente pelo número de CPUs.
maxconnection
O parâmetro
maxconnection determina quantas ligações podem ser efectuadas para um endereço IP específico. O parâmetro é apresentado da seguinte forma:
<connectionManagement>
<add address="*" maxconnection="2">
<add address="65.53.32.230" maxconnection="12">
</connectionManagement>As definições para os parâmetros abordados anteriormente neste artigo encontram-se todas em processamento. No entanto, a definição do parâmetro
maxconnection aplica-se ao nível de AppDomain. Por predefinição, uma vez que esta definição se aplica ao nível de AppDomain, pode criar duas ligações no máximo para um endereço IP específico a partir de cada AppDomain no processo.
executionTimeout
O ASP.NET utiliza a seguinte definição de configuração para limitar o tempo de execução do pedido:
<httpRuntime executionTimeout="90"/>
Também pode definir este limite utilizando a propriedade
Server.ScriptTimeout.
Nota: se aumentar o valor do parâmetro
executionTimeout, também poderá necessitar de modificar a definição do parâmetro
processModel responseDeadlockInterval.
Recomendações
As definições recomendadas nesta secção poderão não funcionar em todas as aplicações. No entanto, as informações adicionais que se seguem poderão ajudá-lo a efectuar os ajustes adequados.
Se estiver a efectuar uma chamada de serviço Web para um único endereço IP a partir de cada página ASPX, a Microsoft recomenda que utilize as seguintes definições de configuração:
- Defina os valores do parâmetro maxWorkerThreads e do parâmetro maxIoThreads como 100.
- Defina o valor do parâmetro maxconnection como 12*N (em que N corresponde ao número de CPUs existentes).
- Defina os valores do parâmetro minFreeThreads como 88*N e do parâmetro minLocalRequestFreeThreads como 76*N.
- Defina o valor de minWorkerThreads como 50. Lembre-se que, minWorkerThreads não se encontra no ficheiro de configuração por predefinição. Tem de adicioná-lo.
Algumas destas recomendações implicam uma simples fórmula que envolve o número de CPUs de um servidor. A variável que representa o número de CPUs nas fórmulas é
N. Nestas definições, se tiver a hyperthreading activada, terá de utilizar o número de CPUs lógicas em vez de o número de CPUs físicas. Por exemplo, se tiver um servidor com quatro processadores com a hyperthreading activada, o valor de
N nas fórmulas será
8 em vez de
4.
Nota: quando utiliza esta configuração, pode executar no máximo 12 pedidos ASP.NET por CPU ao mesmo tempo porque
100-88=12. Por conseguinte, pelo menos 88*
N threads de trabalho e 88*
N threads de porta de conclusão estão disponíveis para outras utilizações (como para chamadas de retorno de serviços Web).
Por exemplo, tem um servidor com quatro processadores e hyperthreading activada. Com base nestas fórmulas, utilizará os seguintes valores para as definições de configuração mencionadas neste artigo.
<processModel maxWorkerThreads="100" maxIoThreads="100" minWorkerThreads="50">
<httpRuntime minFreeThreads="704" minLocalRequestFreeThreads="608">
<connectionManagement>
<add address="[ProvideIPHere]" maxconnection="96"/>
</connectionManagement>
Do mesmo modo, quando utiliza esta configuração, existem 12 ligações disponíveis para CPU por endereço IP para cada AppDomain. Por conseguinte, no seguinte cenário, ocorre muito pouca contenção quando os pedidos aguardam por ligações e o ThreadPool não é totalmente utilizado:
- A Web hospeda apenas uma aplicação (AppDomain).
- Cada pedido para uma página ASPX corresponde a um pedido de serviço Web.
- Todos os pedidos são para o mesmo endereço IP.
No entanto, quando utiliza esta configuração, os cenários que envolvem uma das seguintes situações provavelmente utilizarão demasiadas ligações:
- Os pedidos são para múltiplos endereços IP.
- Os pedidos são redireccionados (código de estado 302).
- Os pedidos requerem autenticação.
- Os pedidos são efectuados a partir de múltiplos AppDomains.
Nestes cenários, deve utilizar um valor inferior para o parâmetro
maxconnection e valores mais elevados para os parâmetros
minFreeThreads e
minLocalRequestFreeThreads.