Nous avons une API qui est implémentée à l'aide de ServiceStack qui est hébergé dans IIS. En effectuant des tests de charge de l'API, nous avons découvert que les temps de réponse sont bons mais qu'ils se détériorent rapidement dès que nous atteignons environ 3 500 utilisateurs simultanés par serveur. Nous avons deux serveurs et lorsqu'ils atteignent 7 000 utilisateurs, les temps de réponse moyens sont inférieurs à 500 ms pour tous les points de terminaison. Les boîtes sont derrière un équilibreur de charge, nous avons donc 3 500 concurrents par serveur. Cependant, dès que nous augmentons le nombre total d'utilisateurs simultanés, nous constatons une augmentation significative des temps de réponse. L'augmentation du nombre d'utilisateurs simultanés à 5 000 par serveur nous donne un temps de réponse moyen par point de terminaison d'environ 7 secondes.
La mémoire et le processeur sur les serveurs sont assez faibles, à la fois pendant que les temps de réponse sont bons et après s'être détériorés. Au sommet avec 10 000 utilisateurs simultanés, le processeur est en moyenne un peu moins de 50% et la RAM se situe autour de 3-4 Go sur 16. Cela nous laisse penser que nous atteignons une sorte de limite quelque part. La capture d'écran ci-dessous montre certains compteurs clés de perfmon lors d'un test de charge avec un total de 10 000 utilisateurs simultanés. Le compteur en surbrillance est requêtes / seconde. À droite de la capture d'écran, vous pouvez voir le graphique des requêtes par seconde devenir vraiment erratique. Il s'agit du principal indicateur de temps de réponse lents. Dès que nous voyons ce modèle, nous remarquons des temps de réponse lents dans le test de charge.
Comment résoudre ce problème de performances? Nous essayons d'identifier s'il s'agit d'un problème de codage ou d'un problème de configuration. Existe-t-il des paramètres dans web.config ou IIS qui pourraient expliquer ce comportement? Le pool d'applications exécute .NET v4.0 et la version IIS est 7.5. La seule modification que nous avons apportée par rapport aux paramètres par défaut est de mettre à jour la valeur de longueur de file d'attente du pool d'applications de 1 000 à 5 000. Nous avons également ajouté les paramètres de configuration suivants au fichier Aspnet.config:
<system.web>
<applicationPool
maxConcurrentRequestsPerCPU="5000"
maxConcurrentThreadsPerCPU="0"
requestQueueLimit="5000" />
</system.web>
Plus de détails:
Le but de l'API est de combiner les données de diverses sources externes et de les renvoyer en JSON. Il utilise actuellement une implémentation de cache InMemory pour mettre en cache les appels externes individuels au niveau de la couche de données. La première demande à une ressource récupérera toutes les données requises et toute demande ultérieure pour la même ressource obtiendra les résultats du cache. Nous avons un «exécuteur de cache» qui est implémenté comme un processus d'arrière-plan qui met à jour les informations dans le cache à certains intervalles définis. Nous avons ajouté un verrouillage autour du code qui récupère les données des ressources externes. Nous avons également implémenté les services pour extraire les données des sources externes de manière asynchrone afin que le point de terminaison ne soit aussi lent que l'appel externe le plus lent (sauf si nous avons des données dans le cache bien sûr). Cela se fait à l'aide de la classe System.Threading.Tasks.Task.Pourrions-nous atteindre une limitation en termes de nombre de threads disponibles pour le processus?