Problema

Molte applicazioni personalizzate chiamano i servizi Web da AEM.  Queste applicazioni utilizzano il client HTTP Apache Commons o altre librerie.  Quando i sistemi di back-end hanno problemi di prestazioni, l'AEM ha tempi di risposta lenti.  Inoltre, se troppi thread sono bloccati, questo può portare a una lenta raccolta di rifiuti della JVM, errori di memoria esaurita, esaurimento del thread del sistema operativo, ecc.

Quando si catturano dump di thread o dump di heap da AEM, si osservano molti thread in attesa sulle chiamate del servizio Web.

Scenario di esempio:
Quello sottostante [1], è un esempio di traccia di stack da un dump di thread JVM .  È stato catturato da un'istanza di AEM con un'applicazione che sperimentava un servizio di back-end poco performante.

Il dump di thread ha mostrato alcuni problemi:

  • Il thread di richiesta qui sotto era bloccato in attesa di un servizio Web che non rispondeva.  Nessun timeout di lettura del socket è stato impostato e il thread aspettava all'infiito.  Vedi qui per la soluzione.
  • Centinaia di thread stavano aspettando il thread della singola richiesta.  Questo perché il pool di thread è stato configurato per un singolo thread, con una coda in cui il primo a entrare è il primo a uscire.  Avere così tanti thread in sospeso ha causato un elevato utilizzo della memoria.  Vedi qui per la soluzione.
  • Il servizio Web che veniva chiamato richiedeva troppo tempo per rispondere.  Questo ha causato l'accumulo di thread di cui sopra.

Nota le righe di stack evidenziate:

  • In giallo, puoi vedere che l'applicazione personalizzata sta usando la libreria RestTemplate di Spring Framework per eseguire una chiamata di servizio Web.  
  • In arancione, puoi vedere che Spring Framework utilizza il client HTTP Apache Commons per le chiamate al servizio Web.  
  • In rosso, puoi vedere che il thread era bloccato in SocketInputStream.socketRead che significa che è in attesa di una risposta sul servizio Web.

[1]

capture

Causa

Di seguito sono riportate alcune cause comuni:

  1. L'host del servizio Web non è raggiungibile e il "timeout di connessione" del socket non è impostato o ha un'impostazione troppo lunga (ad esempio 10 minuti).
  2. Il servizio Web è attivo, ma risponde con un errore che non è gestito dall'applicazione.
  3. Il servizio Web è attivo, ma la risposta è troppo lenta o sospesa durante la risposta.  La socket "timeout lettura" non è impostata o è troppo lunga.  I thread attendono una risposta all'infinito.
  4. Il thread pool è configurato per consentire una richiesta alla volta.  Questo fa sì che i thread di richiesta simultanei restino in attesa.

Risoluzione

Le soluzioni a questi problemi sono le seguenti:

  1. Imposta il "timeout di connessione" su un valore ragionevole, ad esempio 3 secondi.
  2. Imposta il "timeout di lettura" su un valore ragionevole.  Questo valore dipende dal tempo previsto per le risposte.  Per la maggior parte dei piccoli servizi Web, 10 secondi è ragionevole.  Tuttavia, alcuni servizi Web che elaborano molto o inviano e/o ricevono file di grandi dimensioni, richiedono l'impostazione di un timeout di lettura più prolungato.
  3. Consulta la documentazione della tua libreria di client http o di servizi Web per come gestire il multi-threading in modo efficiente.  Ad esempio, nel client HTTP di Apache Commons 3.x, puoi consultare questa pagina.
  4. Memorizza in cache le risposte alle chiamate di servizio.  Questo vale quando si chiama il servizio utilizzando gli stessi parametri e si riceve lo stesso risultato più di una volta.
  5. Se i dati sono condivisi (non specifici per l'utente), considera la possibilità di chiamare il servizio Web in anticipo in un thread in background e memorizza il risultato per un uso successivo.  Ad esempio, utilizza un lavoro sling, un programmatore sling o un importatore di sondaggi AEM per gestire un thread in background.
  6. Se hai un elevato volume di chiamate in uscita, implementa un algoritmo di back-off per gestire le chiamate non riuscite.  Quando l'applicazione chiama il servizio e fallisce X volte, smetterai di provare per un certo periodo di tempo segnalando immediatamente gli errori.  Poi riprova X volte e se non riesce o si verifica di nuovo il timeout, attendi più a lungo e così via.  Questo viene fatto di solito con un aumento esponenziale del tempo di attesa con un limite di tempo massimo (alias "Algoritmo di back-off esponenziale troncato").

Questo prodotto è concesso in licenza in base alla licenza di Attribuzione-Non commerciale-Condividi allo stesso modo 3.0 Unported di Creative Commons.  I post su Twitter™ e Facebook non sono coperti dai termini di Creative Commons.

Note legali   |   Informativa sulla privacy online