20140828

Com utilitzar les cues de missatges natives de UNIX amb PHP

Si mai us heu trobat el problema de registrar visualitzacions a objectes que teniu en base de dades però no voleu penalitzar el rendiment fent un UPDATE cada vegada que un usuari entra al detall d'aquest objecte, una manera molt fàcil de millorar el rendiment es fer servir cues de missatges. La pàgina de detall només registre el hit a la cua i després tenim un batch per anar processant els hits dels últims minuts.


En concret amb PHP la solució més simple es utilitzar les cues de sistema operatiu, es tant fàcil com:


Enviar visualitzacions d'ids a una cua:
// 12345 es el número de cua de procés, ha de ser un número que només utilitzem nosaltres per comunicar els diferents processos.
$queue=msg_get_queue(12345);
msg_send($queue, 1, $id);



Consumir la cua (ho farem en un cron, per tant si trobem el final de la cua sortim):


$queue = msg_get_queue(12345);
$msg_type = NULL;
$msg = NULL;
$max_msg_size = 512;
while (msg_receive($queue, 1, $msg_type, $max_msg_size, $msg))
{
  //do your business logic here and process this message!
  //finally, reset our msg vars for when we loop and run again
  $msg_type = NULL;
  $msg = NULL;
  // Si ja no tenim missatges deixem de processar
  $stats=msg_stat_queue($queue);
  if ($stats['msg_qnum']===0) break;
}



Una manera de veure els missatges que hi han a les cues es utilitzant la comanda de sistema ipcs, en concret:
ipcs -q


Pots sofisticar tant com vulguis la logica, pots jugar amb el $msg_type per enviar i consumir diferents tipus de missatges i el $msg pot ser qualsevol objecte (serialitzat automàticament).

Per provar si el teu sistema operatiu permet utilitzar les cues des de PHP pots fer servir aquest script de test:


echo "Creamos cola\n";
$queue=msg_get_queue(11111);
echo "Insertamos en cola\n";
msg_send($queue, 1, 'hola');
echo "Obtenemos estadisticas de la cola\n";
$stats=msg_stat_queue($queue);
print_r($stats);

echo "Obtenemos mensajes de la cola\n";
$msg_type = NULL;
$msg = NULL;
$max_msg_size = 512;
while (msg_receive($queue, 1, $msg_type, $max_msg_size, $msg)) 
{
echo "Message pulled from queue - $msg \n";
$stats=msg_stat_queue($queue);
//print_r($stats);
if ($stats['msg_qnum']===0) break;
}
echo "Finalizado\n";



La salida si todo es correcto debería ser:

------------
Creamos cola
Insertamos en cola
Obtenemos estadisticas de la cola
Array
(
    [msg_perm.uid] => 0
    [msg_perm.gid] => 0
    [msg_perm.mode] => 438
    [msg_stime] => 1409301612
    [msg_rtime] => 0
    [msg_ctime] => 1409301612
    [msg_qnum] => 1
    [msg_qbytes] => 16384
    [msg_lspid] => 48299
    [msg_lrpid] => 0
)
Obtenemos mensajes de la cola
Message pulled from queue - hola
Finalizado
-----------


Més informació:
Comanda ipcs
Tutorial1
Tutorial2




Happy coding!