En el mundo PHP hay una serie de proyectos muy interesantes, alrededor de lo que se llama ReactPHP. Este post es un codekata sobre cómo empezar con esta herramienta de trabajo en Sistemas Distribuidos. Se trata de cómo crear proyectos a base de microservicios, encapsulando un servidor web HTTP de alto rendimiento construido 100% en PHP dentro de cada microproyecto.
Este servidor web HTTP no está en desarrollo, como reza su web, y ya se está usando en millones de instalaciones en producción.
La idea principal no es nueva. Simplemente se usan loops, los clásicos bucles infinitos, en los que se establecen y procesan peticiones asíncronas, siempre tratando de sacar el máximo rendimiento. El cuello de botella normalmente está en los input/output que se hacen a ficheros, red, etc.. entonces se alcanza su máximo rendimiento no procesando linealmente, sino asíncronamente cada petición en un mismo núcleo de procesador al 100%.
Este sistema se puede balancear y escalar horizontalmente de igual forma que cualquier otro sistema, pero más fácil porque ya tenemos el servidor web embebido. Se eliminan entonces intermediarios, que siempre van a tener un coste de computación.
Si a esto le unimos la velocidad de las últimas versiones de PHP7+ 8+, con la compilación JIT Just In Time, tenemos un cócktel muy pero que muy interesante. Empezamos con el codekata?¿
Aquí la web oficial para el que quiera curiosear:
https://reactphp.org/
Cómo empezar con ReactPHP
Lo primero entonces a indicar, es que simplemente se trata de unas librerías que podemos instalar con Composer. Así que podemos lanzar desde línea de comandos algo como lo siguiente:
composer require react/event-loop react/http
..si todo va bien tenemos que ver algo así:
Hola mundo con ReactPHP
Ahora el clásico hola mundo. Tal y como tenemos en la documentación oficial, algo refactorizado, quitando los objetos deprecated, quedaría como lo siguiente:
<?php
include __DIR__.'/../vendor/autoload.php';
$server = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) {
return new React\Http\Message\Response(
200,
array(
'Content-Type' => 'text/plain'
),
'Hola mundo!'
);
});
$socket = new React\Socket\SocketServer('127.0.0.1:8080');
$server->listen($socket);
echo "Server running at http://127.0.0.1:8080" . PHP_EOL;
Ya hasta aquí podemos lanzarlo desde línea de comandos haciendo:
..y accedemos a http://127.0.0.1:8080/ para ver por pantalla..
Hola mundo algo más elaborado
Por ver cómo sería crear algo más elaborado, en estos primeros pasos, no parece nada complicado. Por ejemplo para establecer una serie de endpoints sería bien simple:
<?php
include __DIR__.'/../vendor/autoload.php';
$server = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) {
$response = '';
switch ($request->getUri()->getPath()) {
case '/test1':
$response = 'test1';
break;
case '/test2':
$response = 'test2';
break;
case '/test3':
$response = 'test3';
break;
default:
$response = 'Hola mundo!';
break;
}
return new React\Http\Message\Response(
200,
[
'Content-Type' => 'text/plain',
],
$response
);
});
$socket = new React\Socket\SocketServer('127.0.0.1:8080');
$server->listen($socket);
echo 'Server running at http://127.0.0.1:8080'.PHP_EOL;
Con este código podremos recibir peticiones y procesarlas en:
- http://127.0.0.1:8080/test1
- http://127.0.0.1:8080/test2
- http://127.0.0.1:8080/test3
Si quisiéramos recibir los párametros de la query string lo podríamos hacer con:
$request->getUri()->getQuery()
Y así sucesivamente, el método de la petición está en:
$request->getMethod()
Me remito a la documentación oficial para el que quiera seguir. Se han implementado muchos proyectos interesantes sobre ReactPHP, construidos 100% en PHP, como servidores Redis, RabbitMQ, etc..
https://github.com/reactphp/react/wiki/Users
Probando el rendimiento con ApacheBench
Para esto podemos lanzarlo desde línea de comandos:
ab -n 1000000 -c 100 http://127.0.0.1:8080/
Si no lo tenemos instalado, en GNU/Linux podemos hacerlo así:
sudo apt install apache-utils
Para este millón de peticiones con una concurrencia de 100, podemos ver un núcleo corriendo al 100% siempre.
Los resultados son bien interesantes.
Este artículo me gusto, recién empiezo como a documentarme, pero no he podido ver algún tutorial en YouTube u otra plataforma donde se muestre este funcionamiento.
Me gustaría saber que tipo de servicios ofrece y cuál es el costo una llamada para hablar sobre el tema.
Muchas gracias
Hola Jhon.
Muchas gracias por dejar este comentario.
Creo que una buena forma de empezar es viendo los ejemplos que ofrecen en Github: https://github.com/reactphp
Saludos.