web-dev-qa-db-fra.com

Délai d'expiration de la demande Tomcat

Dans mon application Web, certaines demandes durent plus de 20 secondes. Mais dans certaines situations, le code peut entraîner une boucle infinie ou quelque chose de similaire qui ralentit le serveur.

Je veux mettre un délai de requête de 60 secondes côté serveur. Est-ce que cela est implémenté dans Tomcat?

Merci, Horatiu

41
Horatiu Jeflea

Avec Tomcat 7, vous pouvez ajouter le StuckThreadDetectionValve qui vous permettra d’identifier les threads "bloqués". Vous pouvez configurer l'élément Valve dans l'élément Context des applications pour lesquelles vous souhaitez effectuer la détection:

<Context ...>
  ...
  <Valve 
    className="org.Apache.catalina.valves.StuckThreadDetectionValve"
    threshold="60" />
  ...
</Context>

Cela écrirait une entrée WARN dans le journal Tomcat pour tout thread prenant plus de 60 secondes, ce qui vous permettrait d'identifier les applications et de les interdire, car elles sont défectueuses.

Sur la base du code source , vous pourrez peut-être écrire votre propre valve qui tente d’arrêter le thread, mais cela aurait des répercussions sur le pool de threads et il y a aucun moyen fiable d'arrêter un fil dans Java sans la coopération de ce fil ...

44
beny23

Si vous essayez d'empêcher une demande de s'exécuter trop longtemps, la définition d'un délai d'attente dans Tomcat ne vous aidera pas. Comme Chris l'a dit, vous pouvez définir la valeur du délai d'expiration global pour Tomcat. Mais, à partir de The Apache Tomcat Connector - Délais de procédure générique , reportez-vous à la section Délai de réponse:

JK peut également utiliser un délai d'expiration pour les réponses à la demande. Ce délai ne mesure pas le temps de traitement complet de la réponse. Au lieu de cela, il contrôle combien de temps entre les paquets de réponse consécutifs est autorisé.

Dans la plupart des cas, c'est ce que l'on veut réellement. Considérez par exemple les téléchargements à long terme. Vous ne pourrez pas définir de délai de réponse global effectif, car les téléchargements pourraient durer plusieurs minutes. Cependant, la plupart des applications ont un temps de traitement limité avant de commencer à renvoyer la réponse. Pour ces applications, vous pouvez définir un délai de réponse explicite. Les applications qui ne s'harmonisent pas avec les délais de réponse sont les applications de type batch, les entrepôts de données et les applications de génération de rapports qui doivent respecter des temps de traitement longs.

Si JK interrompt l'attente d'une réponse, car un délai de réponse est déclenché, il n'y a aucun moyen d'arrêter le traitement sur le backend. Bien que vous libériez des ressources de traitement sur votre serveur Web, la requête continuera à s'exécuter sur le serveur - sans aucun moyen de renvoyer un résultat une fois le délai de réponse écoulé.

Tomcat détectera donc que le servlet n'a pas répondu dans le délai imparti et renverra une réponse à l'utilisateur, mais n'arrêtera pas l'exécution du thread. Je ne pense pas que vous puissiez réaliser ce que vous voulez faire.

22
Matthew Farwell

Vous pouvez définir le délai d'expiration par défaut dans le fichier server.xml.

<Connector URIEncoding="UTF-8" 
    acceptCount="100" 
    connectionTimeout="20000" 
    disableUploadTimeout="true" 
    enableLookups="false" 
    maxHttpHeaderSize="8192" 
    maxSpareThreads="75" 
    maxThreads="150" 
    minSpareThreads="25" 
    port="7777" 
    redirectPort="8443"/>
11
Chris

Cet article traite de la définition des délais d'expiration au niveau du serveur. http://www.coderanch.com/t/364207/Servlets/Java/Servlet-Timeout-two-ways

Qu'est-ce qui fait que l'application passe en boucle infinie? Si vous ouvrez des connexions à d'autres ressources, vous pouvez définir des délais d'expiration pour ces connexions et envoyer la réponse appropriée lorsque ce délai est dépassé.

1
thcricketfan

Si vous n'aimez aucune des solutions publiées ci-dessus comme moi, vous pouvez simplement implémenter vous-même une minuterie et arrêter l'exécution de la demande en lançant une exception d'exécution. Quelque chose comme ci-dessous:

                  try 
                 {
                     timer.schedule(new TimerTask() {
                       @Override
                       public void run() {
                         timer.cancel();
                       }
                     }, /* specify time of the requst */ 1000);
                 }
                 catch(Exception e)
                 {
                   throw new RuntimeException("the request is taking longer than usual");
                 }

ou utilisez de préférence le Java guava timeLimiter ici

0
george