ReactPHP, máximo rendimiento, asíncrono y con servidor web embebido

2021-10-28 - Categorías: General / PHP

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.

2 respuestas a “ReactPHP, máximo rendimiento, asíncrono y con servidor web embebido”

  1. Jhon Fabio Cardona Martinez dice:

    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

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

 

© 2021 JnjSite.com - MIT license

Sitio hecho con WordPress, diseño y programación del tema por Jnj.