Problemas de desempenho ao fazer chamadas para serviços Web de um aplicativo ASP.NET
Este artigo fornece ajuda para resolver os problemas de desempenho que ocorrem quando você faz chamadas para serviços Web de um aplicativo microsoft ASP.NET.
Versão original do produto: ASP.NET
Número de KB original: 821268
Sintomas
Ao fazer chamadas para serviços Web de um aplicativo ASP.NET, você pode ter contenção, desempenho ruim e impasses. Os clientes podem relatar que as solicitações param de responder ou levam muito tempo para serem executadas. Se houver suspeita de um impasse, o processo de trabalho poderá ser reciclado.
Você pode receber a seguinte mensagem de erro de exceção ao fazer uma chamada para o HttpWebRequest.GetResponse
método:
"System.InvalidOperationException: não havia threads gratuitos suficientes no objeto ThreadPool para concluir a operação."
Você também pode receber a seguinte mensagem de erro de exceção no navegador:
"HttpException (0x80004005): Tempo limite de solicitação."
Observação
Este artigo também se aplica a aplicativos que fazem HttpWebRequest
solicitações diretamente.
Motivo
Esse problema pode ocorrer porque ASP.NET limita o número de threads de trabalho e threads de porta de conclusão que uma chamada pode usar para executar solicitações.
Normalmente, uma chamada para um serviço Web usa um thread de trabalho para executar o código que envia a solicitação e um thread de porta de conclusão para receber o retorno de chamada do serviço Web. No entanto, se a solicitação for redirecionada ou exigir autenticação, a chamada poderá usar até dois threads de trabalho e dois threads de porta de conclusão. Portanto, você pode esgotar o gerenciado ThreadPool
quando várias chamadas de serviço Web ocorrem ao mesmo tempo.
Por exemplo, suponha que o ThreadPool
esteja limitado a 10 threads de trabalho e que todos os 10 threads de trabalho estejam executando o código que está aguardando um retorno de chamada para ser executado. O retorno de chamada nunca pode ser executado, pois todos os itens de trabalho que estão enfileirados no ThreadPool
estão bloqueados até que um thread fique disponível.
Outra fonte potencial de contenção é o maxconnection
parâmetro que o System.Net
namespace usa para limitar o número de conexões. Geralmente, esse limite funciona conforme o esperado. No entanto, se muitos aplicativos tentarem fazer muitas solicitações para um único endereço IP ao mesmo tempo, os threads poderão ter que esperar por uma conexão disponível.
Resolução
Para resolve esses problemas, você pode ajustar os seguintes parâmetros no arquivo Machine.config para se adequar melhor à sua situação:
maxWorkerThreads
minWorkerThreads
maxIoThreads
minFreeThreads
minLocalRequestFreeThreads
maxconnection
executionTimeout
Para resolve esses problemas com êxito, execute as seguintes ações:
- Limite o número de solicitações ASP.NET que podem ser executadas ao mesmo tempo para aproximadamente 12 por CPU.
- Permitir que os retornos de chamada do serviço Web usem threads livremente no
ThreadPool
. - Selecione um valor apropriado para o
maxconnections
parâmetro. Baseie sua seleção no número de endereços IP e AppDomains usados.
Observação
A recomendação de limitar o número de solicitações de ASP.NET para 12 por CPU é um pouco arbitrária. No entanto, esse limite provou funcionar bem para a maioria dos aplicativos.
MaxWorkerThreads e maxIoThreads
ASP.NET usa as duas seguintes configurações de configuração para limitar o número máximo de threads de trabalho e threads de conclusão usados:
<processModel maxWorkerThreads="20" maxIoThreads="20">
O maxWorkerThreads
parâmetro e o maxIoThreads
parâmetro são implicitamente multiplicados pelo número de CPUs. Por exemplo, se você tiver dois processadores, o número máximo de threads de trabalho será 2 * maxWorkerThreads
.
MinFreeThreads e minLocalRequestFreeThreads
ASP.NET também contém as seguintes configurações de configuração que determinam quantos threads de trabalho e threads de porta de conclusão devem estar disponíveis para iniciar uma solicitação remota ou uma solicitação local:
<httpRuntime minFreeThreads="8" minLocalRequestFreeThreads="8">
Se não houver threads suficientes disponíveis, a solicitação será enfileirada até que threads suficientes sejam gratuitos para fazer a solicitação. Portanto, ASP.NET não executará mais do que o seguinte número de solicitações ao mesmo tempo:
(maxWorkerThreads
* número de CPUs) - minFreeThreads
Observação
O minFreeThreads
parâmetro e o minLocalRequestFreeThreads
parâmetro não são implicitamente multiplicados pelo número de CPUs.
Minworkerthreads
ASP.NET também contém a seguinte configuração que determina quantos threads de trabalho podem ser disponibilizados imediatamente para atender a uma solicitação remota.
<processModel minWorkerThreads="1">
Os threads controlados por essa configuração podem ser criados a uma taxa muito mais rápida do que os threads de trabalho criados a partir dos recursos padrão de ajuste de thread do CLR (Common Language Runtime).
Essa configuração permite ASP.NET a solicitações de serviço que podem estar preenchendo repentinamente a fila de solicitação ASP.NET devido a uma lentidão em um servidor de back-end, uma explosão repentina de solicitações do final do cliente ou algo semelhante que causaria um aumento repentino no número de solicitações na fila.
O valor padrão do minWorkerThreads
parâmetro é 1. Recomendamos que você defina o valor do minWorkerThreads
parâmetro como o seguinte valor:
minWorkerThreads
= maxWorkerThreads
/ 2
Por padrão, o minWorkerThreads
parâmetro não está presente no arquivo Web.config nem no arquivo Machine.config . Essa configuração é implicitamente multiplicada pelo número de CPUs.
Maxconnection
O maxconnection
parâmetro determina quantas conexões podem ser feitas em um endereço IP específico. O parâmetro aparece da seguinte maneira:
<connectionManagement>
<add address="*" maxconnection="2">
<add address="http://65.53.32.230" maxconnection="12">
</connectionManagement>
Se o código do aplicativo referenciar o aplicativo por nome de host em vez de endereço IP, o parâmetro deverá aparecer da seguinte maneira:
<connectionManagement>
<add address="*" maxconnection="2">
<add address="http://hostname" maxconnection="12">
</connectionManagement>
Por fim, se o aplicativo estiver hospedado em uma porta diferente de 80, o parâmetro deverá incluir a porta não padrão na URL, semelhante à seguinte:
<connectionManagement>
<add address="*" maxconnection="2">
<add address="http://hostname:8080" maxconnection="12">
</connectionManagement>
As configurações para os parâmetros que são discutidos anteriormente neste artigo estão todas no nível do processo. No entanto, a configuração de maxconnection
parâmetro se aplica ao nível appDomain. Por padrão, como essa configuração se aplica ao nível appDomain, você pode criar um máximo de duas conexões com um endereço IP específico de cada AppDomain em seu processo.
Executiontimeout
ASP.NET usa a seguinte configuração para limitar o tempo de execução da solicitação:
<httpRuntime executionTimeout="90"/>
Você também pode definir esse limite usando a Server.ScriptTimeout
propriedade.
Observação
Se você aumentar o valor do executionTimeout
parâmetro, também poderá ter que modificar a configuração do processModel
responseDeadlockInterval
parâmetro.
Recomendações
As configurações recomendadas nesta seção podem não funcionar para todos os aplicativos. No entanto, as seguintes informações adicionais podem ajudá-lo a fazer os ajustes apropriados.
Se você estiver fazendo uma chamada de serviço Web para um único endereço IP de cada página ASPX, a Microsoft recomenda que você use as seguintes configurações:
- Defina os valores do
maxWorkerThreads
parâmetro e domaxIoThreads
parâmetro como 100. - Defina o valor do
maxconnection
parâmetro como 12*N (em que N é o número de CPUs que você tem). - Defina os valores do
minFreeThreads
parâmetro como 88*N e ominLocalRequestFreeThreads
parâmetro como 76*N. - Defina o valor de
minWorkerThreads
como 50. Lembre-se de queminWorkerThreads
não está no arquivo de configuração por padrão. Você deve adicioná-lo.
Algumas dessas recomendações envolvem uma fórmula simples que envolve o número de CPUs em um servidor. A variável que representa o número de CPUs nas fórmulas é N.
Para essas configurações, se você tiver a hiperthreading habilitada, deverá usar o número de CPUs lógicas em vez do número de CPUs físicas. Por exemplo, se você tiver um servidor de quatro processadores com hiperthreading habilitado, o valor de N nas fórmulas será 8 em vez de 4.
Observação
Ao usar essa configuração, você pode executar no máximo 12 ASP.NET solicitações por CPU ao mesmo tempo porque 100-88=12. Portanto, pelo menos 88*N threads de porta de conclusão e 88*N estão disponíveis para outros usos (como para os retornos de chamada do serviço Web).
Por exemplo, você tem um servidor com quatro processadores e hiperthreading habilitados. Com base nessas fórmulas, você usaria os valores a seguir para as configurações mencionadas neste artigo.
<system.web>
<processModel maxWorkerThreads="100" maxIoThreads="100" minWorkerThreads="50"/>
<httpRuntime minFreeThreads="704" minLocalRequestFreeThreads="608"/>
</system.web>
<system.net>
<connectionManagement>
<add address="[ProvideIPHere]" maxconnection="96"/>
</connectionManagement>
</system.net>
Além disso, quando você usa essa configuração, 12 conexões estão disponíveis por CPU por endereço IP para cada AppDomain. Portanto, no cenário a seguir, muito pouca contenção ocorre quando as solicitações estão aguardando conexões, e a ThreadPool
não está esgotada:
- A Web hospeda apenas um aplicativo (AppDomain).
- Cada solicitação de uma página ASPX faz uma solicitação de serviço Web.
- Todas as solicitações são para o mesmo endereço IP.
No entanto, quando você usa essa configuração, os cenários que envolvem um dos abaixo provavelmente usarão muitas conexões:
- As solicitações são para vários endereços IP.
- As solicitações são redirecionadas (302 status código).
- As solicitações exigem autenticação.
- As solicitações são feitas de vários AppDomains.
Nesses cenários, é uma boa ideia usar um valor menor para o maxconnection
parâmetro e valores mais altos para o minFreeThreads
parâmetro e o minLocalRequestFreeThreads
parâmetro.
Mais informações
Para obter mais informações, confira Melhorando ASP.NET desempenho.
Se você estiver enfrentando um fraco desempenho e contenção no IIS junto com ASP.NET, acesse os seguintes blogs da Microsoft:
Comentários
https://aka.ms/ContentUserFeedback.
Brevemente: Ao longo de 2024, vamos descontinuar progressivamente o GitHub Issues como mecanismo de feedback para conteúdos e substituí-lo por um novo sistema de feedback. Para obter mais informações, veja:Submeter e ver comentários