web-dev-qa-db-fra.com

Qu'est-ce qui pourrait provoquer un ralentissement global de Tomcat / JVM?

Je rencontre un problème étrange mais grave en exécutant plusieurs (environ 15) instances d'une Java applications Web EE-ish (Hibernate 4 + Spring + Quartz + JSF + Facelets + Richfaces) sur Tomcat 7/Java 7.

Le système fonctionne très bien, mais après une période de temps très variable, toutes les instances de l'application en même temps subissent soudainement une augmentation des temps de réponse. Fondamentalement, l'application fonctionne toujours, mais les temps de réponse sont environ trois fois plus élevés.

Il s'agit de deux diagrammes affichant le temps de réponse de deux certains flux de travail/actions courts (connexion, liste d'accès aux séminaires, ajax-rafraîchissement de cette liste, déconnexion; la ligne inférieure est juste le temps de demande pour le rafraîchissement ajax) de deux exemples d'instances de l'application:

Response times of context 1Resoinse times of context 2

Comme vous pouvez le voir, les deux instances de l'application "explosent" en même temps et restent lentes. Après avoir redémarré le serveur, tout redevient normal. Toutes les instances de l'application "explosent" simultanément.

Nous stockons les données de session dans une base de données et les utilisons pour le clustering. Nous avons vérifié la taille et le nombre de sessions et les deux sont plutôt faibles (ce qui signifie que sur d'autres serveurs avec d'autres applications, nous avons parfois des sessions plus grandes et plus nombreuses). L'autre Tomcat du cluster reste généralement rapide pendant encore quelques heures et après ce laps de temps aléatoire, il "meurt" également. Nous avons vérifié les tailles de tas avec jconsole et le tas principal reste entre 2,5 et 1 Go, le pool de connexions db est essentiellement plein de connexions gratuites, ainsi que les pools de threads. La taille maximale du tas est de 5 Go, il y a aussi beaucoup d'espace de perm perm disponible. La charge n'est pas particulièrement élevée; il y a environ 5% de charge sur le processeur principal. Le serveur ne change pas. Ce n'est pas non plus un problème matériel car nous avons également déployé les applications sur un VM où les problèmes restent les mêmes.

Je ne sais plus où chercher, je suis à court d'idées. Quelqu'un at-il une idée où chercher?

2013-02-21 Mise à jour: nouvelles données!

J'ai ajouté deux autres traces de synchronisation à l'application. Quant à la mesure: le système de surveillance appelle une servlet qui effectue deux tâches, mesure le temps d'exécution de chacune sur le serveur et écrit le temps pris en réponse. Ces valeurs sont enregistrées par le système de surveillance.

J'ai plusieurs faits nouveaux intéressants: un redéploiement à chaud de l'application fait que cette seule instance sur le Tomcat actuel devient folle. Cela semble également affecter les performances de calcul du processeur brut (voir ci-dessous). Cette explosion de contexte individuel est différente de l'explosion de contexte global qui se produit de manière aléatoire.

Maintenant pour quelques données:

Diagram 3Diagram 4

D'abord les lignes individuelles:

  1. Le bleu clair est le temps d'exécution total d'un petit workflow (détails voir ci-dessus), mesuré sur le client
  2. Le rouge fait "partie" du bleu clair et représente le temps nécessaire pour effectuer une étape spéciale de ce flux de travail, mesurée sur le client
  3. Le bleu foncé est mesuré dans l'application et consiste à lire une liste d'entités de la base de données via Hibernate et à parcourir cette liste, à récupérer des collections paresseuses et des entités paresseuses.
  4. Le vert est une petite référence de CPU utilisant des opérations en virgule flottante et en nombre entier. Pour autant que je ne vois aucune allocation d'objet, donc pas de déchets.

Maintenant, pour les différentes étapes de l'explosion: j'ai marqué chaque image avec trois points noirs. La première est une "petite" explosion dans plus ou moins une seule instance d'application - dans Inst1, elle saute (surtout visible sur la ligne rouge), tandis que Inst2 ci-dessous reste plus ou moins calme.

Après cette petite explosion, le "big bang" se produit et toutes les instances d'application sur ce Tomcat explosent (2e point). Notez que cette explosion affecte toutes les opérations de haut niveau (traitement des demandes, accès aux bases de données), mais pas la référence du processeur. Il reste bas dans les deux systèmes.

Après cela, j'ai redéployé à chaud Inst1 en touchant le fichier context.xml. Comme je l'ai dit plus tôt, cette instance passe d'explosé à complètement dévasté maintenant (la ligne bleu clair est hors du graphique - elle est à environ 18 secondes). Notez comment a) ce redéploiement n'affecte pas du tout Inst2 et b) comment l'accès brut à la base de données d'Inst1 n'est pas non plus affecté - mais comment le CPU soudainement semble être devenu plus lent! . C'est fou, dis-je.

Mise à jour de la mise à jour L'écouteur de prévention des fuites de Tomcat ne se plaint pas de ThreadLocals ou Threads périmés lorsque l'application n'est pas déployée. Il semble évidemment qu'il y ait un problème de nettoyage (ce qui, je suppose, n'est pas directement lié au Big Bang), mais Tomcat n'a pas d'indice pour moi.

2013-02-25 Mise à jour: environnement d'application et calendrier Quartz

L'environnement d'application n'est pas très sophistiqué. Hormis les composants réseau (je n'en sais pas assez), il y a essentiellement un serveur d'applications (Linux) et deux serveurs de bases de données (MySQL 5 et MSSQL 2008). La charge principale est sur le serveur MSSQL, l'autre sert simplement de lieu de stockage des sessions.

Le serveur d'applications exécute un Apache comme équilibreur de charge entre deux Tomcats. Nous avons donc deux machines virtuelles Java exécutées sur le même matériel (deux instances Tomcat ). Nous utilisons cette configuration non pas pour équilibrer réellement la charge car le serveur d'applications est capable d'exécuter l'application très bien (ce qu'il faisait depuis des années maintenant) mais pour permettre de petites mises à jour d'applications sans temps d'arrêt. L'application Web en question est déployée dans des contextes distincts pour différents clients, environ 15 contextes par Tomcat. (Il me semble que j'ai mélangé des "instances" et des "contextes" dans mon message - ici au bureau, ils sont souvent utilisés comme synonymes et nous savons généralement comme par magie de quoi parle le collègue. Mon mauvais, je suis vraiment désolé.)

Pour clarifier la situation avec une meilleure formulation: les diagrammes que j'ai postés montrent les temps de réponse de deux contextes différents de la même application sur la même JVM. Le Big Bang affecte tous les contextes sur une JVM mais ne se produit pas sur l'autre (l'ordre dans lequel les Tomcats explosent est aléatoire entre les deux). Après le redéploiement à chaud, un contexte sur une instance de Tomcat devient fou (avec tous les effets secondaires amusants, comme un processeur apparemment plus lent pour ce contexte).

La charge globale sur le système est plutôt faible. Il s'agit d'un logiciel interne au cœur de métier avec environ 30 utilisateurs actifs simultanément. Les demandes spécifiques aux applications (contacts avec le serveur) sont actuellement à environ 130 par minute. Le nombre de demandes uniques est faible, mais les demandes elles-mêmes nécessitent souvent plusieurs centaines de sélections dans la base de données, elles sont donc plutôt coûteuses. Mais généralement, tout est parfaitement acceptable. L'application ne crée pas non plus de caches infinis volumineux - certaines données de recherche sont mises en cache, mais uniquement pendant une courte période.

Ci-dessus, j'ai écrit que les serveurs étaient capables d'exécuter l'application très bien pendant plusieurs années. Je sais que la meilleure façon de trouver le problème serait de savoir exactement quand les choses ont mal tourné pour la première fois et de voir ce qui a changé dans ce laps de temps (dans l'application elle-même, les bibliothèques ou l'infrastructure associées), mais le problème est que nous ne savons pas quand les problèmes sont survenus pour la première fois. Appelons simplement cette surveillance d'application sous-optimale (dans le sens d'absence) ...: - /

Nous avons exclu certains aspects, mais l'application a été mise à jour plusieurs fois au cours des derniers mois et nous avons donc par exemple ne peut pas simplement déployer une ancienne version. La plus grande mise à jour qui n'a pas changé de fonctionnalité a été le passage de JSP à Facelets. Mais encore, "quelque chose" doit être la cause de tous les problèmes, mais je n'ai aucune idée pourquoi Facelets par exemple devrait influencer les temps de requête DB purs.

Quartz

Quant à l'horaire Quartz: il y a un total de 8 emplois. La plupart d'entre eux ne s'exécutent qu'une fois par jour et ont à voir avec la synchronisation des données à grand volume (absolument pas "grande" comme dans "big data large"; c'est juste plus que ce que l'utilisateur moyen voit dans son travail quotidien habituel). Cependant, ces travaux s'exécutent bien sûr la nuit et les problèmes surviennent pendant la journée. J'omets ici une liste de travail détaillée (si cela est bénéfique, je peux bien sûr fournir plus de détails). Le code source des travaux n'a pas été modifié au cours des derniers mois. J'ai déjà vérifié si les explosions concordaient avec les emplois - pourtant les résultats ne sont pas concluants au mieux. Je dirais en fait qu'ils ne s'alignent pas, mais comme il y a plusieurs tâches qui s'exécutent chaque minute, je ne peux pas encore l'exclure. Les tâches acutales qui s'exécutent toutes les minutes sont assez légères à mon avis, elles vérifient généralement si les données sont disponibles (dans différentes sources, base de données, systèmes externes, compte de messagerie) et si c'est le cas, écrivez-les dans la base de données ou poussez-les vers un autre système .

Cependant, j'active actuellement la journalisation de l'exécution individuelle des travaux afin que je puisse voir exactement les horodatages de début et de fin de chaque exécution de travail. Peut-être que cela donne plus d'informations.

2013-02-28 Mise à jour: Phases et calendrier JSF

J'ai ajouté manuellement un écouteur de phase JSF à l'application. J'ai exécuté un exemple d'appel (le rafraîchissement ajax) et voici ce que j'ai (à gauche: instance Tomcat en cours d'exécution normale, à droite: instance Tomcat après Big Bang - les chiffres ont été tirés presque simultanément des deux Tomcats et sont en millisecondes):

  1. RESTORE_VIEW: 17 contre 46
  2. APPLY_REQUEST_VALUES: 170 contre 486
  3. PROCESS_VALIDATIONS: 78 contre 321
  4. UPDATE_MODEL_VALUES: 75 contre 307
  5. RENDER_RESPONSE: 1059 contre 4162

Le rafraîchissement ajax lui-même appartient à un formulaire de recherche et à son résultat de recherche. Il y a aussi un autre délai entre le filtre de demande le plus éloigné de l'application et le flux Web commence son travail: il y a un FlowExecutionListenerAdapter qui mesure le temps pris dans certaines phases du flux Web. Cet auditeur rapporte 1405 ms pour la "demande soumise" (qui est pour autant que je connaisse le premier événement de flux Web) sur un total de 1632 ms pour la demande complète sur un Tomcat non explosé, donc j'estime environ 200 ms de surcharge.
. de la demande de flux Web soumise.
Sous mon filtre de mesure, la chaîne de filtres contient un org.ajax4jsf.webapp.BaseFilter, la servlet Spring est appelée.

2013-06-05 Update: tout ce qui s'est passé ces dernières semaines

Une petite mise à jour plutôt tardive ... les performances de l'application sont toujours nulles après un certain temps et le comportement reste erratique. Le profilage n'a pas encore beaucoup aidé, il a juste généré une énorme quantité de données difficiles à disséquer. (Essayez de fouiller dans les données de performances ou de profiler un système de production ... soupir) Nous avons effectué plusieurs tests (arracher certaines parties du logiciel, annuler le déploiement d'autres applications, etc.) et avons en fait apporté quelques améliorations qui affectent l'ensemble de l'application. Le mode de vidage par défaut de notre EntityManager est AUTO et pendant le rendu de la vue, de nombreuses récupérations et sélections sont émises, incluant toujours la vérification si le vidage est nécessaire.
Nous avons donc créé un écouteur de phase JSF qui définit le mode de vidage sur COMMIT pendant RENDER_RESPONSE. Cela a amélioré considérablement les performances globales et semble avoir quelque peu atténué les problèmes.

Pourtant, notre surveillance des applications continue de produire des résultats et des performances complètement fous dans certains contextes sur certaines instances de Tomcat. Comme une action qui devrait se terminer en moins d'une seconde (et qui le fait réellement après le déploiement) et qui prend maintenant plus de quatre secondes. (Ces chiffres sont pris en charge par la synchronisation manuelle dans les navigateurs, donc ce n'est pas la surveillance qui cause les problèmes).

Voir l'image suivante par exemple:
Diagram

Ce diagramme montre deux instances Tomcat exécutant le même contexte (c'est-à-dire la même base de données, la même configuration, le même bocal). Encore une fois, la ligne bleue représente le temps nécessaire aux opérations de lecture de base de données pure (récupérer une liste d'entités, les parcourir, rechercher paresseusement les collections et les données associées). La ligne turquoise et rouge est mesurée en affichant plusieurs vues et en effectuant un rafraîchissement ajax, respectivement. Les données rendues par deux des demandes en turquoise et en rouge sont essentiellement les mêmes que celles demandées pour la ligne bleue.

Maintenant, vers 0700 sur l'instance 1 (à droite), il y a cette énorme augmentation du temps de base de données pur qui semble également affecter les temps de réponse de rendu réels, mais uniquement sur Tomcat 1. Tomcat 0 n'est pratiquement pas affecté par cela, donc il ne peut pas être causé par la base de données serveur ou réseau avec les deux tomcats fonctionnant sur le même matériel physique. Ce doit être un problème logiciel dans le domaine Java.

Lors de mes derniers tests, j'ai découvert quelque chose d'intéressant: toutes les réponses contiennent l'en-tête "X-Powered-By: JSF/1.2, JSF/1.2". Certains (les réponses de redirection produites par WebFlow) contiennent même trois fois "JSF/1.2".
J'ai retracé les parties de code qui définissent ces en-têtes et la première fois que cet en-tête est défini, il est provoqué par cette pile:

... at org.ajax4jsf.webapp.FilterServletResponseWrapper.addHeader(FilterServletResponseWrapper.Java:384)
at com.Sun.faces.context.ExternalContextImpl.<init>(ExternalContextImpl.Java:131)
at com.Sun.faces.context.FacesContextFactoryImpl.getFacesContext(FacesContextFactoryImpl.Java:108)
at org.springframework.faces.webflow.FlowFacesContext.newInstance(FlowFacesContext.Java:81)
at org.springframework.faces.webflow.FlowFacesContextLifecycleListener.requestSubmitted(FlowFacesContextLifecycleListener.Java:37)
at org.springframework.webflow.engine.impl.FlowExecutionListeners.fireRequestSubmitted(FlowExecutionListeners.Java:89)
at org.springframework.webflow.engine.impl.FlowExecutionImpl.resume(FlowExecutionImpl.Java:255)
at org.springframework.webflow.executor.FlowExecutorImpl.resumeExecution(FlowExecutorImpl.Java:169)
at org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.Java:183)
at org.springframework.webflow.mvc.servlet.FlowController.handleRequest(FlowController.Java:174)
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.Java:48)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.Java:925)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.Java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.Java:920)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.Java:827)
at javax.servlet.http.HttpServlet.service(HttpServlet.Java:641)
... several thousands ;) more

La deuxième fois que cet en-tête est défini par

at org.ajax4jsf.webapp.FilterServletResponseWrapper.addHeader(FilterServletResponseWrapper.Java:384)   
at com.Sun.faces.context.ExternalContextImpl.<init>(ExternalContextImpl.Java:131)   
at com.Sun.faces.context.FacesContextFactoryImpl.getFacesContext(FacesContextFactoryImpl.Java:108)   
at org.springframework.faces.webflow.FacesContextHelper.getFacesContext(FacesContextHelper.Java:46)   
at org.springframework.faces.richfaces.RichFacesAjaxHandler.isAjaxRequestInternal(RichFacesAjaxHandler.Java:55)   
at org.springframework.js.ajax.AbstractAjaxHandler.isAjaxRequest(AbstractAjaxHandler.Java:19)   
at org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.createServletExternalContext(FlowHandlerAdapter.Java:216)   
at org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.Java:182)   
at org.springframework.webflow.mvc.servlet.FlowController.handleRequest(FlowController.Java:174)   
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.Java:48)   
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.Java:925)   
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.Java:856)   
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.Java:920)   
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.Java:827)   
at javax.servlet.http.HttpServlet.service(HttpServlet.Java:641)

Je ne sais pas si cela pourrait indiquer un problème, mais je ne l'ai pas remarqué avec d'autres applications qui s'exécutent sur l'un de nos serveurs, donc cela pourrait aussi bien fournir quelques conseils. Je n'ai vraiment aucune idée de ce que fait ce code cadre (certes, je n'y ai pas encore plongé) ... peut-être que quelqu'un a une idée? Ou suis-je dans une impasse?

Appendice

Mon code de référence CPU consiste en une boucle qui calcule Math.tan et utilise la valeur de résultat pour modifier certains champs sur l'instance de servlet (pas de volatile/synchronisé là-bas), et effectue ensuite plusieurs calculs de nombres entiers bruts. Ce n'est pas très sophistiqué, je sais, mais bon ... il semble montrer quelque chose dans les graphiques, mais je ne suis pas sûr de ce qu'il montre. Je fais les mises à jour sur le terrain pour empêcher HotSpot d'optimiser tout mon précieux code;)

    long time2 = System.nanoTime();
    for (int i = 0; i < 5000000; i++) {
        double tan = Math.tan(i);
        if (tan < 0) {
            this.l1++;
        } else {
            this.l2++;
        }
    }

    for (int i = 1; i < 7500; i++) {
        int n = i;
        while (n != 1) {
            this.steps++;
            if (n % 2 == 0) {
                n /= 2;
            } else {
                n = n * 3 + 1;
            }
        }
    }
    // This execution time is written to the client.
    time2 = System.nanoTime() - time2;
41
chammp

Tout d'abord, permettez-moi de dire que vous avez fait un excellent travail en saisissant en détail - faits sur le problème; J'aime vraiment la façon dont vous expliquez clairement ce que vous savez et ce que vous spéculez - cela aide vraiment.

EDIT 1 Édition massive après la mise à jour du contexte par rapport à l'instance

Nous pouvons exclure:

  • GC (cela affecterait le thread de service de référence du CPU et augmenterait le CPU principal)
  • Tâches Quartz (qui affecteraient à la fois les Tomcats ou le benchmark CPU)
  • La base de données (qui affecterait les deux Tomcats)
  • Tempêtes de paquets réseau et similaires (qui affecteraient les deux Tomcats)

Je pense que vous souffrez d'une augmentation de la latence quelque part dans votre machine virtuelle Java. La latence est l'endroit où un thread attend (de manière synchrone) une réponse de quelque part - cela augmente le temps de réponse de votre servlet mais sans frais pour le CPU. Les latences typiques sont causées par:

  • Appels réseau, y compris
    • JDBC
    • EJB ou RMI
    • JNDI
    • DNS
    • Partages de fichiers
  • Lecture et écriture sur disque
  • Filetage
    • Lecture (et parfois écriture) dans les files d'attente
    • synchronized méthode ou bloc
    • futures
    • Thread.join()
    • Object.wait()
    • Thread.sleep()

Confirmation que le problème est la latence

Je suggère d'utiliser un outil de profilage commercial. J'aime [JProfiler] ( http://www.ej-technologies.com/products/jprofiler/overview.html , version d'essai de 15 jours disponible) mais YourKit est également recommandé par la communauté StackOverflow. Dans cette discussion, j'utiliserai la terminologie JProfiler.

Attachez-vous au processus Tomcat pendant qu'il fonctionne bien et obtenez une idée de son apparence dans des conditions normales. En particulier, utilisez les sondes JDBC, JPA, JNDI, JMS, servlet, socket et fichier de haut niveau pour voir combien de temps les opérations JDBC, JMS, etc. prennent ( screencast . Exécutez-le à nouveau lorsque le serveur présente des problèmes et compare. J'espère que vous verrez ce qui a précisément été ralenti. Dans la capture d'écran du produit ci-dessous, vous pouvez voir les synchronisations SQL à l'aide de la sonde JPA:

JPA hotspots
(source: ej-technologies.com )

Cependant, il est possible que les sondes n'aient pas isolé le problème - par exemple, il pourrait s'agir d'un problème de thread. Accédez à la vue Threads de l'application; cela affiche un diagramme en cours des états de chaque thread, et s'il s'exécute sur le CPU, dans une Object.wait(), attend pour entrer un bloc synchronized ou attend sur le réseau I/O. Lorsque vous savez quel thread ou quels threads présentent le problème, accédez aux vues CPU, sélectionnez le thread et utilisez le sélecteur d'état des threads pour explorer immédiatement les méthodes coûteuses et leurs piles d'appels. [Screencast] (( screencast ). Vous serez en mesure d'explorer votre code d'application.

Il s'agit d'une pile d'appels pour le temps exécutable:

enter image description here

Et c'est le même, mais montrant la latence du réseau:

enter image description here

Lorsque vous savez que quoi bloque, nous espérons que le chemin vers la résolution sera plus clair.

9
Andrew Alcock

Nous avons eu le même problème, fonctionnant sur Java 1.7.0_u101 (une des versions prises en charge par Oracle, puisque le dernier JDK/JRE 7 public est 1.7.0_u79), fonctionnant sur le garbage collector G1. Je ne peux pas dire si le problème apparaît dans d'autres versions Java 7 ou avec d'autres GC.

Notre processus était Tomcat exécutant Liferay Portal (je crois que la version exacte de Liferay n'a aucun intérêt ici).

C'est le comportement que nous avons observé: en utilisant un -Xmx de 5 Go, la taille du pool de cache de code initial juste après le démarrage variait à environ 40 Mo. Après un certain temps, il est tombé à environ 30 Mo (ce qui est un peu normal, car il y a beaucoup de code en cours d'exécution au démarrage qui ne sera plus jamais exécuté, il devrait donc être expulsé du cache après un certain temps). Nous avons observé qu'il y avait une certaine activité JIT, donc le JIT a effectivement rempli le cache (par rapport aux tailles que je mentionne plus tard, il semble que la petite taille du cache par rapport à la taille globale du tas impose des exigences strictes au JIT, ce qui rend le ces derniers expulsent la cache plutôt nerveusement). Cependant, après un certain temps, plus aucune compilation n'a eu lieu et la JVM est devenue extrêmement lente. Nous devions tuer nos Tomcats de temps en temps pour retrouver des performances adéquates, et au fur et à mesure que nous ajoutions du code à notre portail, le problème empirait (depuis que le cache de code était saturé plus rapidement, je suppose).

Il semble qu'il y ait plusieurs bogues dans JDK 7 JVM qui l'empêchent de redémarrer le JIT (regardez ce billet de blog: https://blogs.Oracle.com/poonam/entry/why_do_i_get_message ), même dans JDK 7, après une vidange d'urgence (le blog mentionne Java bugs 8006952, 8012547, 8020151 et 8029091).

C'est pourquoi l'augmentation manuelle du cache de code à un niveau où il est peu probable qu'un vidage d'urgence se produise "corrige" le problème (je suppose que c'est le cas avec JDK 7).

Dans notre cas, au lieu d'essayer d'ajuster la taille du pool de cache de code, nous avons choisi de mettre à niveau vers Java 8. Cela semble avoir résolu le problème. De plus, le cache de code semble maintenant être assez plus grande (la taille de démarrage atteint environ 200 Mo et la taille de croisière atteint environ 160 Mo). Comme il est prévu, après un certain temps d'inactivité, la taille du pool de cache diminue, pour se relever si un utilisateur (ou robot, ou autre) navigue sur notre site , provoquant l'exécution de plus de code.

J'espère que vous trouverez les données ci-dessus utiles.

J'ai oublié de dire: j'ai trouvé l'exposition, les données à l'appui, la logique de déduction et la conclusion de ce message très, très utiles. Merci vraiment!

2
avarvit

Avez-vous vérifié les heures JVM GC? Certains algorithmes GC peuvent "suspendre" les threads d'application et augmenter le temps de réponse.

Vous pouvez utiliser l'utilitaire jstat pour surveiller les statistiques de récupération de place:

jstat -gcutil <pid of Tomcat> 1000 100

La commande ci-dessus imprimerait les statistiques du GC toutes les 1 secondes 100 fois. Regardez les colonnes FGC/YGC, si le nombre continue d'augmenter, il y a un problème avec vos options de GC.

Vous souhaiterez peut-être basculer vers CMS GC si vous souhaitez réduire le temps de réponse:

-XX:+UseConcMarkSweepGC

Vous pouvez vérifier plus d'options GC ici .

1
ericson

Que se passe-t-il après que votre application fonctionne lentement pendant un certain temps, est-ce qu'elle redevient performante? Si c'est le cas, je vérifierais s'il y a une activité qui n'est pas liée à votre application en cours à ce moment. Quelque chose comme une analyse antivirus ou une sauvegarde système/db.

Sinon, je suggère de l'exécuter avec un profileur (JProfiler, yourkit, etc.), ces outils peuvent vous diriger très facilement vers vos hotspots.

1
Doron Manor

Quelqu'un at-il une idée où chercher?

  1. Le problème peut être hors de Tomcat/JVM - avez-vous un travail par lots qui entre en jeu et met l'accent sur les ressources partagées comme une base de données commune?

  2. Prenez un vidage de thread et voyez ce que font les processus Java lorsque le temps de réponse de l'application explose?

  3. Si vous utilisez Linux, utilisez un outil comme strace et vérifiez ce que fait le processus Java.

1
Bimalesh Jha

Vous utilisez Quartz, qui gère les processus chronométrés, et cela semble se produire à des moments particuliers.

Publiez votre calendrier Quartz et faites-nous savoir si cela correspond, et si oui, vous pouvez déterminer quel processus de demande interne pourrait démarrer pour consommer vos ressources.

Alternativement, il est possible qu'une partie de votre code d'application ait finalement été activée et décide de charger des données dans le cache mémoire. Vous utilisez Hibernate; vérifiez les appels vers votre base de données et voyez si quelque chose coïncide.

0
JoshDM