Guía de actualización 1.5

Haga una copia de seguridad antes de actualizar y ejecute el siguiente comando para actualizar
composer require workerman/webman-framework ^1.5 -W && composer require webman/console ^1.2.12 && php webman install

Características y cambios

Soporta la corutina de Workerman v5

Nota
Workerman v5 requiere PHP>=8.1
Comando de actualización de Workerman composer require workerman/workerman ^5.0.0 -W
La corutina Fiber requiere la instalación de composer require revolt/event-loop ^1.0.0

Ejemplos

Respuesta retrasada

<?php

namespace app\controller;

use support\Request;
use Workerman\Timer;

class TestController
{
    public function index(Request $request)
    {
        // Dormir durante 1.5 segundos
        Timer::sleep(1.5);
        return $request->getRemoteIp();
    }
}

Timer::sleep() es similar a la función sleep() incorporada de PHP, la diferencia es que Timer::sleep() no bloqueará el proceso

Realizar una solicitud HTTP

Nota
Se requiere la instalación de composer require workerman/http-client ^2.0.0

<?php

namespace app\controller;

use support\Request;
use Workerman\Http\Client;

class TestController
{
    public function index(Request $request)
    {
        static $client;
        $client = $client ?: new Client();
        $response = $client->get('http://ejemplo.com'); // Realizar una solicitud asincrónica de forma síncrona
        return $response->getBody()->getContents();
    }
}

De igual manera, la solicitud $client->get() no es bloqueante y puede utilizarse para manejar solicitudes HTTP de forma no bloqueante en webman, mejorando el rendimiento.

Para más información, consulta workerman/http-client

Añadir la clase support\Context

La clase support\Context se utiliza para almacenar datos relacionados con la solicitud, y cuando se completa la solicitud, los datos de contexto correspondientes se eliminarán automáticamente. Es decir, el ciclo de vida de los datos de contexto sigue el ciclo de vida de la solicitud.

Contaminación de variables globales

Se prohíbe en el entorno de la corutina almacenar información de estado relacionada con la solicitud en variables globales o estáticas, ya que esto podría provocar la contaminación de variables globales, por ejemplo

<?php

namespace app\controller;

use support\Request;
use Workerman\Timer;

class TestController
{
    protected static $name = '';

    public function index(Request $request)
    {
        static::$name = $request->get('name');
        Timer::sleep(5);
        return static::$name;
    }
}

Al configurar el número de procesos en 1, cuando realizamos dos solicitudes consecutivas
http://127.0.0.1:8787/test?name=lilei
http://127.0.0.1:8787/test?name=hanmeimei
Esperamos que los resultados de las dos solicitudes sean lilei y hanmeimei respectivamente, pero en realidad ambos devuelven hanmeimei.
Esto se debe a que la segunda solicitud sobrescribe la variable estática $name, y cuando la primera solicitud termina la espera, el retorno de la variable estática $name ya se ha convertido en hanmeimei.

El método correcto es utilizar Context para almacenar los datos del estado de la solicitud

<?php

namespace app\controller;

use support\Request;
use support\Context;
use Workerman\Timer;

class TestController
{
    public function index(Request $request)
    {
        Context::set('name', $request->get('name'));
        Timer::sleep(5);
        return Context::get('name');
    }
}

Las variables locales no causarán contaminación de datos

<?php

namespace app\controller;

use support\Request;
use support\Context;
use Workerman\Timer;

class TestController
{
    public function index(Request $request)
    {
        $name = $request->get('name');
        Timer::sleep(5);
        return $name;
    }
}

Debido a que $name es una variable local, las corutinas no pueden acceder entre sí a las variables locales, por lo que el uso de variables locales es seguro para la corutina.

Sobre las corutinas

Las corutinas no son una solución universal, introducirlas significa que hay que tener cuidado con la contaminación de las variables globales/estáticas, y es más complicado depurar errores en el entorno de la corutina que en la programación bloqueante.

La programación bloqueante en webman es lo suficientemente rápida. Según los datos de las últimas tres rondas de pruebas de carga de techempower.com, la programación bloqueante en webman con operaciones de base de datos supera en rendimiento a los marcos de trabajo web en Go, como gin y echo, aproximadamente en un 100%, y supera en rendimiento a los marcos de trabajo tradicionales como Laravel en casi un 40%.

Cuando la base de datos, Redis, etc. están en la red interna, es probable que el rendimiento en la programación bloqueante con múltiples procesos sea superior al de las corutinas, ya que cuando la base de datos, Redis, etc. son lo suficientemente rápidos, los costos de crear, planificar y destruir corutinas pueden ser mayores que los costos de cambio de procesos, por lo que la introducción de corutinas no necesariamente mejora significativamente el rendimiento.

Cuándo utilizar corutinas

Cuando hay acceso lento en la aplicación, como la necesidad de acceder a una API de terceros, se pueden utilizar llamadas HTTP asincrónicas workerman/http-client de forma corutinaria para mejorar la capacidad de concurrencia de la aplicación.