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]
Causa
Di seguito sono riportate alcune cause comuni:
- 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).
- Il servizio Web è attivo, ma risponde con un errore che non è gestito dall'applicazione.
- 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.
- 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:
- Imposta il "timeout di connessione" su un valore ragionevole, ad esempio 3 secondi.
- 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.
- 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.
- 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.
- 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.
- 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").
Accedi al tuo account