Laravel es un framework fantástico para construir nuestras aplicaciones, pero a medida que los proyectos crecen, podemos llegar a generar un "cuello de botella". Aquí es donde entran en juego los microservicios, pequeñas aplicaciones independientes que se encargar de una funcionalidad específica.
Para poder usar los microservicios, necesitamos un bus de mensajería, un sistema que permita la conexión entre nuestra aplicación y el microservicio sin estar directamente acoplados. En este caso usaremos RabbitMQ.
Arquitectura
La arquitectura básica que usaremos será la siguiente:
Un servicio envía un mensaje cuando ocurre algo en nuestra aplicación, RabbitMQ recibe y encola el mensaje, el microservicio escucha la cola de y procesa el mensaje.
Configuración de RabbitMQ
Para configurar RabbitMQ haremos uso de Docker:
# docker-compose.yaml
version: '3'
services:
rabbitmq:
image: rabbitmq:3-managment
ports:
- "5672:5672"
- "15672:15672Luego levantamos nuestra máquina docker:
docker compose up -dAbrimos el panel de administración de RabbitMQ en http://localhost:15672 con usuario guest y contraseña guest.
Una vez logueados veremos lo siguiente:
Configurando nuestro Servicio
En el primer microservicio, instalaremos la librería para manejar AMQP:
composer require php-amqplib/php-amqplibA continuación crearemos un servicio para publicar mensajes a RabbitMQ:
<?php
namespace App\Services;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
class RabbitMQService
{
public function publish(string $queue, array $data): void
{
$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();
$channel->queue_declare($queue, false, false, false, false);
$msg = new AMQPMessage(json_encode($data));
$channel->basic_publish($msg, '', $queue);
$channel->close();
$connection->close();
}
}Luego, en un controlador, incorporamos lo siguiente:
use App\Services\RabbitMQService;
public function register(Request $request, RabbitMQService $rabbit)
{
// Aquí el contenido de nuestro controllador, por ejemplo el registro de un usuario
$rabbit->publish('notifications', [
'user_id' => 1,
'message' => '¡Bienvenido a la plataforma!'
]);
return response()->json(['status' => 'User created']);
}
Una vez realizado esto, tenemos nuestro primer microservicio configurado.
Configurando el Consumidor
Crearemos otro microservicio, en este caso el consumidor de estas notificaciones que hemos enviado a RabbitMQ. Debemos instalar la misma librería que instalamos en el primer microservicio:
composer require php-amqplib/php-amqplibCreamos un comando para escuchar la cola:
php artisan make:command ConsumeNotificationsUna vez creado, procedemos a editar el comando:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use PhpAmqpLib\Connection\AMQPStreamConnection;
class ConsumeNotifications extends Command
{
protected $signature = 'rabbitmq:consume';
protected $description = 'Consume messages from RabbitMQ';
public function handle()
{
$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();
$channel->queue_declare('notifications', false, false, false, false);
$callback = function ($msg) {
$data = json_decode($msg->body, true);
$this->info("Notificación recibida: {$data['message']}");
};
$channel->basic_consume('notifications', '', false, true, false, false, $callback);
while ($channel->is_consuming()) {
$channel->wait();
}
$channel->close();
$connection->close();
}
}Con esto ya estaría toda la configuración realizada, tan solo nos falta probar que todo funcione.
Probando nuestros Microservicios y RabbitMQ
Debemos ejecutar la función del controlador que dispara el proceso de RabbitMQ, en este caso el registro de un usuario. Una vez lo hayamos lanzado, en nuestro panel de RabbitMQ debemos ver lo siguiente en la sección de Connections:
Luego, en nuestro segundo microservicio, ejecutamos lo siguiente:
php artisan rabbitmq:consumeSi todo ha ido bien debemos recibir el siguiente mensaje en nuestra terminal:
Notificación recibida: ¡Bienvenido a la plataforma!
Conclusión
Gracias a la integración de microservicios y RabbitMQ podemos tener una comunicación asíncrona entre microservicios en nuestras aplicaciones Laravel, permitiéndonos un desacoplamiento de servicios y con ello aumentar la escalabilidad de nuestros proyectos.