Guide

Come velocizzare WordPress con Memcached e Batcache

Più del 20% dei siti web al mondo sono sviluppati con tecnologia WordPress. Il nostro amato CMS, come tutti gli altri del suo settore, richiede però elaborazioni non indifferenti.

Ogni volta che una pagina viene richiesta, infatti, numerose sono le query SQL che CMS e plugin effettuano per scaricare le configurazioni e realizzare il codice HTML da fornire al browser. I più curiosi possono vederlo utilizzando il plugin Query Monitor.

Tutte queste query unite all’elaborazione del codice PHP rallentano il tempo di caricamento della pagina, con impatti negativi sulle prestazioni.

Per sopperire a questo problema viene solitamente utilizzato il plugin WP Super Cache di Automattic. Questo ottimo plugin, utilizzato per l’appunto come cache HTML, salva le copie delle pagine sul disco fisso.

Fintanto che si usano dischi SSD o si risiede su hosting condivisi, questo plugin rimane un’ottima scelta. Ma quando ci si trova a lavorare su un server virtuale o dedicato, allora è possibile ottenere prestazioni più elevate effettuando caching HTML in RAM.

Abbiamo già visto come aumentare del 150% le performance utilizzando FastCGI Cache di Nginx.  Oggi vedremo insieme una tecnica di ottimizzazione in grado di velocizzare il sito web utilizzando il famoso Memcached, un key-store value solitamente utilizzato per limitare gli accessi al database, salvando in memoria il risultato di alcune query.

Memcached può essere utilizzato per memorizzare in memoria RAM qualsiasi tipo di contenuto, anche codice HTML. Per raggiungere l’obiettivo utilizzeremo il plugin gratuito Batcache.

Alla fine del processo le pagine del sito web saranno completamente caricate in RAM con tempi di risposta molto più rapidi. Se sei un amante di Redis potrebbe interessarti la guida su come velocizzare WordPress con Redis Cache.

Installazione di Memcached

Come primo passo occorre installare memcached. Su sistemi debian-based come Ubuntu, basta avviare il seguente comando che consentirà di installare memcached ed il modulo per PHP:

$ sudo apt-get install memcached php-memcached

Terminata l’installazione, verificare che memcached 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 1055/mysqld 
tcp 0 0 127.0.0.1:11211 0.0.0.0:* LISTEN 17644/memcached

Se tra i servizi è presente memcached, che di default è in ascolto in localhost sulla porta 11211, allora tutto è andato a buon fine. Naturalmente come qualsiasi altro tipo di servizio è possibile stopparlo, avviarlo o riavviarlo:

sudo service memcached restart

Il file di configurazione di memcached si trova di default su /etc/memcached.conf. Dal file di configurazione è possibile cambiare la quantità di memoria RAM da dedicare al servizio (di default 64 MegaByte), la porta ed il numero di connessioni simultanee (di default 1024).

Queste impostazioni vanno configurate a seconda delle caratteristiche hardware del server.

# Start with a cap of 64 megs of memory. It's reasonable, and the daemon default
# Note that the daemon will grow to this size, but does not start out holding this much
# memory
-m 64

# Default connection port is 11211
-p 11211

# Limit the number of simultaneous incoming connections. The daemon default is 1024
# -c 1024

Ogni qual volta si effettua una modifica al file di configurazione di memcached, occorre riavviare il servizio.

A questo punto non rimane che riavviare il demone PHP per interfacciarlo con memcached. Su Nginx basta riavviare PHP-FPM:

sudo service php7.1-fpm restart

Su Apache occorre riavviare l’intero server web:

sudo service apache2 restart

Adesso occorre verificare la corretta installazione del modulo PHP. Per farlo basta creare un file sulla root del sito web, ad esempio phpinfo.php, ed inserire al suo interno il seguente codice:

<?php phpinfo(); ?>

Salvare e aprire tale file con il browser. Se memcached è stato installato correttamente, vedrete tra le varie configurazioni pure quelle che lo riguardano:

Installazione di Batcache

Batcache 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/batcache.

Fatto questo, scaricare sempre su wp-content il file http://svn.wp-plugins.org/memcached/trunk/object-cache.php, che altro non sarebbe che il plugin Memcached Object Cache.

Modificare wp-config.php ed inserire le seguenti righe

global $batcache;

$batcache = array('max_age' => 3600 );

define('WP_CACHE_KEY_SALT', 'test.example.com');
define('WP_CACHE', true);

Il primo parametro dell’array batcache, max_age, indica il tempo di vita della cache in secondi. In questo caso sono 3600, l’equivalente di 1 ora oltre la quale la cache viene svuotata.

Con la costante WP_CACHE_KEY_SALT settata sul nome del sito evitiamo race condition con eventuali altri siti ospitati sullo stesso server e che utilizzano la medesima configurazione.

Fatto questo, salvare wp-config.php e visitare una pagina del sito, avendo l’accortezza di caricarla due volte per permettere alla cache di avere effetto. Se tutto è andato a buon fine, in fondo al codice sorgente della pagina vedrete un commento HTML simile al seguente:

<!--
    generated in 0.116 seconds
    50610 bytes batcached for 3600 seconds
-->

Benchmark

Quando si effettua qualsiasi tipo di testing occorre utilizzare diversi tool esterni ed analizzarne le metriche. I tool esterni sono molto affidabili in quanto preservano quasi sempre la connettività e non hanno cali di rendimento hardware, cosa che invece potrebbe capitare con i personal computer e connessioni ADSL casalinghe.

Al termine del test noterete come le performance del Time To First Byte medio sono aumentate del 93.5%!

TTFB senza Memcached

TTFB con Memcached

Ottimizzazione di Memcached con i Socket Unix

Nella versione di default, memcached utilizza i socket TCP per interfacciarsi con le applicazioni. È possibile aumentare la velocità di risposta di circa il 33% utilizzando al suo posto i socket Unix, che operando ad un livello inferiore del modello OSI sono più veloci. 

Come prima cosa aggiungere l’utente memcache al gruppo www-data:

sudo usermod -g www-data memcache

Dopodiché modificare /etc/memcached.conf, commentare le righe che fanno riferimento all’indirizzo IP e alla porta e aggiungere le righe di configurazione che consentono di utilizzare i socket unix e di settare il giusto permesso:

#-p 11211
#-l 127.0.0.1
# Set unix socket which we put in the folder /var/run/memcached and made memcache user the owner
-s /tmp/memcached.sock

# Set permissions for the memcached socket so memcache user and www-data group can execute
-a 775

Di seguito il file di configurazione di default completo di modifiche per i socket unix:

# memcached default config file
# 2003 - Jay Bonci <jaybonci@debian.org>
# This configuration file is read by the start-memcached script provided as
# part of the Debian GNU/Linux distribution.

# Run memcached as a daemon. This command is implied, and is not needed for the
# daemon to run. See the README.Debian that comes with this package for more
# information.
-d

# Log memcached's output to /var/log/memcached
logfile /var/log/memcached.log

# Be verbose
# -v

# Be even more verbose (print client commands as well)
# -vv

# Start with a cap of 64 megs of memory. It's reasonable, and the daemon default
# Note that the daemon will grow to this size, but does not start out holding this much
# memory
-m 64

# Default connection port is 11211
#-p 11211

# Run the daemon as root. The start-memcached will default to running as root if no
# -u command is present in this config file
-u memcache

# Specify which IP address to listen on. The default is to listen on all IP addresses
# This parameter is one of the only security measures that memcached has, so make sure
# it's listening on a firewalled interface.
#-l 127.0.0.1

# Limit the number of simultaneous incoming connections. The daemon default is 1024
# -c 1024

# Lock down all paged memory. Consult with the README and homepage before you do this
# -k

# Return error when memory is exhausted (rather than removing items)
# -M

# Maximize core file limit
# -r

# Set unix socket which we put in the folder /var/run/memcached and made memcache user the owner
-s /tmp/memcached.sock

# Set permissions for the memcached socket so memcache user and www-data group can execute
-a 775

Salvare il file e riavviare memcached:

sudo service memcached restart

A questo punto verificare l’avvenuta creazione del descrittore del socket unix all’interno di /tmp:

$ ls /tmp/
memcached.sock

Una volta sicuri che il socket unix sia stato creato correttamente, modificare wp-config.php e aggiungere dopo global $batcache; la seguente riga:

$memcached_servers = array('unix:///tmp/memcached.sock');

Ecco la configurazione completa:

global $batcache;

$memcached_servers = array('unix:///tmp/memcached.sock');

$batcache = array('max_age' => 3600 );

define('WP_CACHE_KEY_SALT', 'test.example.com');
define('WP_CACHE', true);

Salvare e verificare, come sempre caricando una pagina due volte, che la cache stia funzionando correttamente.

Casi noti di utilizzo

Memcached come page caching viene utilizzato da Salvatore Aranzulla per ottenere bassi tempi di Time To First Byte. Naturalmente non è questa sola configurazione a rendere il sito molto veloce.

Il sito di Salvatore, infatti, ha alle spalle una solida infrastruttura server. L’applicazione web, inoltre, è configurata per diminuire al massimo il sovraccarico del browser, ottimizzando il percorso di rendering critico.

Unita ad altre best practice di performance e ad una scrupolosa ottimizzazione del template, Salvatore presenta un sito semplice e molto rapido, che risponde benissimo alle esigenze dei suoi lettori ed al modello di business.

Conclusione

Abbiamo visto come utilizzare Memcached non solo per sopperire al continuo utilizzo di query SQL bensì come storage per cache HTML del nostro sito WordPress.

Naturalmente questa parte di ottimizzazione riguarda la parte server, mentre per la parte client, ovvero la più critica, occorrerà sempre richiedere una consulenza per ottimizzare il percorso di rendering critico ed ottenere così tempi di caricamento prossimi al secondo.

Salvatore Fresta

Disqus Comments Loading...
Share
Pubblicato da
Salvatore Fresta
Tag: wordpress

Recent Posts

Cloudflare: come identificare la location del server

Cloudflare si antepone tra il server di origine e la richiesta dell'utente per servire file…

18 Marzo 2019

Ottimizzazione MySQL: come scegliere il valore di InnoDB Buffer Pool

L'ottimizzazione del database MySQL è tra i tuning più importanti in tema di performance web.…

5 Marzo 2019

Cache di post e pagine WordPress con Cloudflare

Cloudflare è un ottimo servizio utilizzato sia per migliorare le performance in caso di traffico…

19 Settembre 2018

WordPress, CDN, offloading e compressione immagini

Una delle tante pratiche di ottimizzazione del tempo di caricamento pagina quando si riceve un…

22 Maggio 2018

WordPress e WebP: guida completa

WebP è un formato di immagine sviluppato da Google ed appositamente pensato per ottimizzare il…

17 Maggio 2018

Caching avanzato con i Service Worker

Qualche settimana fa abbiamo visto cosa sono i service worker e come utilizzarli per creare…

12 Maggio 2018