Che cosa limita il numero di connessioni simultanee che la mia applicazione ASP.NET può effettuare a un servizio Web?


90

Ho un'applicazione ASP.NET 4.0 in esecuzione su IIS 7.5 su una macchina Windows Server 2008 R2 Enterprise a 64 bit con gocce di RAM, CPU, disco, ecc.

Con ogni richiesta Web, l'applicazione ASP.NET effettua una connessione a un servizio Web back-end (tramite socket raw), che è in esecuzione sulla stessa macchina.

Problema: sembra esserci qualcosa che limita il numero di connessioni simultanee al servizio web di backend. Sospettosamente, il numero di connessioni simultanee sta raggiungendo 16.

Ho trovato questo articolo chiave di Microsoft che spiega come modificare le impostazioni di IIS per soddisfare le app ASP.NET che effettuano molte richieste di servizi Web: http://support.microsoft.com/?id=821268#tocHeadRef

Ho seguito le raccomandazioni dell'articolo, ma ancora senza fortuna. L'ambientazione particolarmente interessante è l' maxconnectionambientazione, che ho addirittura portato a 999.

Qualche idea su cos'altro potrebbe limitare le connessioni?

Nota: quando escludo IIS dal mix e faccio in modo che i client si colleghino direttamente al servizio web di backend, aprirà felicemente tutte le connessioni di cui ho bisogno, quindi sono sicuro che il backend non sia il collo di bottiglia. Deve essere qualcosa in IIS / ASP.NET-land.

Ecco la sezione pertinente di machine.configcui sono sicuro viene letta dall'applicazione (verificata con 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>

@ DanB ha un buon punto qui: come stai misurando il numero di connessioni simultanee?
Jeremy McGee

@ JeremyMcGee Sto misurando il numero di connessioni simultanee eseguendo TCPView sul server per vedere quante connessioni back-end vengono effettuate dai processi di lavoro IIS.
Rob Sobers

I client Web sono in esecuzione su macchine indipendenti o sulla stessa macchina? (Controllando che non sia in corso alcun throttling lato client.)
Jeremy McGee

3
@JeremyMcGee Macchine separate. 1 connessione client-server per macchina. Inoltre, sappiamo che non c'è alcuna limitazione da qualche parte sulla rete perché quando raggiungiamo direttamente il backend (cosa che accade anche su HTTP) non incappiamo nel collo di bottiglia.
Rob Sobers

1
Rob, hai mai trovato una soluzione definitiva a questo?
elettronico

Risposte:


104

La maggior parte delle risposte fornite qui riguarda il numero di richieste in entrata al tuo servizio web di backend, non il numero di richieste in uscita che puoi fare dall'applicazione ASP.net al tuo servizio di backend.

Non è il tuo servizio web di backend che sta limitando la tua velocità di richiesta qui, è il numero di connessioni aperte che la tua applicazione chiamante è disposta a stabilire allo stesso endpoint (stesso URL).

È possibile rimuovere questa limitazione aggiungendo la seguente sezione di configurazione al file machine.config:

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

Ovviamente potresti scegliere un numero più ragionevole se desideri, ad esempio 50 o 100 connessioni simultanee. Ma quanto sopra lo aprirà fino a max. Puoi anche specificare un indirizzo specifico per la regola del limite aperto sopra invece di "*" che indica tutti gli indirizzi.

Documentazione MSDN per System.Net.connectionManagement

Un'altra grande risorsa per comprendere ConnectManagement in .NET

Spero che questo risolva il tuo problema!

EDIT: Oops, vedo che hai la gestione della connessione menzionata nel tuo codice sopra. Lascio le mie informazioni di cui sopra in quanto sono rilevanti per i futuri richiedenti con lo stesso problema. Tuttavia, tieni presente che attualmente ci sono 4 diversi file machine.config sulla maggior parte dei server aggiornati!

Esiste .NET Framework v2 in esecuzione sia a 32 bit che a 64 bit, nonché .NET Framework v4 in esecuzione sia a 32 bit che a 64 bit. A seconda delle impostazioni scelte per il pool di applicazioni, potresti utilizzare uno qualsiasi di questi 4 diversi file machine.config! Si prega di controllare tutti e 4 i file machine.config che di solito si trovano qui:

  • 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

Sì, ho coperto quella base. Grazie comunque, @BenSwayne! Ho verificato di aver modificato il corretto machine.config(64 bit 4.0).
Rob Sobers

@ RobSobers: In questo caso sarei un po 'sospettoso del codice di implementazione. Forse stai esaurendo i thread o qualcosa del genere? Puoi lanciare il tuo codice di chiamata del servizio web TcpClient in un'app console e vedere se riesci a ottenere un tasso di richiesta migliore? Ciò dimostrerà se si tratta di una configurazione specifica di IIS o di una configurazione .NET più ampia o del codice.
BenSwayne

Questa linea va nella macchina client?
Uri Abramson

grazie, le tue impostazioni si combinano con processModel twekaing da codeproject.com/Articles/133738/… risolto "ISAPI 'C: \ windows \ Microsoft.Net \ Framework \ v2.0.050727 \ aspnet_isapi.dll' segnalato come malsano per il seguente motivo : Problema "Deadlock rilevato"
Zante

@ BenSwayne vale lo stesso concetto anche per le connessioni SMTP? Sto progettando un'applicazione per l' invio di messaggi di posta elettronica in blocco, quindi questa proprietà ConnectionManagement sarà utile anche per inviare messaggi di posta in blocco (utilizzando il multi threading per la funzione mail.send )?
vibs2006

7

Mi rendo conto che la domanda potrebbe essere piuttosto vecchia, ma dici che il backend è in esecuzione sullo stesso server. Ciò significa su una porta diversa, probabilmente diversa dalla porta predefinita 80.

Ho letto che quando si utilizza l'elemento di configurazione "connectionManagement", è necessario specificare il numero di porta se è diverso da quello predefinito 80.

LINK: l' impostazione maxConnection potrebbe non funzionare anche autoConfig = false in ASP.NET

In secondo luogo, se scegli di utilizzare la configurazione predefinita (address = "*") estesa con il tuo valore specifico di backend, potresti considerare di mettere prima il valore specifico! Altrimenti, se viene effettuata una richiesta, * corrisponde per primo e viene utilizzato il valore predefinito di 2 connessioni. Proprio come quando usi la sezione in web.config.

LINK: <remove> Elemento per connectionManagement (impostazioni di rete)

Spero che aiuti qualcuno.


5

È possibile che tu stia utilizzando un riferimento al servizio Web basato su WCF? Per impostazione predefinita, ServiceThrottlingBehavior.MaxConcurrentCalls è 16.

Potresti provare ad aggiornare l' <serviceThrottling>elemento del comportamento di riferimento del servizio

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

(Notare che consiglierei le impostazioni precedenti.) Vedere MSDN per ulteriori informazioni su come configurare un <behavior>elemento appropriato .


Vorrei che lo fossimo, ma non lo siamo. Il servizio consumato è in esecuzione in Apache / Python / mod_wsgi su un'altra macchina e, come ha detto Rob, chiaramente non è il problema.
Benjamin Pollack

I riferimenti al servizio sono sul client. In che modo il tuo client utilizza il servizio Apache?
John Saunders

Come ha detto John: il throttling viene impostato sul client che utilizza il servizio web. Forse la frase "il tuo comportamento di servizio" è un po 'fuorviante. Ha più senso se espresso come "comportamento di riferimento del servizio"?
Ruben

@john Viene consumato tramite a TcpClient(il servizio vende BLOB binari personalizzati, non WCF / SOAP o simili). Quelle opzioni di configurazione sembrano avere un impatto puramente su di te se usi ServiceHost, no TcpClient; mi sto perdendo qualcosa?
Benjamin Pollack

Perché non utilizzare "Aggiungi riferimento al servizio"?
John Saunders

3

Hai provato a impostare il valore della proprietà DefaultConnectionLimit statica a livello di codice ?

Ecco una buona fonte di informazioni su quel vero mal di testa ... Utilizzo dei thread ASP.NET su IIS 7.5, IIS 7.0 e IIS 6.0 , con aggiornamenti per framework 4.0.


Immagino che non dovrebbe importare, ma lo proverò comunque.
Rob Sobers

Ecco come l'abbiamo risolto alcuni anni fa. Abbiamo avuto problemi di concorrenza e questo sembrava risolverlo. Net.ServicePointManager.DefaultConnectionLimit = 1000 è quello che abbiamo usato. È necessario impostarlo PRIMA di creare classi di connessione.
Brain2000

2

Vedere la sezione "Threading" di questa pagina: http://msdn.microsoft.com/en-us/library/ff647786.aspx , insieme alla sezione "Connections".

Hai provato ad aumentare l'attributo maxconnection dell'impostazione processModel?


Sì. Ma quell'articolo che hai citato sottolinea qualcosa di interessante che mai altri articoli sull'argomento hanno trascurato di menzionare: che l' maxconnectionattributo non si applica alle chiamate ai servizi web locali . In questo caso particolare, il servizio Web è locale, ma abbiamo lo stesso problema in un altro ambiente in cui il servizio non è locale.
Rob Sobers

@ RobSobers - Penso che il link sopra sia degno di una seconda occhiata. Controllare la parte su minLocalRequestFreeThreads: questo processo di lavoro utilizza questa impostazione per accodare le richieste dall'host locale (dove un'applicazione Web chiama un servizio Web sullo stesso server ) se il numero di thread disponibili nel pool di thread è inferiore a questo numero. Questa impostazione è simile a minFreeThreads, ma si applica solo alle richieste che utilizzano localhost .
Ahmad

@Ahmad Sì, ho impostato anche io minLocalRequestFreeThreads(vedi il mio machine.confignella domanda.
Rob Sobers,

0

Se non è definito nel servizio Web o nell'applicazione o nel server (apache o IIS) che ospita il consumabile del servizio Web, è possibile creare connessioni infinite fino al fallimento


0

mentre eseguo i test delle prestazioni, la misura che seguo è l'RPS, ovvero quante richieste al secondo può servire il server entro una latenza accettabile.

teoricamente un server può eseguire solo tante richieste contemporaneamente quanti sono i core su di esso.

Non sembra che il problema sia il modello di threading di ASP.net, dal momento che può potenzialmente servire migliaia di rps. Sembra che il problema potrebbe essere la tua applicazione. Stai usando primitive di sincronizzazione?

anche qual è la latenza sui tuoi servizi web, sono molto veloci nel rispondere (entro microsecondi), in caso contrario potresti prendere in considerazione le chiamate asincrone, quindi non finisci per bloccare

Se questo non produce qualcosa, potresti voler profilare il tuo codice usando Visual Studio o Redgate Profiler

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.