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 workermancomposer require workerman/workerman ^5.0.0 -W
La coroutine Fiber nécessite l'installation decomposer 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 decomposer 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.