La campagna parte alle 9 del mattino. Il traffico triplica entro le 9:20. Le pagine prodotto impiegano otto secondi a caricarsi, il carrello si blocca su "aggiungi al carrello" e un cliente ti invia uno screenshot di un errore 504. Riavvia PHP, il negozio si riprende e il budget pubblicitario ha già sfruttato l'ora migliore della giornata.
Quando un negozio PrestaShop rallenta durante una promozione, raramente il problema è la larghezza di banda. Il problema è la concorrenza . Servire dieci clienti e servirne quattrocento sono due compiti diversi per lo stesso hardware: ogni visualizzazione di pagina non memorizzata nella cache impegna un worker PHP per tutta la sua durata, richiede una o due connessioni al database e compete per CPU e memoria con tutte le altre operazioni in corso. In un tranquillo martedì non si raggiunge mai quel limite. Ma dopo venti minuti dall'inizio di una campagna, lo si raggiunge già.
Il problema, quindi, è capire quale livello si è bloccato per primo. Sei possibili cause coprono la maggior parte degli incidenti: caching configurato solo parzialmente, pagine dinamiche non memorizzate nella cache, contesa del database, un modulo "avido" all'interno di un hook, hosting acquistato per giorni di utilizzo medio e un front-end troppo pesante per i telefoni reali. Una sezione per ciascuna causa, di seguito.
1.0 Cosa succede effettivamente a PrestaShop quando il traffico aumenta
Tracciamo una richiesta di pagina prodotto. Apache o Nginx la riceve e la passa a un worker PHP-FPM, il quale si trova ora a dover svolgere una lunga serie di compiti: avviare il kernel, risolvere il controller, attivare ogni hook registrato da un modulo, interrogare MySQL per informazioni su prezzi, disponibilità e regole del carrello, renderizzare i template Smarty e restituire l'HTML. Il worker rimane occupato per tutta la durata di queste operazioni. Il visitatore successivo attende il suo completamento.
Il numero di worker rappresenta il limite massimo, ed è un limite difficile da raggiungere. Supponiamo che il pool consenta 20 processi PHP simultanei e che la creazione di una pagina prodotto richieda 800 ms. In questo caso, si ottengono circa 25 pagine al secondo, indipendentemente dalla larghezza di banda disponibile. Inviandone 60 al secondo, le richieste in eccesso si accumulano, si accumulano e alla fine raggiungono il limite di max_execution_time o il timeout di lettura del proxy. È a questo punto che iniziano a comparire errori 502 e 504.

L'aspetto spiacevole è che il problema si autoalimenta. Le pagine lente trattengono più a lungo gli operatori, la coda si allunga, le pagine rallentano ulteriormente e gli acquirenti, stanchi di aspettare, aggiornano la pagina, aggiungendo ulteriore carico a quello che ha causato l'attesa. I negozi non si deteriorano gradualmente durante i saldi. Sembrano perfetti, e due minuti dopo sono spariti.
Il tempo di risposta al primo byte ( TTFB ) è il dato da tenere d'occhio in tutto questo. jPresta interpreta un TTFB superiore a un secondo come un segnale che qualcosa lato server richiede attenzione, il che sembra corretto. Se un lunedì tranquillo vi porta già vicini a questa soglia, non vi rimane più energia per una campagna.
2.0 Checklist: Il negozio PrestaShop rallenta durante i saldi: da dove iniziare a cercare
Prima di affezionarvi a una teoria, date un'occhiata a questa lista. Bastano quindici minuti e, nella maggior parte dei casi, vi indicherà il colpevole.
- Modalità debug: è _PS_MODE_DEV_ Oppure il profiler è ancora attivo dalla tua ultima indagine?
- Smarty: l'impostazione del modello dice "non ricompilare mai" oppure la ricompilazione avviene su richiesta?
- CCCLe cache CSS e JavaScript sono effettivamente abilitate?
- Backend della cache: qualcosa al di là del filesystem, come APCu, Memcached o Redis?
- Lavoratori: cosa è pm.max_bambiniE quanti erano occupati nelle ore di punta?
- Query lenteIl registro delle query lente contiene informazioni relative alla finestra di vendita?
- moduliPer questa campagna è stata inserita una promozione, un conto alla rovescia o un modulo popup?
3.0 Causa 1: Cache che sembra abilitata ma non lo è
Inizia da Parametri avanzati → Prestazioni . La soluzione più economica si trova nel Back Office, ed è la pagina che più spesso viene lasciata in errore.
I template vengono convertiti in PHP prima che qualsiasi elemento raggiunga il browser, e la frequenza con cui ciò avviene è un'impostazione che puoi controllare. La documentazione ufficiale sulle prestazioni elenca tre modalità; una di queste, ovvero " non ricompilare mai i file dei template ", è consigliata per un sito web sotto carico . Selezionando "ricompila se i file vengono aggiornati", ogni template effettua un controllo del filesystem a ogni richiesta: gestibile con traffico ridotto, ma inefficiente con traffico elevato. L'opzione "Forza la compilazione" è un'impostazione dello sviluppatore e, se lasciata attiva per tutta la durata di una campagna, comporta la ricostruzione di template identici migliaia di volte senza alcun risultato.
Su quello schermo sono presenti altre due funzioni. La modalità di debug visualizza le tracce dello stack e disattiva le ottimizzazioni, quindi in produzione deve essere sempre disattivata. Gli interruttori per disabilitare i moduli non PrestaShop e tutte le opzioni di override servono per la diagnostica; non sono impostazioni che vengono distribuite.
4.0 Configurazione della cache CCC di PrestaShop da verificare prima di una vendita
Le tre C sono combinazione, compressione e caching, e l'effetto è un numero inferiore di file di risorse, più piccoli, che PrestaShop smette di ricostruire a ogni accesso. Attiva il CSS; raramente causa problemi. Il JavaScript, invece, merita prima un test di staging, poiché l'unione dei file ne modifica l'ordine di esecuzione e alcuni moduli non lo gradiscono affatto. Meglio scoprirlo di giovedì che a metà del checkout del Black Friday.
Da sapere: il multiplexing HTTP/2 gestisce senza problemi un gran numero di file di piccole dimensioni, quindi combinarli risulta meno vantaggioso rispetto al passato . La minimizzazione e la lunga durata della cache del browser continuano a essere importanti.
Il backend della cache è l'ultimo elemento in quella schermata. Il filesystem è l'impostazione predefinita e regge fino all'arrivo del volume. APCu è adatto a un singolo server, Memcached a diversi server e Redis gestisce bene le sessioni e la cache degli oggetti. Tutti questi sistemi leggono dalla memoria anziché dal disco e, in presenza di concorrenza, questa differenza si amplia rapidamente.
5.0 Causa 2: Nessuna pagina dinamica viene memorizzata nella cache
Tutto ciò che è descritto nella Causa 1 contribuisce a ridurre i costi di creazione di una pagina. Nessuno di questi elementi impedisce la creazione della pagina stessa. PHP si avvia comunque, le query vengono eseguite e l'HTML viene generato per ogni visitatore, inclusi i duemila che arrivano tutti sulla stessa pagina della categoria scontata nello stesso minuto.
La cache full-page risolve questo problema. Posiziona un reverse proxy prima del server web ( di solito si sceglie Varnish ), lascia che conservi l'HTML finale e le centinaia di visitatori successivi verranno serviti senza che PHP o MySQL si attivino. Le risposte arrivano in pochi millisecondi e il tuo server di origine gestisce solo ciò che deve essere effettivamente elaborato. Nei giorni di saldi lampo, questo semplice accorgimento può fare la differenza tra un negozio che stenta a decollare e uno che fallisce.
Ci sono delle regole che non si possono infrangere:
- I percorsi specifici della sessione vengono esclusi. Escludi le pagine del carrello, del checkout, del login e dell'account, altrimenti gli acquirenti finiranno per visualizzare il carrello di qualcun altro. Ogni team che ha gestito male una cache a pagina intera ha questa storia da raccontare.
- Decidere l'invalidazione prima del lancio. Definisci cosa elimina una voce quando il prezzo o il livello delle azioni si modificano, quindi testa l'eliminazione. Servire il prezzo di ieri nel bel mezzo di una promozione costa fiducia e una mattinata di richieste di assistenza.
- Utilizza ESI per i piccoli dettagli personalizzati. come ad esempio il totale del carrello o il nome di un cliente, quindi un singolo blocco dinamico non invalida un'intera pagina.

I picchi di traffico vengono gestiti al meglio a livelli. Il browser gestisce ciò che può, una CDN si occupa dei file statici, il proxy gestisce l'HTML, Redis o Memcached rispondono alle domande ricorrenti e il database interviene solo quando nessun livello superiore è in grado di fornire una risposta. Molti negozi utilizzano solo il primo e l'ultimo livello, senza nulla in mezzo.
6.0 Causa 3: Il database è il luogo in cui si forma effettivamente la coda
I processi si accumulano perché ognuno è in attesa di MySQL. Le tabelle del carrello e degli ordini non si riducono mai, quindi ps_cart , ps_cart_product , ps_orders e ps_order_detail sopportano il carico maggiore proprio nel momento in cui il checkout diventa più affollato. L'ottimizzazione del database di PrestaShop per i picchi di traffico si basa principalmente su queste quattro operazioni:
- Individua le query lente nei log, non affidarti all'intuito. Un valore predefinito tempo_di_richiesta_lungo Dieci secondi sono inutili per la vendita al dettaglio, quindi abbassali. jPresta ritiene che qualsiasi valore superiore a 100 ms meriti un'occhiata e che il tempo del database superiore alla metà del tempo di pagina sia un avvertimento. Il profiler racconta la stessa storia per ogni hook; limitalo al tuo IP in config/defines.inc.php così i clienti non lo vedono mai.
- Alimenta il pool di buffer. InnoDB mantiene dati e indici nella RAM quando gli si concede spazio. Su un server dedicato al database, circa il 70-80% della memoria è occupato da pagine di carrello e prodotti molto richiesti, che non scrivono su disco.
- Potate solo ciò che è sicuro potare. Sessioni guest scadute, vecchi registri di connessione e statistiche di ricerca obsolete intasano le tabelle e rallentano ogni scansione. Un'attività pianificata mensilmente, non un panico la mattina dei saldi. Carrelli e ordini sono dati aziendali, quindi archiviateli anziché eliminarli.
- Non fare affidamento sulla cache delle query. MySQL 8.0 ha eliminato questa funzionalità, quindi se il vostro modello mentale include ancora un database che memorizza silenziosamente le query ripetute, aggiornatelo. Redis o Memcached svolgono ora questo compito.
Un altro aspetto che spesso crea confusione è il parametro max_connections . Se lo si imposta a un valore inferiore al numero di worker moltiplicato per il numero di connessioni aperte da ciascuna richiesta, si rischia di ricevere l'errore "troppe connessioni" nei momenti di picco. Il messaggio viene interpretato come un crash, ma si tratta semplicemente di un calcolo aritmetico.
7.0 Causa 4: Un modulo che esegue un lavoro oneroso all'interno di un hook
Le vendite coincidono con l'installazione di nuovi moduli, ed è per questo che questa categoria domina le analisi post-vendita.
Il codice hook viene eseguito a ogni rendering, quindi qualsiasi operazione compiuta viene moltiplicata per il traffico. Un modulo per il conto alla rovescia che controlla le promozioni attive per ogni prodotto in un elenco di 48 articoli. Un widget "visualizzati di recente" che scrive una riga per ogni visualizzazione di pagina. Un modulo di avviso di disponibilità che chiama un'API senza timeout. Ognuno di questi trasforma una singola richiesta di pagina in decine di operazioni, impercettibili con dieci visitatori e evidenti con quattrocento.

Le chiamate in uscita sono la versione peggiore. Un modulo che comunica in modo sincrono con un servizio di terze parti rimane in attesa quando quel servizio ha un suo momento di crisi, e i tuoi worker restano bloccati con esso. Venti worker in attesa di una chiamata API di cinque secondi sono come un negozio chiuso, a prescindere da ciò che dice il grafico della CPU.
Trovare il colpevole è un lavoro di bisezione. Su una copia di staging, disattiva i moduli non-PrestaShop, verifica che la pagina sia più veloce, quindi riattivali gradualmente fino a quando il costo non torna ai livelli precedenti. Il profiler semplifica notevolmente questo processo, poiché riporta il numero di query e i tempi per ogni hook, invece di lasciarti il compito di dedurli. hiddentechies e jPresta giungono alla stessa conclusione: eliminare i moduli che nessuno usa è più redditizio della maggior parte delle ottimizzazioni.
8.0 Causa 5: Hosting dimensionato per una giornata media
L'hosting condiviso funziona bene con un traffico costante. Il problema sorge a livello strutturale durante i periodi di saldi: CPU, memoria e I/O sono condivisi con gli altri server e i provider limitano le prestazioni in caso di picchi di traffico. Una campagna di sconti rappresenta, di per sé, un unico, lungo picco.
Quattro cose da verificare:
- Versione PHP e OPcache. Le versioni più recenti di PHP sono notevolmente più veloci rispetto alla serie 7.x e OPcache memorizza il bytecode compilato nella memoria condivisa, impedendo all'interprete di rileggere i file. Verifica che sia abilitato e controlla l'allocazione di memoria, poiché le impostazioni predefinite non sono state pensate per una codebase di queste dimensioni.
- Dimensionamento del pool PHP-FPM. Lavora pm.max_bambini ricavato dalla memoria misurata per singolo worker, non da un post di un blog. Impostandolo su un valore basso, le richieste vengono accodate mentre la CPU è inattiva. Impostandolo su un valore alto, il sistema effettua lo swapping, il che è più dannoso.
- Verifica della correttezza della configurazione del server. Il progetto PrestaShop script php-ps-info ti dirà se le impostazioni di PHP e del server web corrispondono a quelle previste dalla tua versione.
- Spazio in altezza. Se, nonostante tutte queste ottimizzazioni, il TTFB è ancora superiore a un secondo, significa che l'hardware non è sufficiente. Un VPS o un hosting PrestaShop gestito su NVMe possono essere d'aiuto, così come la memorizzazione nella cache HTML, e la soluzione migliore è combinare entrambe le cose.
9.0 Causa 6: Un'interfaccia che blocca il browser
Capacità e velocità percepita sono due problemi distinti, non uno solo. Un backend che risponde in 200 ms sembra comunque inefficiente di fronte a quattro megabyte di immagini principali non modificate. Le soglie di Google funzionano come un punteggio: 2.5 secondi per il rendering del contenuto più grande, un quinto di secondo per l'interazione con il rendering successivo, 0.1 secondi per lo spostamento del layout. Le pagine delle campagne non superano tutte e tre le prove contemporaneamente, perché banner, badge, widget per il conto alla rovescia e qualsiasi tag aggiunto dal marketing la settimana scorsa arrivano in ritardo e riorganizzano la pagina mentre qualcuno la sta leggendo.
Nessuna delle soluzioni proposte è interessante, ed è probabilmente per questo che vengono ignorate. Comprimi le immagini e distribuisci in formato WebP o AVIF. Carica in modo differito tutto ciò che si trova al di sotto della parte visibile della pagina. Assegna dimensioni fisse a banner e countdown in modo che non possano spostare il contenuto. Esegui JavaScript solo quando non è necessario. Infine, sposta i file statici su una CDN, il che accorcia i tempi di caricamento per gli utenti remoti e riduce il carico di banda sul tuo server.
10.0 Leggere i dati dopo una giornata di vendite negativa
La registrazione di un brutto venerdì è ancora sul tuo server. Ripercorrila a ritroso.

- Crea una cronologia. Confronta i log di accesso, i log di PHP-FPM e i log di MySQL con il minuto in cui il traffico è aumentato. Considera la risorsa che si satura per prima in quell'intervallo di tempo.
- Leggi l'errore, poi verificalo. Un errore 502 di solito significa che nessun worker era libero o che uno si è interrotto durante la richiesta; un errore 504 significa che qualcosa ha superato il tempo limite. "Troppe connessioni" è un messaggio del database. Nessuno di questi errori indica da solo la causa principale, quindi è consigliabile leggerli insieme al log dell'applicazione.
- Attiva il log delle operazioni lente di PHP-FPM. Qualsiasi operazione più lenta della soglia impostata genera una traccia dello stack che indica la funzione ancora in esecuzione. È una tecnica poco utilizzata, ma solitamente rappresenta il percorso più rapido per accedere a un modulo specifico.
- Controlla il registro delle query lente per la finestra di vendita, ordinata in base al tempo totale anziché alla peggiore singola esecuzione.
- Mantenere separata la misurazione della parte anteriore. Lighthouse, PageSpeed Insights, WebPageTest o GTmetrix si occupano del rendering. Combinando questi dati con i tempi di esecuzione del server, si arriva spesso ad acquistare hardware per risolvere un problema di visualizzazione delle immagini.
Uno strumento APM trasforma questo processo da analisi forense a monitoraggio, che è l'ordine migliore in cui procedere.
11.0 Come prepararsi alla prossima vendita
Una vendita è un evento di capacità a cui è associata un'attività di marketing. Pianificala in quest'ottica.

- Descrivi come appare la normalità. TTFB, LCP, rapporto di successo della cache, tempo medio di accesso al database, tutti rilevati in un noioso mercoledì. Saltare questo passaggio significa che ogni successiva modifica diventerà un'opinione anziché una misurazione.
- Eseguire un test di carico sulla copia di staging. Eseguite un test con un numero di richieste simultanee di picco reale, inclusa l'aggiunta al carrello, e annotate la frequenza delle richieste in corrispondenza della quale iniziano a comparire errori. Tale frequenza rappresenta la vostra capacità effettiva.
- Congela il negozio prima del lancio. Nessuna modifica al tema, nessun nuovo modulo, nessun aggiornamento negli ultimi giorni. Le distribuzioni svuotano la cache e una cache fredda pochi minuti prima dell'apertura è la peggiore delle situazioni possibili.
- Riscalda le cache e pre-genera le immagini per le pagine della campagna dopo l'implementazione finale, in modo che il visitatore numero uno riceva una visita invece di creare la voce.
- Guardalo mentre è in esecuzione. Saturazione dei worker, rapporto di successo della cache, connessioni al database, tasso di errore. Individuare un problema in due minuti è meglio che venirne a conoscenza dopo quaranta.
- Decidete ora il piano di degradazione. Un blocco di raccomandazioni, contatori di magazzino in tempo reale, un filtro a più livelli: impara a capire cosa puoi disattivare per alleggerire il carico senza dover chiudere l'attività.
Il quinto passaggio è quello che molti saltano, per poi scoprire un rallentamento delle vendite tramite un'email di un cliente. Scegliete due o tre parametri che monitorerete attentamente e decidete dove visualizzarli: su una dashboard, in una vista APM o in un terminale con i log in esecuzione. In questo modo, ridurrete la distanza tra "le vendite sembrano lente" e "il problema è nel database", e durante una campagna questa distanza si misura in ordini persi.
12.0 Dove ti porta tutto questo
Un negozio PrestaShop lento durante i saldi è spesso dovuto a un problema di capacità, con una lista di possibili cause piuttosto breve. Il traffico ha spinto qualcosa oltre un limite mai raggiunto prima, e di solito si tratta di caching incompleto, pagine dinamiche non memorizzate nella cache, un database che lavora più del necessario, un modulo che non funziona correttamente all'interno di un hook, un hosting dimensionato per i giorni normali o un front-end progettato senza pensare ai dispositivi mobili.
Procedi in ordine dall'elenco, dato che gli elementi meno costosi si trovano in cima. Imposta Smarty su "mai ricompilare", CCC attivo, cache spostata in memoria, modalità debug disattivata: questo richiede solo un pomeriggio e cambia la capacità di carico del tuo server attuale. Esegui un test di carico in seguito, in modo che la prossima campagna parta da dati concreti anziché da un eccesso di ottimismo.
Se questa settimana dovete fare una sola cosa, aprite il registro delle query lente accanto alla pagina Prestazioni e seguite la checklist qui sopra. Tutto ciò che emergerà sarà la causa del problema la prossima volta, ed è molto più facile affrontarlo in un tranquillo martedì che alle 9:20 del mattino del lancio.
Se hai domande o necessiti di assistenza per le prestazioni o la migrazione del tuo sito web, i nostri esperti sono a tua disposizione. Contatta oggi stesso il team di Knowband all'indirizzo [email protected] per plugin e-commerce affidabili e personalizzati in base alle tue esigenze.



