Guida all'aggiornamento 1.5

Effettuare il backup prima dell'aggiornamento e eseguire i seguenti comandi
composer require workerman/webman-framework ^1.5 -W && composer require webman/console ^1.2.12 && php webman install

Funzionalità e Cambiamenti

Supporto per workerman v5Coroutine

Nota
workerman v5 richiede PHP>=8.1
Comando di aggiornamento workerman composer require workerman/workerman ^5.0.0 -W
La Coroutine richiede l'installazione di composer require revolt/event-loop ^1.0.0

Esempi

Risposta ritardata

<?php

namespace app\controller;

use support\Request;
use Workerman\Timer;

class TestController
{
    public function index(Request $request)
    {
        // Dormire per 1.5 secondi
        Timer::sleep(1.5);
        return $request->getRemoteIp();
    }
}

Timer::sleep() è simile alla funzione sleep() integrata di PHP, ma non blocca il processo.

Inviare richieste HTTP

Nota
È necessario installare 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'); // Invia una richiesta asincrona in modo sincrono
        return $response->getBody()->getContents();
    }
}

Anche la richiesta $client->get() è non bloccante, ciò è utile per gestire le richieste http in modo non bloccante in webman, migliorando le prestazioni.

Per ulteriori informazioni, consulta workerman/http-client

Aggiunta di supporto per la classe support\Context

La classe support\Context è utilizzata per memorizzare i dati correlati alla richiesta e vengono automaticamente eliminati una volta completata la richiesta. In altre parole, il ciclo di vita dei dati del contesto segue il ciclo di vita della richiesta.

Inquinamento delle variabili globali

L'ambiente della Coroutine vieta di memorizzare le informazioni sullo stato relativo alla richiesta in variabili globali o statiche, poiché ciò potrebbe causare un inquinamento delle variabili globali, ad esempio

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

Impostando il numero di processi su 1, quando si avviano due richieste consecutive
http://127.0.0.1:8787/test?name=lilei
http://127.0.0.1:8787/test?name=hanmeimei
Ci aspetteremmo che i risultati restituiti dalle due richieste siano rispettivamente lilei e hanmeimei, ma in realtà entrambi restituiscono hanmeimei.
Questo perché la seconda richiesta sovrascrive la variabile statica $name e quando la prima richiesta termina il sonno, il valore restituito dalla variabile statica $name è già diventato hanmeimei.

Il modo corretto è memorizzare i dati di stato della richiesta utilizzando il contesto

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

Le variabili locali non causano inquinamento dei dati

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

Poiché $name è una variabile locale, non c'è accesso concorrente tra le coroutine, quindi l'uso di variabili locali è sicuro nelle coroutine.

Riguardo alle Coroutine

Le coroutine non sono una soluzione miracolosa, l'introduzione delle coroutine comporta l'attenzione all'inquinamento delle variabili globali/variabili statiche e richiede la configurazione del contesto. Inoltre, il debug dei bug nell'ambiente delle coroutine è più complesso rispetto alla programmazione bloccante.

La programmazione bloccante all'interno di webman è già abbastanza veloce, come dimostrato dai dati di stress test delle ultime tre serie su techempower.com, che indicano che webman con attività di database è quasi due volte più veloce dei framework web go come gin, echo, e quasi 40 volte più veloce dei framework tradizionali come laravel.

Quando il database, redis, e altri servizi sono all'interno della rete, la programmazione bloccante con più processi potrebbe spesso offrire prestazioni migliori delle coroutine. Questo è dovuto al fatto che, quando il database, redis e così via sono sufficientemente veloci, il costo di creare, programmare e distruggere coroutine potrebbe essere maggiore del costo di commutazione di processo, quindi introdurre le coroutine potrebbe non migliorare significativamente le prestazioni.

Quando usare le coroutine

Quando ci sono chiamate lente nel business, ad esempio, l'azienda deve accedere a una chiamata di terze parti, si può utilizzare workerman/http-client per effettuare chiamate HTTP asincrone tramite coroutine, aumentando la capacità di concorrenza dell'applicazione.