Guide de mise à niveau vers 1.5

Avant la mise à niveau, veuillez effectuer une sauvegarde et exécuter la commande de mise à niveau suivante :
composer require workerman/webman-framework ^1.5 -W && composer require webman/console ^1.2.12 && php webman install

Fonctionnalités et modifications

Prise en charge de la coroutine de workerman v5

Remarque
workerman v5 nécessite PHP>=8.1
Commande de mise à niveau de workerman composer require workerman/workerman ^5.0.0 -W
La coroutine Fiber nécessite l'installation de composer require revolt/event-loop ^1.0.0

Exemples

Réponse différée

<?php

namespace app\controller;

use support\Request;
use Workerman\Timer;

class TestController
{
    public function index(Request $request)
    {
        // Dormir pendant 1,5 secondes
        Timer::sleep(1.5);
        return $request->getRemoteIp();
    }
}

Timer::sleep() est similaire à la fonction sleep() intégrée de PHP, la différence est que Timer::sleep() ne bloque pas le processus.

Envoi de requêtes HTTP

Remarque
Nécessite l'installation 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://example.com'); // Envoi de requête asynchrone de manière synchrone
        return $response->getBody()->getContents();
    }
}

De même, la demande $client->get() est non bloquante, cela peut être utilisé pour traiter les requêtes HTTP de manière non bloquante dans webman, améliorant ainsi les performances.

Pour plus d'informations, voir workerman/http-client

Ajout de la classe support\Context

La classe support\Context est utilisée pour stocker les données relatives à la requête. Lorsque la requête est terminée, les données de contexte correspondantes seront automatiquement supprimées. Autrement dit, la durée de vie des données de contexte suit la durée de vie de la requête.

Pollution des variables globales

L'environnement de la coroutine interdit de stocker les informations d'état liées à la requête dans des variables globales ou statiques, car cela pourrait entraîner une pollution des variables globales, par exemple :

<?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;
    }
}

En définissant le nombre de processus sur 1, lorsque nous envoyons deux requêtes consécutives :
http://127.0.0.1:8787/test?name=lilei
http://127.0.0.1:8787/test?name=hanmeimei
Nous nous attendons à ce que les résultats de ces deux requêtes soient respectivement lilei et hanmeimei, mais en réalité, ils sont tous les deux renvoyés comme hanmeimei.
Cela est dû au fait que la deuxième requête écrase la variable statique $name, et lorsque la première requête se termine après la pause, la variable statique $name est devenue hanmeimei.

La bonne pratique consiste à utiliser le stockage des données d'état de la requête dans le contexte

<?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');
    }
}

Les variables locales ne causeront pas de pollution des données

<?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;
    }
}

Parce que $name est une variable locale, les coroutines ne peuvent pas accéder aux variables locales les unes des autres, donc l'utilisation de variables locales est sûre pour les coroutines.

À propos des coroutines

Les coroutines ne sont pas une solution miracle, leur introduction signifie qu'il faut faire attention à la pollution des variables globales/statiques et qu'il faut définir le contexte.

De plus, déboguer les bugs dans un environnement de coroutine est un peu plus compliqué que la programmation bloquante.

La programmation bloquante avec webman est déjà assez rapide, selon les données récentes de techempower.com, sur les trois dernières années, les tests de performances montrent que webman avec des opérations de base de données bloquantes est presque deux fois plus performant que le framework web go, gin et echo, et presque 40 fois plus performant que le framework traditionnel laravel.

Lorsque la base de données, le Redis, etc., sont en réseau local, la performance de la programmation bloquante avec plusieurs processus peut souvent être supérieure à celle des coroutines. Cela est dû au fait que lorsque les bases de données, le Redis, etc., sont suffisamment rapides, le coût de création, de planification et de destruction des coroutines peut être plus élevé que le coût de commutation de processus, de sorte que l'introduction des coroutines ne permet pas nécessairement d'améliorer significativement les performances.

Quand utiliser des coroutines

Lorsque l'application a des accès lents, par exemple, lorsque des appels à des API tierces sont nécessaires, vous pouvez utiliser workerman/http-client pour effectuer des appels HTTP asynchrones sous forme de coroutine, améliorant ainsi la capacité concurrente de l'application.