O que está limitando o número de conexões simultâneas que meu aplicativo ASP.NET pode fazer com um serviço da web?

90

Eu tenho um aplicativo ASP.NET 4.0 em execução no IIS 7.5 em uma máquina Windows Server 2008 R2 Enterprise de 64 bits com montes de RAM, CPU, disco, etc.

Com cada solicitação da Web, o aplicativo ASP.NET faz uma conexão com um serviço da Web de back-end (por meio de soquetes brutos), que está sendo executado na mesma máquina.

Problema: parece haver algo limitando o número de conexões simultâneas ao serviço da web de back-end. Suspeito, o número de conexões simultâneas está chegando a 16.

Encontrei este artigo importante da Microsoft explicando como ajustar as configurações do IIS para acomodar aplicativos ASP.NET que fazem muitas solicitações de serviço da Web: http://support.microsoft.com/?id=821268#tocHeadRef

Segui as recomendações do artigo, mas ainda sem sorte. A configuração que é particularmente interessante é a maxconnectionconfiguração, que até aumentei para 999.

Alguma ideia do que mais poderia ser conexões de estrangulamento?

Observação: quando eu excluo o IIS da mistura e faço com que os clientes se conectem diretamente ao serviço da web de back-end, ele felizmente abrirá quantas conexões forem necessárias, portanto, tenho certeza de que o back-end não é o gargalo. Deve ser algo na área do IIS / ASP.NET.

Esta é a seção relevante do machine.configque tenho certeza que está sendo lida pelo aplicativo (verificado com appcmd.exe):

<system.web>
    <processModel autoConfig="false" maxWorkerThreads="100" maxIoThreads="100" minWorkerThreads="50" />
    <httpRuntime minFreeThreads="176" minLocalRequestFreeThreads="152"/>

    <httpHandlers />

    <membership>
        <providers>
            <add name="AspNetSqlMembershipProvider"
                type="System.Web.Security.SqlMembershipProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
                connectionStringName="LocalSqlServer"
                enablePasswordRetrieval="false"
                enablePasswordReset="true"
                requiresQuestionAndAnswer="true"
                applicationName="/"
                requiresUniqueEmail="false"
                passwordFormat="Hashed"
                maxInvalidPasswordAttempts="5"
                minRequiredPasswordLength="7"
                minRequiredNonalphanumericCharacters="1"
                passwordAttemptWindow="10"
                passwordStrengthRegularExpression="" />
        </providers>
    </membership>

    <profile>
        <providers>
            <add name="AspNetSqlProfileProvider" connectionStringName="LocalSqlServer" applicationName="/"
                type="System.Web.Profile.SqlProfileProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        </providers>
    </profile>

    <roleManager>
        <providers>
            <add name="AspNetSqlRoleProvider" connectionStringName="LocalSqlServer" applicationName="/"
                type="System.Web.Security.SqlRoleProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            <add name="AspNetWindowsTokenRoleProvider" applicationName="/"
                type="System.Web.Security.WindowsTokenRoleProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        </providers>
    </roleManager>
</system.web>
<system.net>
    <connectionManagement>
        <add address="*" maxconnection="999"/>
    </connectionManagement>
</system.net>
Rob Sobers
fonte
@DanB tem um bom ponto aqui - como você está medindo o número de conexões simultâneas?
Jeremy McGee
@JeremyMcGee Estou medindo o número de conexões simultâneas executando o TCPView no servidor para ver quantas conexões de back-end são feitas pelos processos de trabalho do IIS.
Rob Sobers,
Os clientes da Web estão executando em máquinas independentes ou na mesma máquina? (Verificando se não há estrangulamento do lado do cliente acontecendo.)
Jeremy McGee
3
@JeremyMcGee Máquinas separadas. 1 conexão cliente-servidor por máquina. Além disso, sabemos que não há limitação em algum lugar da rede porque, quando atingimos o back-end diretamente (o que também acontece por meio de HTTP), não encontramos o gargalo.
Rob Sobers
1
Rob, você já encontrou uma solução definitiva para isso?
electronicKT de

Respostas:

104

A maioria das respostas fornecidas aqui aborda o número de solicitações de entrada para seu serviço da web de back-end, não o número de solicitações de saída que você pode fazer de seu aplicativo ASP.net para seu serviço de back-end.

Não é o seu serviço da web de back-end que está limitando sua taxa de solicitação, é o número de conexões abertas que seu aplicativo de chamada está disposto a estabelecer para o mesmo ponto de extremidade (mesma URL).

Você pode remover essa limitação adicionando a seguinte seção de configuração ao arquivo machine.config:

<configuration>
  <system.net>
    <connectionManagement>
      <add address="*" maxconnection="65535"/>
    </connectionManagement>
  </system.net>
</configuration>

Você pode, é claro, escolher um número mais razoável se desejar, como 50 ou 100 conexões simultâneas. Mas o texto acima irá abri-lo no máximo. Você também pode especificar um endereço específico para a regra de limite de abertura acima, em vez do '*' que indica todos os endereços.

Documentação MSDN para System.Net.connectionManagement

Outro ótimo recurso para entender o ConnectManagement em .NET

Espero que isso resolva seu problema!

EDIT: Opa, vejo que você tem o gerenciamento de conexão mencionado em seu código acima. Vou deixar minhas informações acima, pois são relevantes para futuros inquiridores com o mesmo problema. No entanto, observe que atualmente existem 4 arquivos machine.config diferentes na maioria dos servidores atualizados!

Há o .NET Framework v2 rodando em 32 bits e 64 bits, bem como o .NET Framework v4 também rodando em 32 bits e 64 bits. Dependendo das configurações escolhidas para o pool de aplicativos, você pode usar qualquer um desses 4 arquivos machine.config diferentes! Verifique todos os 4 arquivos machine.config normalmente localizados aqui:

  • C: \ Windows \ Microsoft.NET \ Framework \ v2.0.50727 \ CONFIG
  • C: \ Windows \ Microsoft.NET \ Framework64 \ v2.0.50727 \ CONFIG
  • C: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ Config
  • C: \ Windows \ Microsoft.NET \ Framework64 \ v4.0.30319 \ Config
BenSwayne
fonte
Sim, eu cobri essa base. De qualquer forma, obrigado, @BenSwayne! Verifiquei que modifiquei o correto machine.config(64 bits 4.0).
Rob Sobers,
@RobSobers: Nesse caso, eu ficaria um pouco desconfiado do código de implementação. Talvez você esteja ficando sem tópicos ou algo assim? Você pode lançar seu código de chamada de serviço da web TcpClient em um aplicativo de console e ver se consegue obter uma taxa de solicitação melhor? Isso vai provar se é uma configuração específica do IIS ou uma configuração .NET mais ampla ou seu código.
BenSwayne
Essa linha vai na máquina cliente?
Uri Abramson
obrigado, suas configurações combinam com processModel twekaing de codeproject.com/Articles/133738/… corrigido "ISAPI 'C: \ windows \ Microsoft.Net \ Framework \ v2.0.050727 \ aspnet_isapi.dll' relatou-se como não íntegro pelo seguinte motivo : Problema de "impasse detectado"
Zakos
@BenSwayne o mesmo conceito se aplica a conexões SMTP também? Estou projetando um aplicativo de envio de e-mail em massa, então esta propriedade ConnectionManagement será útil no envio de e-mails em massa também (usando multithreading para a função mail.send )?
vibs2006
7

Sei que a pergunta pode ser bastante antiga, mas você diz que o back-end está sendo executado no mesmo servidor. Isso significa em uma porta diferente, provavelmente diferente da porta 80 padrão.

Eu li que quando você usa o elemento de configuração "connectionManagement", você precisa especificar o número da porta se for diferente do padrão 80.

LINK: a configuração maxConnection pode não funcionar mesmo autoConfig = false no ASP.NET

Em segundo lugar, se você escolher usar a configuração padrão (endereço = "*") estendida com seu próprio valor específico de back-end, você pode considerar colocar o valor específico primeiro! Caso contrário, se uma solicitação for feita, o * corresponde primeiro e o padrão de 2 conexões é usado. Exatamente como quando você usa a seção em web.config.

LINK: Elemento <remove> para connectionManagement (configurações de rede)

Espero que ajude alguém.

Sebastian hek
fonte
5

É possível que você esteja usando uma referência de serviço da web baseada em WCF? Por padrão, ServiceThrottlingBehavior.MaxConcurrentCalls é 16.

Você pode tentar atualizar seu <serviceThrottling>elemento de comportamento de referência de serviço

<serviceThrottling
    maxConcurrentCalls="999" 
    maxConcurrentSessions="999" 
    maxConcurrentInstances="999" />

(Observe que eu recomendo as configurações acima.) Consulte MSDN para obter mais informações sobre como configurar um <behavior>elemento apropriado .

Ruben
fonte
Eu gostaria que estivéssemos, mas não somos. O serviço que está sendo consumido está sendo executado em Apache / Python / mod_wsgi em outra máquina e, como Rob mencionou, claramente não é o problema.
Benjamin Pollack
As referências de serviço estão no cliente. Como seu cliente está consumindo o serviço Apache?
John Saunders
Como o John disse: a limitação é definida no cliente que consome o serviço da web. Talvez a frase "comportamento do seu serviço" seja um pouco enganosa. Faz mais sentido quando expresso como "seu comportamento de referência de serviço"?
Ruben
@john É consumido por meio de um TcpClient(o serviço vende blobs binários personalizados, não WCF / SOAP ou similar). Essas opções de configuração parecem estar impactando puramente se você usar ServiceHost, não TcpClient; estou esquecendo de algo?
Benjamin Pollack
Por que não usar "Adicionar referência de serviço"?
John Saunders,
3

Você tentou definir o valor da propriedade estática DefaultConnectionLimit programaticamente?

Aqui está uma boa fonte de informações sobre essa verdadeira dor de cabeça ... Uso de thread ASP.NET no IIS 7.5, IIS 7.0 e IIS 6.0 , com atualizações para o framework 4.0.

Simon Mourier
fonte
Imagino que isso não importe, mas vou tentar mesmo assim.
Rob Sobers,
Foi assim que consertamos alguns anos atrás. Tivemos problemas de simultaneidade e isso pareceu esclarecer tudo. Net.ServicePointManager.DefaultConnectionLimit = 1000 é o que usamos. Você deve configurá-lo ANTES de criar classes de conexão.
Brain2000
2

Consulte a seção "Threading" desta página: http://msdn.microsoft.com/en-us/library/ff647786.aspx , em conjunto com a seção "Conexões".

Você já tentou aumentar o atributo maxconnection de sua configuração processModel?

Matt Evans
fonte
Sim, eu tenho. Mas aquele artigo que você citou aponta algo interessante que todos os outros artigos sobre o assunto deixaram de mencionar: que o maxconnectionatributo não se aplica a chamadas de serviço web locais . Neste caso particular o serviço web é local, mas temos o mesmo problema em outro ambiente onde o serviço não é local.
Rob Sobers,
@RobSobers - Acho que o link acima vale uma segunda olhada. Verifique a parte sobre minLocalRequestFreeThreads- Este processo de trabalho usa essa configuração para enfileirar solicitações de localhost (onde um aplicativo da Web chama um serviço da Web no mesmo servidor ) se o número de threads disponíveis no pool de threads ficar abaixo desse número. Essa configuração é semelhante a minFreeThreads, mas se aplica apenas a solicitações que usam localhost .
Ahmad
@Ahmad Sim, eu também configurei minLocalRequestFreeThreads(veja minha machine.configpergunta.
Rob Sobers
0

Se não estiver definido no serviço da web ou aplicativo ou servidor (apache ou IIS) que hospeda o consumível do serviço da web, você pode criar conexões infinitas até a falha

Frank tudor
fonte
0

ao fazer o teste de desempenho, a medida que eu uso é RPS, ou seja, quantas solicitações por segundo o servidor pode atender com latência aceitável.

teoricamente, um servidor só pode executar tantas solicitações simultaneamente quanto o número de núcleos nele.

Não parece que o problema seja o modelo de threading do ASP.net, uma vez que pode servir potencialmente a milhares de rps. Parece que o problema pode ser seu aplicativo. Você está usando algum primitivo de sincronização?

também qual é a latência em seus serviços da web, eles são muito rápidos para responder (em microssegundos), se não, você pode querer considerar chamadas assíncronas, para que você não acabe bloqueando

Se isso não render nada, você pode querer criar um perfil de seu código usando o visual studio ou redgate profiler

np-hard
fonte