In una guida precedente abbiamo visto come velocizzare WordPress con Memcached, metodo largamente utilizzato sul sito di Salvatore Aranzulla per ottenere tempi di risposta molto rapidi e poter ospitare più utenti contemporaneamente.
Oggi vedremo come utilizzare il diretto concorrente di Memcached per ottenere prestazioni ancora maggiori. Stiamo parlando di Redis, un key-value store sviluppato dal siciliano Salvatore Sanfilippo.
Molto apprezzato per le sue caratteristiche, secondo DB-Engines.com è oggi il key-value store più utilizzato al mondo. Esattamente come Memcached, su WordPress Redis è largamente utilizzato per effettuare caching di query SQL mediante il plugin Redis Object Cache.
Oggi vedremo come utilizzarlo per effettuare page caching, ovvero memorizzare in cache l’intera pagina HTML affinché questa non venga nuovamente elaborata quando richiesta una seconda volta.
A differenza del page caching effettuato da plugin come WP Super Cache, in questo caso la copia della pagina non viene memorizzata sul disco rigido bensì in memoria RAM, aumentando di gran lunga il tempo di risposta.
Indice dei contenuti
Come primo passo occorre installare Redis. Su sistemi debian-based come Ubuntu, basta avviare il seguente comando che consentirà di installare sia il key-store value che il modulo per PHP:
$ sudo apt-get install redis-server php-redis
Terminata l’installazione, verificare che Redis sia installato ed attivo. Per farlo controlliamo i servizi di rete in ascolto:
$ sudo netstat -ntapd Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 11464/nginx -g daem tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN 24504/mysqld tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 25117/redis-server
Se tra i servizi è presente redis-server, che di default è in ascolto in localhost sulla porta 6379, allora tutto è andato a buon fine. Naturalmente come qualsiasi altro tipo di servizio è possibile stopparlo, avviarlo o riavviarlo:
$ sudo service redis-server restart
Il file di configurazione di Redis si trova di default su /etc/redis/redis.conf. Dal file di configurazione è possibile cambiare molte configurazioni tra cui la quantità di memoria RAM massima da utilizzare e la politica da adottare per rimuovere gli elementi dalla cache quando la RAM viene saturata.
La quantità massima di RAM da allocare viene specificata dalla direttiva maxmemory mentre la politica dalla direttiva maxmemory-policy:
maxmemory 500m maxmemory-policy allkeys-lru
La quantità di memoria da allocare dipende sia dalle caratteristiche del server che dal numero di HIT della cache, per cui inizialmente le statistiche di HIT/MISS vanno monitorate per poi applicare le corrette ottimizzazioni.
Ricordarsi di riavviare il servizio ad ogni modifica del file di configurazione.
Il plugin Redis Page Cache può essere installato direttamente dallo stesso WordPress oppure può essere scaricato dal repository ufficiale.
Una volta installato ed attivato, copiare su wp-content il file advanced-cache.php presente all’interno della directory del plugin wp-content/plugins/pj-page-cache-red.
Dopodiché modificare wp-config.php ed inserire la seguente riga:
define('WP_CACHE', true);
Per controllare se la pagina viene inserita in cache, ovvero se viene effettuato un HIT anziché un MISS, occorre aprire la DevTools di Google Chrome, cliccare sul tab Network, cliccare sulla prima richiesta (ovvero la pagina web) ed andare a verificare il campo x-pj-cache-status nello header HTTP di risposta.
Pagina in cache
Pagina non in cache
Passiamo alla fase più interessante delle ottimizzazioni: il test delle performance. In questo caso il test è stato molto semplice. È stato misurato il Time To First Byte prima e dopo l’applicazione di Redis sullo stesso sito WordPress.
Al termine del primo test abbiamo appurato come le performance del tempo di risposta della pagina web siano aumentate del 130%!
TTFB senza Redis
TTFB con Redis
In aggiunta al primo test abbiamo effettuato anche uno stress test con loader.io di 1000 utenti in appena 60 secondi. Dai grafici sottostanti è possibile notare come senza Redis il TTFB medio sale a 855 ms mentre con Redis scende a 299 ms.
Grazie a Redis le performance sono aumentate del 186%, permettendo al server di poter gestire un numero più alto di utenti contemporaneamente connessi!
Redis Page Cache non dispone di un’interfaccia grafica. Tutte le configurazioni devono essere effettuate per mezzo dell’array PHP globale $redis_page_cache_config.
Basta aprire wp-config.php ed aggiungere le righe necessarie per applicare la configurazione voluta. Ad esempio:
$redis_page_cache_config = array(); // Cambio il time to live della cache a 10 minuti (600 secondi) $redis_page_cache_config['ttl'] = 600; // Ignoro/elimino i seguenti cookie per migliorare la memorizzazione in cache $redis_page_cache_config['ignore_cookies'] = array( 'wordpress_test_cookie', 'openstat_ref' ); // Per lo stesso motivo ignoro le seguenti variabili GET $redis_page_cache_config['ignore_request_keys'] = array( 'utm_source', 'utm_medium' ); // Per le richieste mobile voglio utilizzare un contenitore di memoria differente $redis_page_cache_config['unique'] = array( 'is_mobile' => my_is_mobile() );
È possibile effettuare altri tipi di configurazione semplicemente analizzando il contenuto del file advanced-cache.php.
Di default il plugin effettua il purge della cache ogni qual volta un post viene pubblicato o aggiornato, inclusa la home page ed i feeds RSS.
In ogni caso è possibile svuotare la cache manualmente creando un semplice script PHP interconnesso a WordPress (come un must use plugin). Di seguito diversi esempi di purge manuale:
// Purge per post ID Redis_Page_Cache::clear_cache_by_post_id( $post->ID ); // Purge per URL Redis_Page_Cache::clear_cache_by_url( 'https://example.org/secret-page/' ); // Purge per flag Redis_Page_Cache::clear_cache_by_flag( array( 'special-flag' ) );
I flag sono come dei tag per la cache. Un post può essere rappresentato da diverse URL, ognuna avente una locazione di memoria in cache dedicata. Esempio:
https://example.org/?p=123 https://example.org/post-slug/ https://example.org/post-slug/page/2/ https://example.org/post-slug/?show_comments=1
Nell’esempio precedente è possibile vedere come il post con ID 123 può essere rappresentato da ben 4 URL. Tutte queste URL sono accomunate dall’ID 123 che viene utilizzato come flag. Se si conosce tale ID è possibile eliminare dalla cache tutte le rappresentazioni del post in una volta sola:
$post_id = 123; $flag = sprintf( 'post:%d:%d', get_current_blog_id(), $post_id ); Redis_Page_Cache::clear_cache_by_flag( $flag );
È inoltre possibile contrassegnare i post con flag personalizzati:
// Contrassegno tutti i post con un flag che chiamo my-special-tag: if ( is_single() && has_tag( 'my-special-tag' ) ) { Redis_Page_Cache::flag( 'my-special-tag' ); }
E quando si desidera svuotare la cache dei soli post basterà richiamare il metodo PHP passando come argomento il nome del flag personalizzato:
Redis_Page_Cache::clear_cache_by_flag( 'my-special-tag' );
Nota bene! Tutti i metodi di purge manuale appena discussi non eliminano gli elementi dalla memoria bensì ne azzerano il time to live affinché possano essere rimpiazzati con i nuovi. Se si desidera eliminarli dalla memoria, basterà passare al metodo un secondo argomento ($expire) da settare a false.
Redis_Page_Cache::clear_cache_by_flag( 'my-special-tag', false );
Nella versione di default Redis utilizza i socket TCP. È possibile aumentare la velocità di circa il 25% utilizzando al loro posto i socket Unix, che operando ad un livello inferiore del modello OSI risultano essere più veloci.
Come prima cosa aggiungere l’utente redis al gruppo www-data:
$ sudo usermod -g www-data redis
Creare la directory dove far girare il socket Unix ed attribuirgli la corretta ownership:
$ sudo mkdir -p /var/run/redis/ $ sudo chown -R redis:www-data /var/run/redis
Dopodiché aprire il file di configurazione di Redis ed aggiungere le seguenti righe:
unixsocket /var/run/redis/redis.sock unixsocketperm 775
Salvare il file e riavviare Redis:
$ sudo service redis-server restart
A questo punto verificare l’avvenuta creazione del descrittore del socket Unix all’interno di /var/run/redis/:
$ ls /var/run/redis/ redis.sock
Una volta sicuri che il socket unix sia stato creato correttamente, modificare wp-config.php e aggiungere la seguente configurazione di Redis Page Cache per specificare il path del socket unix:
$redis_page_cache_config = array(); $redis_page_cache_config['redis_host'] = '/var/run/redis/redis.sock';
Salvare e verificare il corretto funzionamento della cache.
Abbiamo visto come utilizzare Redis come cache HTML per le pagine del nostro sito WordPress. Così come per Memcached ed Nginx FastCGI Cache, questa configurazione di Redis non permette di memorizzare in RAM anche una copia dei file statici, come immagini e fogli di stile.
Tale limitazione ci consente dunque di sopperire alla “sola” elaborazione PHP della pagina. Successivamente vedremo come installare sul server uno stack con Varnish per effettuare anche caching di file statici, memorizzando in RAM una copia completa del sito web.
Per ottenere tempi di caricamento prossimi al secondo per siti web complessi come WordPress, non basta solo curare gli aspetti lato server. L’applicazione web va infatti ottimizzata nel suo percorso di rendering critico affinché il browser, special modo se mobile, riesca a velocizzarne la visualizzazione.
Se anche tu vuoi ottenere la massima velocità dal tuo sito web continua a seguire le guide su questo sito o richiedi una consulenza in performance.