Problema
Spesso in un progetto PHP capita di dover eseguire operazioni in modo asincrono. Alcuni esempi sono: lavorazione di code email, indicizzazione di dati, calcoli che richiedono lunghi tempi di elaborazione.
Prassi comune è gestire tali operazioni utilizzando cron per eseguire processi in backgroud. Tuttavia, utilizzare cron richiede espedienti per evitare l’accavallemento delle esecuzioni e ci costringe ad implementare procedure specifiche e meccanismi di stoccaggio dei dati necessari per l’elaborazione.
Soluzione: Gearman + Supervisor
La soluzione che concerne Gearman e Supervisor, invece, non richiede alcun meccanismo di data storage e fornisce un modo molto semplice per sviluppare processi in PHP.
Dalla homepage di Gearman:
Gearman fornisce una applicazione framework generica per distribuire lavoro su altre macchine o processi che sono più adatti ad eseguire tale lavoro. Esso vi permette di eseguire lavori in parallelo, di bilanciare il carico di lavoro ed eseguire funzioni tra linguaggi diversi. Può essere utilizzato per una varietà di applicazioni, da siti Web con alta disponibilità a trasporto di eventi di replicazione database. In altre parole, è il sistema nervoso per la comunicazione distribuita fra processi.
Inoltre, sviluppare clients e workers per Gearman in PHP è molto semplice, come mostrato in questo esempio nella documentazione PHP di Gearman.
D’altra parte, come scritto sulla homepage di Supervisor:
Supervisor, è un sistema client/server che permette ai suoi utenti di monitorare e controllare un gran numero di processi su sistemi operativi derivati da UNIX.
In pratica, la combinazione di Gearman e Supervisor crea una infrastruttura stabile, flessibile e scalabile per gestire i nostri jobs. Come mostrato nel seguente schema, essa ci fornisce una struttura client/server e si occupa della comunicazione e (volendo) della distribuzione. Noi dobbiamo solo aver cura di scrivere il codice per eseguire le nostre operazioni.
Installazione
Sto per mostrare come installare e configurare Gearman e Supervisor in ambiente debian wheezy.
Normalmente, i seguenti pacchetti dovrebbero essere già presenti in un sistema configurato per il PHP, ma giusto per essere sicuri, lanciamo:
$ apt-get install apache2 php5 libapache2-mod-php5 php5-dev
Ora siamo pronti per iniziare l’installazione di Gearman. I comandi necessari sono i seguenti:
$ apt-get install gearman-job-server libgearman-dev
A questo punto dobbiamo installare l’estensione Pecl per Gearman per poter utilizzare le classi PHP necessarie. In un mondo perfetto, noi dovremmo semplicemente installare l’ultima versione, ma (al momento) la versione stabile di Gearman Pecl richiede una versione di libgearman più nuova di quella presente nei repository di debian e, se provassimo ad installarla, dovremmo ricevere un errore simile al seguente:
configure: error: libgearman version 1.1.0 or later required
ERROR: `/tmp/pear/temp/gearman/configure' failed
Per risolvere questo problema, potremmo compilare e installare noi stessi libgearman, oppure, come preferisco io, installare una versione più vecchia di estensione Pecl lanciando i seguenti comandi:
$ apt-get install php-pear
$ pecl install gearman-1.0.3
Nota: se preferite compilare voi libgearman, potete facilmente trovare il modo cercando su Google.
Per completare l’installazione, i seguenti comandi attivano l’estensione Gearman per Apache2:
$ echo "extension=gearman.so" > /etc/php5/conf.d/gearman.ini
$ service apache2 restart
A questo punto, siamo pronti per creare i nostri client e worker per Gearman come mostrato nella sezione Gearman della documentazione PHP.
Ma noi non siamo ancora soddisfatti: noi vogliamo anche poter gestire i nostri processi in modo intelligente. Vogliamo poterli controllare, monitorarli e specificare dettagli come: numero di istanze, priorità, ecc. In pratica, vogliamo eseguirli attraverso Supervisor.
Quindi installiamolo:
$ apt-get install supervisor
In debian, supervisor è un demone di sistema e può essere avviato e fermato usando i soliti comandi:
$ service supervisor start
$ service supervisor stop
L’ultimo passo è configurare i nostri workers di Gearman in Supervisor. Per farlo, creeremo dei file in /etc/supervisor/conf.d/ che conterranno una configurazione simile a questa:
/etc/supervisor/conf.d/myprocess.conf:
[program:myprocess]
command=php /path/to/project/myprocess.php
numprocs=12
directory=/path/to/project/spool/myprocess/
autostart=true
autorestart=true
stdout_logfile=/path/to/project/log/myprocess.log
stdout_logfile_maxbytes=1MB
stderr_logfile=/path/to/project/log/myprocess.log
stderr_logfile_maxbytes=1MB
Per la lista completa delle opzioni, fare riferimento alla documentazione di Supervisor.
Riferimenti:
See also
- How to setup Docker container with legacy PHP 5.6 and Xdebug
- Split, reduce and convert PDF to JPEG using PHP ImageMagick
- Quickly setup HTTPS on PHP Apache2 Docker container with self-signed SSL certificate
- Building ZF3 composed pages using Nesting View Models and Forward Controller Plugin
- How to inject Zend Service Manager in ZF3 Controllers