Qu'est-ce qui limite le nombre de connexions simultanées que mon application ASP.NET peut établir à un service Web?

90

J'ai une application ASP.NET 4.0 fonctionnant sur IIS 7.5 sur une machine Windows Server 2008 R2 Enterprise 64 bits avec des tas de RAM, CPU, disque, etc.

Avec chaque requête Web, l'application ASP.NET établit une connexion à un service Web de backend (via des sockets bruts), qui s'exécute sur la même machine.

Problème: il semble y avoir quelque chose qui limite le nombre de connexions simultanées au service Web principal. De manière suspecte, le nombre de connexions simultanées atteint 16.

J'ai trouvé cet article clé de Microsoft expliquant comment modifier les paramètres d'IIS pour accueillir les applications ASP.NET qui font de nombreuses demandes de service Web: http://support.microsoft.com/?id=821268#tocHeadRef

J'ai suivi les recommandations de l'article, mais toujours pas de chance. Le réglage qui est particulièrement intéressant est le maxconnectionréglage, que j'ai même grimpé à 999.

Des idées sur quoi d' autre pourrait être la limitation des connexions?

Remarque: lorsque je coupe IIS du mix et que les clients se connectent directement au service Web backend, il ouvrira avec plaisir autant de connexions que nécessaire, donc je suis sûr que le backend n'est pas le goulot d'étranglement. Ce doit être quelque chose dans IIS / ASP.NET-land.

Voici la section pertinente du machine.configqui, j'en suis sûr, est en cours de lecture par l'application (vérifiée avec 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
la source
@DanB a un bon point ici - comment mesurez-vous le nombre de connexions simultanées?
Jeremy McGee
@JeremyMcGee Je mesure le nombre de connexions simultanées en exécutant TCPView sur le serveur pour voir combien de connexions backend sont établies par les processus de travail IIS.
Rob Sobers
Les clients Web fonctionnent-ils sur des machines indépendantes ou sur la même machine? (Vérification qu'il n'y a pas de limitation côté client en cours.)
Jeremy McGee
3
@JeremyMcGee Machines séparées. 1 connexion client-serveur par machine. De plus, nous savons qu'il n'y a pas de limitation quelque part sur le réseau car lorsque nous touchons directement le backend (ce qui se produit également via HTTP), nous ne rencontrons pas le goulot d'étranglement.
Rob Sobers
1
Rob, avez-vous déjà trouvé une solution définitive à cela?
electronicKT

Réponses:

104

La plupart des réponses fournies ici concernent le nombre de demandes entrantes vers votre service Web backend, et non le nombre de demandes sortantes que vous pouvez effectuer depuis votre application ASP.net vers votre service backend.

Ce n'est pas votre webservice backend qui limite votre taux de requêtes ici, c'est le nombre de connexions ouvertes que votre application appelante est prête à établir vers le même point de terminaison (même URL).

Vous pouvez supprimer cette limitation en ajoutant la section de configuration suivante à votre fichier machine.config:

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

Vous pouvez bien sûr choisir un nombre plus raisonnable si vous le souhaitez, par exemple 50 ou 100 connexions simultanées. Mais ce qui précède l'ouvrira jusqu'à max. Vous pouvez également spécifier une adresse spécifique pour la règle de limite d'ouverture ci-dessus plutôt que le «*» qui indique toutes les adresses.

Documentation MSDN pour System.Net.connectionManagement

Une autre excellente ressource pour comprendre ConnectManagement dans .NET

J'espère que ceci résoudra votre problème!

EDIT: Oups, je vois que vous avez la gestion des connexions mentionnée dans votre code ci-dessus. Je laisserai mes informations ci-dessus car elles sont pertinentes pour les futurs demandeurs avec le même problème. Cependant, veuillez noter qu'il existe actuellement 4 fichiers machine.config différents sur la plupart des serveurs à jour!

Il existe .NET Framework v2 fonctionnant à la fois sous 32 bits et 64 bits, ainsi que .NET Framework v4 fonctionnant également sous 32 bits et 64 bits. En fonction des paramètres que vous avez choisis pour votre pool d'applications, vous pouvez utiliser l'un de ces 4 fichiers machine.config différents! Veuillez vérifier les 4 fichiers machine.config généralement situés ici:

  • 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
la source
Ouais, j'ai couvert cette base. Merci quand même, @BenSwayne! J'ai vérifié que j'avais modifié le bon machine.config(64 bits 4.0).
Rob Sobers
@RobSobers: Dans ce cas, je me méfierais un peu du code d'implémentation. Peut-être êtes-vous à court de threads ou quelque chose du genre? Pouvez-vous lancer votre code d'appel de service Web TcpClient dans une application console et voir si vous pouvez obtenir un meilleur taux de demande? Cela prouvera s'il s'agit d'une configuration spécifique à IIS ou d'une configuration .NET plus large ou de votre code.
BenSwayne
Cette ligne va-t-elle dans la machine cliente?
Uri Abramson
merci, vos paramètres se combinent avec processmodel twekaing de codeproject.com/Articles/133738/... fixe « ISAPI 'C: \ windows \ Microsoft.Net \ Framework \ v2.0.050727 \ aspnet_isapi.dll' lui - même signalé comme étant non pour la raison suivante : Problème de "blocage détecté"
Zakos
@BenSwayne est-ce que le même concept s'applique également aux connexions SMTP? Je conçois une application d'envoi d'e-mails en masse, cette propriété ConnectionManagement sera-t-elle également utile pour l'envoi d'e-mails en masse (en utilisant le multi-threading pour la fonction mail.send )?
vibs2006
7

Je me rends compte que la question est peut-être assez ancienne, mais vous dites que le backend fonctionne sur le même serveur. Cela signifie sur un port différent, probablement autre que le port par défaut 80.

J'ai lu que lorsque vous utilisez l 'élément de configuration "connectionManagement", vous devez spécifier le numéro de port s'il diffère du 80 par défaut.

LINK: le paramètre maxConnection peut ne pas fonctionner même autoConfig = false dans ASP.NET

Deuxièmement, si vous choisissez d'utiliser la configuration par défaut (adresse = "*") étendue avec votre propre valeur spécifique au backend, vous pouvez envisager de mettre la valeur spécifique en premier! Sinon, si une demande est faite, le * correspond en premier et la valeur par défaut de 2 connexions est prise. Tout comme lorsque vous utilisez la section dans web.config.

LINK: <remove> Élément pour la gestion de la connexion (Paramètres réseau)

J'espère que ça aide quelqu'un.

Sebastian Hek
la source
5

Serait-il possible que vous utilisiez une référence de service Web basée sur WCF? Par défaut, le ServiceThrottlingBehavior.MaxConcurrentCalls est 16.

Vous pouvez essayer de mettre à jour l' <serviceThrottling>élément de comportement de votre référence de service

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

(Notez que je recommande les paramètres ci-dessus.) Consultez MSDN pour plus d'informations sur la configuration d'un <behavior>élément approprié .

Ruben
la source
J'aurais aimé que ce soit le cas, mais nous ne le sommes pas. Le service consommé s'exécute dans Apache / Python / mod_wsgi sur une autre machine et, comme Rob l'a mentionné, ce n'est clairement pas le problème.
Benjamin Pollack
Les références de service sont sur le client. Comment votre client consomme-t-il le service Apache?
John Saunders
Comme John l'a dit: la limitation est définie sur le client qui utilise le service Web. Peut-être que l'expression «votre comportement de service» est un peu trompeuse. Est-ce que cela a plus de sens lorsqu'il est formulé comme «votre comportement de référence de service»?
Ruben
@john Il est consommé via un TcpClient(le service vend des blobs binaires personnalisés, pas WCF / SOAP ou similaire). Ces options de configuration semblent avoir un impact pur sur vous si vous utilisez ServiceHost, non TcpClient; est-ce que je manque quelque chose?
Benjamin Pollack
Pourquoi ne pas utiliser "Ajouter une référence de service"?
John Saunders
3

Avez-vous essayé de définir la valeur de la propriété statique DefaultConnectionLimit par programme?

Voici une bonne source d'informations sur ce véritable casse-tête ... Utilisation des threads ASP.NET sur IIS 7.5, IIS 7.0 et IIS 6.0 , avec des mises à jour pour le framework 4.0.

Simon Mourier
la source
J'imagine que cela ne devrait pas avoir d'importance, mais je vais quand même l'essayer.
Rob Sobers
C'est ainsi que nous l'avons résolu il y a quelques années. Nous avons eu des problèmes de concurrence et cela a semblé résoudre le problème. Net.ServicePointManager.DefaultConnectionLimit = 1000 est ce que nous avons utilisé. Vous devez le définir AVANT de créer des classes de connexion.
Brain2000
2

Consultez la section «Threading» de cette page: http://msdn.microsoft.com/en-us/library/ff647786.aspx , conjointement avec la section «Connexions».

Avez-vous essayé d'augmenter l'attribut maxconnection de votre paramètre processModel?

Matt Evans
la source
Oui j'ai. Mais cet article que vous avez cité souligne quelque chose d'intéressant que jamais un autre article sur le sujet a négligé de mentionner: l' maxconnectionattribut ne s'applique pas aux appels de service Web locaux . Dans ce cas particulier, le service Web est local, mais nous avons le même problème dans un autre environnement où le service n'est pas local.
Rob Sobers
@RobSobers - Je pense que le lien ci-dessus mérite un second regard. Vérifiez la partie about minLocalRequestFreeThreads- Ce processus de travail utilise ce paramètre pour mettre en file d'attente les demandes de l'hôte local (où une application Web appelle un service Web sur le même serveur ) si le nombre de threads disponibles dans le pool de threads tombe en dessous de ce nombre. Ce paramètre est similaire à minFreeThreads, mais il ne s'applique qu'aux demandes qui utilisent localhost .
Ahmad
@Ahmad Yup, je me suis mis minLocalRequestFreeThreadsaussi (voir mon machine.configdans la question.
Rob Sobers
0

S'il n'est pas défini dans le service Web ou l'application ou le serveur (apache ou IIS) qui héberge le consommable du service Web, vous pouvez créer des connexions infinies jusqu'à l'échec

Frank Tudor
la source
0

tout en faisant des tests de performances, la mesure que j'utilise est RPS, c'est-à-dire combien de requêtes par seconde le serveur peut-il servir dans une latence acceptable.

théoriquement, un serveur ne peut exécuter simultanément autant de requêtes que de cœurs.

Il ne semble pas que le problème soit le modèle de thread d'ASP.net, car il peut potentiellement servir des milliers de rps. Il semble que le problème soit lié à votre application. Utilisez-vous des primitives de synchronisation?

quelle est également la latence de vos services Web, sont-ils très rapides à répondre (en quelques microsecondes), sinon vous voudrez peut-être envisager les appels asynchrones, afin de ne pas bloquer

Si cela ne répond pas à quelque chose, vous voudrez peut-être profiler votre code à l'aide de Visual Studio ou Redgate Profiler

np-dur
la source