Blocage des fils de discussion des appels de service Web en arrière-plan

Problème

De nombreuses applications personnalisées appellent des services Web depuis AEM.  Ces applications utilisent Apache Commons HTTP Client ou d'autres bibliothèques.  Lorsque les systèmes en arrière-plan posent des problèmes de performance, AEM peut devenir plus lent.  En outre, si trop de fils sont suspendus, cela peut entraîner des collections de mémoire JVM lentes, des erreurs de mémoire, l'épuisement des fils du système d'exploitation, etc.

Lors de l’acquisition du vidage de fil ou du vidage de tas à partir AEM, vous observez plusieurs fils en attente des appels de service Web.

Scénario d'exemple :
ci-dessous [1], c'est un exemple d'une trace de pile d'un vidage de fils JVM.  Elle a été capturée à partir d’une occurrence AEM avec une application qui réalise un service de fin de processus de mauvaise qualité.

Le service de vidage de fil a rencontré quelques problèmes :

  • Le fil demandé ci-dessous a été bloqué en attendant un service Web qui ne répond pas.  Aucun délai de lecture de port n'a été défini en conséquence le fil est resté en attente.  Cliquez ici pour la solution.
  • Des centaines de fils étaient en attente lors de la demande unique.  Ceci a été dû au fait que le regroupement de fils a été configuré pour être lié séparément, en file d’attente premier arrivé, premier servi.  Le fait d'avoir autant de fils en attente a causé une utilisation élevée de la mémoire.  Voir ici pour la solution.
  • Le service Web appelé a été trop long à répondre.  Ceci a pour effet d’accélérer le tas de fils.

Remarquez les lignes de la pile en surbrillance :

  • En jaune, vous pouvez voir que l’application personnalisée utilise la bibliothèque RestTemplate de Spring Framework pour appeler un service Web.  
  • En orange, vous pouvez constater que Spring Framework utilise Apache Commons HTTP Client pour ses appels de services Web.  
  • En rouge, vous pouvez constater que le thread a été bloqué dans SocketInputStream.socketRead, ce qui signifie qu’il attend une réponse du service Web.

[1]

Cause

Voici quelques causes courantes :

  1. L’hôte du service web est inaccessible et le « délai de connexion » du socket n'est pas défini ou il est trop long (par exemple 10 minutes).
  2. Le service web est actif mais répond avec une erreur non gérée par l’application.
  3. Le service web est actif, mais réagit trop lentement ou est suspendu pendant la réponse.  Le socket « délai d’attente de lecture » n’est pas défini ou est trop long.  Les fils attendent indéfiniment une réponse.
  4. L'ensemble de fils est configuré pour autoriser une demande à la fois.  Cela entraîne l’attente de fils de demande simultanés.

Résolution

Les solutions à ces problèmes sont les suivantes :

  1. Définissez le « délai d'expiration de connexion » à une valeur raisonnable, par exemple, 3 secondes.
  2. Définissez le « délai d'expiration de lecture » à une valeur raisonnable.  Cette valeur dépend du délai d’attente des réponses.  Pour la plupart des petits services web, 10 secondes sont raisonnables.  Toutefois, certains services Web qui effectuent beaucoup de traitement ou envoient et/ou reçoivent des fichiers volumineux nécessitent un délai d'expiration de lecture plus élevé.
  3. Consultez la documentation de votre bibliothèque client httpclient ou client de service web pour savoir comment gérer efficacement le multi-filage.  Par exemple, dans Apache Commons Http Client 3.x, vous pouvez consulter cette page.
  4. Mettez en cache les réponses des appels de service.  Faites-le lorsque vous appelez le service à l’aide des mêmes paramètres et que vous recevez le même résultat plusieurs fois.
  5. Si les données sont partagées (et non spécifiques à l’utilisateur), envisagez d’appeler le service Web en avance dans un fil d’arrière-plan et de stocker le résultat pour une utilisation ultérieure.  Par exemple, utilisez un tâche Sling, planificateur sling ou importateur d'interrogation AEM pour gérer les fils d'arrière-plan.
  6. Si vous avez un grand volume d'appels sortants, mettez en œuvre un algorithme de repousse pour traiter les échecs.  C’est là que lorsque l’application appelle le service et qu’elle échoue X fois, vous devez arrêter d'essayer pendant un certain temps et générer immédiatement un rapport d'erreurs.  Essayez ensuite de le relancer X fois et, en cas d'échec ou d'expiration, patientez plus longtemps, et ainsi de suite.   Cela se fait généralement avec une augmentation exponentielle du temps d’attente avec un temps de limitation maximal (ou algorithme de réduction exponentielle tronquée).

 Adobe

Recevez de l’aide plus rapidement et plus facilement

Nouvel utilisateur ?