Qu’est ce qui détermine le nombre de connexions simultanées

Dans un environnement de servlet Java, quels sont les facteurs qui constituent le goulot d’étranglement pour le nombre d’utilisateurs simultanés.

  1. Nombre de connexions HTTP que le serveur peut autoriser par port
  2. Nombre de connexions HTTP que le serveur peut autoriser sur plusieurs ports (je peux avoir plusieurs profils WAS sur plusieurs ports HTTP)
  3. Nombre de servlets dans le pool
  4. Nombre de threads configurés pour WAS à utiliser pour desservir les connexions
  5. RAM disponible pour le serveur (existe-t-il une corrélation entre le nombre de threads de service en supposant une fuite de mémoire dans l’application)

Y a-t-il d’autres facteurs?

Modifié: pour ne pas avoir de logique applicative, supposez qu’un seul servlet imprime une ligne sur Log4j.

  • Mon serveur Tomcat peut-il gérer 6000 connexions HTTP simultanées? Pourquoi pas (descripteurs de fichier? Temps CPU par requête?)?
  • Puis-je avoir une taille de pool de threads égale à 5 000 (les threads inactifs coûtent-ils en coût CPU / RAM)?
  • Puis-je avoir une taille de pool de connexions Oracle de 500 connexions (les connexions inactives coûtent-elles en coût CPU / RAM)?

La quantité de déchets générée pour chaque connexion a-t-elle un impact? Par exemple, si pour chaque connexion HTTP, 20 Ko d’objects sont créés et laissés par Tomcat .., au moment où 2 500 demandes sont traitées, un segment de mémoire de 100 Mo sera utilisé, ce qui peut déclencher une pause de 300 ms dans le CPG.

Pouvons-nous dire quelque chose comme ceci: si Tomcat utilise 0,2 s de temps CPU pour traiter une requête HTTP unique, il sera alors capable de gérer environ 500 connexions http en une seconde. Donc, 6000 connexions auraient besoin de 5 secondes.

Question intéressante, si nous laissons de côté toutes les performances qui déterminent les atsortingbuts, cela se résume au volume de travail effectué dans la servlet ou au temps nécessaire pour disposer de la plus grande capacité d’E / S, de CPU et de mémoire. Maintenant, passons à la liste avec votre déclaration en tête; –

Nombre de connexions HTTP que le serveur peut autoriser par port

Il y a une limite pour les descripteurs de fichier, mais cela est à nouveau déclenché par le temps requirejs par une servlet pour compléter une requête ou par le temps écoulé entre la réception du premier octet de la requête et la fin de l’envoi de la réponse. Parce que si cela prend seulement 1 ms et que vous utilisez une connexion persistante et Netty, vous pouvez atteindre un très haut >> 6000.

Nombre de servlets dans le pool

Théoriquement >> 6000. Mais combien de threads traitent vos requêtes? Un pool de threads est-il en train de graver vos demandes? Donc, vous voulez augmenter le nombre de threads, mais combien, disons, 2000 threads simultanés. Est-ce que votre processeur se comporte mal avec le changement de contexte? Est-ce I / O lié? Si oui, il est judicieux de changer de contexte mais vous atteindrez ces limites du réseau car beaucoup de threads attendent sur les E / S du réseau, donc en fin de compte le temps que vous avez consacré à un travail.

DB

Si cela vous convient, qu’il vous soit permis de gérer les connexions, vous avez certainement besoin d’une surveillance rigoureuse ici. À présent, il ne s’agit que d’un autre facteur limitant et peut être considéré comme une simple autre entrée / sortie bloquante. Par définition, le temps de latence / débit est important et devient un goulot d’étranglement au moment où il devient plus gros que le plus petit travail.

Donc, enfin, vous devez décomposer les atsortingbuts suivants ou plus pour tous les servlets

  1. Est-ce lié au CPU? Si oui, combien de cycles cela prend-il ou peut-il être converti en toute sécurité en une unité de temps. Par exemple, 1ms pour le travail de calcul.
  2. Est-ce que I / O est lié, Si oui trouve également l’unité.
  3. et d’autres
  4. Une longue liste de ce que vous avez, par exemple CPU, mémoire, Go / s

Maintenant, vous savez combien de travail il rest à faire et tout ce que vous faites est divisé par ce que vous avez et continuez à vous adapter, de manière à rechercher l’optimum et à découvrir les autres atsortingbuts que vous n’avez pas pris en compte et à les prendre en compte.

Le plus gros goulot d’étranglement que j’ai connu est le temps qu’il faut pour traiter la demande. Plus vous pouvez traiter rapidement une demande, plus vous pouvez gérer de connexions.

C’est une question difficile à répondre car chaque application est différente. Pour comprendre cela avec une application que je supporte, j’ai créé un test unitaire qui génère de nombreux threads et je surveille l’utilisation de la mémoire dans VisualVM dans eclipse.

Vous pouvez voir comment votre consommation de mémoire change avec le nombre de threads utilisés. Et vous devriez pouvoir obtenir un vidage de thread et voir la quantité de mémoire utilisée par le thread. Vous pouvez extrapoler une moyenne pour comprendre la quantité de mémoire vive dont vous pourriez avoir besoin pour N nombre d’utilisateurs.

Le goulot d’étranglement sera une cible mobile, car vous optimiserez une zone jusqu’à ce que vous puissiez agrandir, puis une autre zone deviendra votre goulot d’étranglement.

Si le temps de réponse du servlet est un goulot d’étranglement, vous pouvez utiliser certaines mathématiques pour mettre en queue le nombre de demandes pouvant être mises en queue de manière optimale en fonction du temps de réponse moyen.

http://www4.ncsu.edu/~hp/SSME_QueueingTheory.pdf

J’espère que cela t’aides.

Mis à jour pour répondre à vos questions supplémentaires:

Mon serveur Tomcat peut-il gérer 6000 connexions HTTP simultanées? Pourquoi pas (descripteurs de fichier? Temps CPU par requête?)?

C’est possible mais probablement pas. En outre, vous devriez probablement append une couche Web devant le serveur d’application si vous envisagez de faire de gros volumes.
Supposons que vous ayez 6000 utilisateurs tout à fait sur votre application. Chaque demande envoyée par un utilisateur n’existe que sur le serveur pendant un moment [dans l’espoir], et le nombre de threads maximal n’a peut-être jamais dépassé 20.
Je vous recommande de mettre en place une surveillance pour comprendre le fonctionnement de votre application dans des cas d’utilisation réels. Consultez le site http://Hawt.io qui utilise Jolokia pour récupérer les mésortingques JMX via http.
Si vous êtes vraiment sérieux en analytique, je vous recommanderais d’utiliser quelque chose comme Graphite pour agréger vos mésortingques JMX. https://github.com/graphite-project/graphite-web
J’ai écrit un collecteur pour Jolokia afin qu’il envoie des mésortingques à Carbon / Graphite. Je peux peut-être ouvrir le code source avec l’approbation de ma direction. Fais moi savoir si tu es intéressé.

Puis-je avoir une taille de pool de threads égale à 5 000 (les threads inactifs coûtent-ils en coût CPU / RAM)?

Les threads inactifs ne sont pas inquiétants, bien que définir un pool de threads trop élevé pourrait permettre à votre serveur d’applications de recevoir trop de requêtes. Si cela se produit, vous risquez d’inonder votre firebase database avec des connexions qu’elle ne peut pas gérer ou votre allocation de mémoire risque de ne pas être suffisante pour gérer autant de requêtes. Cela pourrait entraîner une dégradation générale des performances de l’application.
Si la valeur est trop basse, votre serveur d’applications pourrait recommencer à mettre la demande en queue, ce qui entraînerait une dégradation des performances.
Il est généralement normal de faire la queue pendant les pics ou les périodes de volume élevé, mais vous ne voulez pas surcharger votre serveur d’applications. Consultez la théorie des files d’attente pour en savoir plus à ce sujet.
En outre, c’est là qu’un serveur Web situé devant le serveur d’applications pourrait vous aider. Si Apache sert votre contenu statique, seules les requêtes dynamics atteindront les serveurs d’applications dans la plupart des cas.
Le réglage est très spécifique à votre application. Je vous recommande de conserver les valeurs par défaut et d’optimiser votre code jusqu’à ce que vous puissiez collecter suffisamment de données pour savoir quel bouton doit être activé.

Puis-je avoir une taille de pool de connexions Oracle égale à 500 connexions (est-ce que les connexions inactives coûtent du CPU / RAM)?

Même situation que la taille du pool de threads d’application. Bien que la taille de votre pool pour DB soit beaucoup plus petite que le nombre de threads de l’application.
500 serait trop élevé pour la plupart des applications Web, sauf si vous avez un volume très élevé. Dans ce cas, vous aurez peut-être besoin d’un environnement de cluster de firebase database tel qu’Oracle RAC.
Si le pool est défini sur une valeur trop élevée et que vous commencez à utiliser de nombreuses connexions, votre matériel de firebase database ne sera pas en mesure de vous suivre et vous rencontrerez un problème de performances sur le serveur de firebase database.
Le temps nécessaire au retour d’une requête peut augmenter, entraînant une augmentation du temps de réponse de votre application. L’effet “log jam”.
Utilisez le profilage ou les mesures pour déterminer le nombre moyen de connexions de firebase database actives sous une utilisation normale, puis utilisez-le comme base pour déterminer le nombre maximal autorisé.

La quantité de déchets générée pour chaque connexion a-t-elle un impact? Par exemple, si pour chaque connexion HTTP, 20 Ko d’objects sont créés et laissés par Tomcat .., au moment où 2 500 demandes sont traitées, un segment de mémoire de 100 Mo sera utilisé, ce qui peut déclencher une pause de 300 ms dans le CPG.

Les chiffres seraient différents, mais oui. Rappelez-vous également que le GC complet est plus préoccupant. Les GC incrémentiels ne mettront pas votre application en pause. Découvrez “marquer et balayer simultanément” et “Les ordures en premier”.

Pouvons-nous dire quelque chose comme ceci: si Tomcat utilise 0,2 s de temps CPU pour traiter une requête HTTP unique, il sera alors capable de gérer environ 500 connexions http en une seconde. Donc, 6000 connexions auraient besoin de 5 secondes.

Ce n’est pas aussi facile que chaque demande arrive, il y en a aussi en cours de traitement et de traitement. Consultez la théorie des files d’attente pour mieux comprendre cela. http://www4.ncsu.edu/~hp/SSME_QueueingTheory.pdf

Il existe un autre goulot d’étranglement commun: la taille du pool de connexions à la firebase database. Mais j’ai une remarque supplémentaire à faire: lorsque vous épuisez le nombre de connexions HTTP autorisées, le nombre de threads autorisés à répondre aux demandes, vous ne refuserez que certaines demandes. Toutefois, lorsque vous épuisez la mémoire (trop de sessions contenant trop de données, par exemple), vous pouvez planter toute l’application.

La différence est que dans le cas d’une charge lourde pendant une courte période, lorsque la charge tombe plus tard:

  • dans le premier cas, l’application est active et peut servir les demandes normalement
  • dans le second cas, l’application est en panne et doit être redémarrée

MODIFIER :

J’ai oublié de me souvenir de cas d’utilisation réels. Le plus gros problème que j’ai jamais rencontré pour desservir de nombreuses connexions simultanées est la qualité des demandes de firebase database (en supposant que vous utilisiez une firebase database). Il n’y a pas d’impact direct puisqu’il n’y a pas de nombre maximum, mais vous pouvez facilement engloutir toutes les ressources du serveur de firebase database. Exemples courants de demandes de firebase database médiocres:

  • aucun index sur une table avec un grand nombre de lignes
  • une requête (sur une grande table) qui n’utilise aucun index
  • le syndrome n + 1: avec un ORM lorsque vous associez une relation un à plusieurs à une collection, pas avec impatience lorsque vous avez toujours besoin des données de la collection
  • le syndrome de chargement de firebase database complète : avec un ORM lorsque vous mappez toutes les relations avec impatience, toute requête unique aboutit à charger une grande quantité de données dépendantes.

Ce qui est pire avec ces problèmes, c’est qu’ils ne peuvent pas nuire aux tests lorsque la firebase database est récente, car il n’ya pas beaucoup de lignes, mais avec le temps et les nombres croissants, les performances chutent, donnant une application inutilisable à quelques utilisateurs.

Nombre de connexions HTTP que le serveur peut autoriser par port

Illimitée sauf par les ressources du kernel, par exemple les FD, les tampons de socket, etc.

Nombre de connexions HTTP que le serveur peut autoriser sur plusieurs ports (je peux avoir plusieurs profils WAS sur plusieurs ports HTTP)

Comme le nombre de connexions par port est illimité, cela est sans importance.

Nombre de servlets dans le pool

Peu importe sauf dans la mesure où cela augmente le taux de demandes entrantes.

Nombre de threads configurés pour que WAS utilise pour entretenir des connexions

Pertinent de manière indirecte, voir ci-dessous.

RAM disponible pour le serveur (existe-t-il une corrélation entre le nombre de threads de service en supposant une fuite de mémoire dans l’application)

Pertinent si le nombre de threads est inférieur au nombre de threads configuré mentionné ci-dessus.

La limitation fondamentale est le temps de service de demande. Le plus court, le meilleur. Plus la durée est longue, plus le fil est lié dans la requête, plus les files d’attente sont longues, … La théorie des files d’attente dicte que le «point idéal» ne représente pas plus de 70% d’utilisation du serveur. Au-delà, les temps d’attente augmentent rapidement avec l’utilisation croissante.

Donc, tout ce qui consortingbue à la durée du service de demande est significatif: par exemple, la taille du pool de threads, la taille du pool de connexion, les goulots d’étranglement de la simultanéité, …

Vous devez également considérer que le cas d’utilisation lui-même limite la quantité de simultanéité. Imaginez un environnement collaboratif où l’ordre des actions compte. Cela vous oblige à synchroniser les actions, même si vous auriez pu toutes les traiter en même temps.

En java land, cela pourrait être une chose simple que de partager une ressource unique qui utilise un access bloquant. (par exemple, des générateurs de nombres aléatoires partagés (pas par thread), des vecteurs partagés, des structures simultanées telles que ConcurrentHashMap, etc.).

Plus la synchronisation est importante, moins vous pourrez utiliser pleinement le matériel de votre serveur.

Ainsi, outre le fait de manquer de mémoire, de saturer le processeur ou d’atteindre la limite de récupération de place, cette synchronisation peut constituer un problème qui doit non seulement être résolu dans votre code, mais peut-être même vous obliger à assouplir certaines exigences du stream de travail de haut niveau.

Vu le point 6, vous pouvez utiliser ces outils pour voir si votre matériel constitue le goulet d’étranglement: En supposant que vous soyez sur Linux, vous pouvez utiliser VmStat pour afficher des statistiques sur votre utilisation de RAM, en top ou atop (en fonction de votre dissortingbution): voir les processus prendre un péage dans votre CPU et votre RAM, nload et iftop pour voir ce qui consum la bande passante réseau, et iotop pour voir ce qui est lu et écrit sur votre disque.