Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

AMPHP: Asynchronous Multitasking con PHP

AMPHP è un raccolta di librerie event-driven per PHP pensato per scrivere applicazioni concorrenti sfruttando le Fiber
AMPHP è un raccolta di librerie event-driven per PHP pensato per scrivere applicazioni concorrenti sfruttando le Fiber
Link copiato negli appunti

AMPHP è un raccolta di librerie event-driven per PHP pensato per scrivere applicazioni concorrenti sfruttando le Fiber (supportate da PHP 8.1 e versioni successive) e un sistema di I/O "non bloccante". Invece di lasciare un processo di PHP fermo ad aspettare rete o database, si possono avviare più operazioni I/O in parallelo e riprendere l'esecuzione quando i risultati sono pronti mantenendo uno stile di codice molto simile a quello sincrono.

Il vantaggio è quindi quello di portare anche in PHP un modello di esecuzione più vicino a ciò che si potrebbe ottenere con Node o Go, soprattutto per quanto riguarda la concorrenza I/O.

Perché utilizzare AMPHP

Quando si sviluppa un'applicazione che prevede dei progetti concorrenti, la maggior parte dei colli di bottiglia è legata all'I/O con chiamate HTTP verso API esterne, query di database, accesso a cache o Redis, upload e download, WebSocket e molto altro. AMPHP è particolarmente utile proprio in questi casi, ad esempio quando si devono effettuare due richieste HTTP concorrenti (non sequenziali) e poi combinare i risultati ottenuti. Altri casi d'uso tipici sono i WebSocket server e i chatbot.

Il pacchetto core del progetto è amphp/amp che mette a disposizione due primitive con un ruolo centrale. La prima è "Future" che è in pratica un contenitore per il risultato futuro di un'operazione asincrona. Concettualmente si tratta quindi di qualcosa di simile a una promise ma con un orientamento awaited senza catene di then.
La seconda primitiva può essere riassunta con il concetto di "Cancellazioni". Una modalità standard con cui interrompere delle operazioni pendenti, ad esempio timeout, abort di una request, un ordine di shutdown e non solo.

La concorrenza viene orchestrata da un event loop. Nelle versioni più recenti dell'ecosistema AMPHP l'event loop è gestito da Revolt mentre Amp rimane il layer di concorrenza per future, combinatori e cancellazioni.

Amp\async() e Future::await()

Con Amp\async() è possibile avviare una coroutine (praticamente una Fiber con il proprio call stack) e ottenere una Future. Quando si ha la necessità di ottenere un risultato non si deve fare altro che lanciare un ->await(). In questo caso particolare il vantaggio è che si può può scrivere del codice leggibile, lineare che però non blocca il processo a livello di I/O.

Un esempio potrebbe essere quello di richiamare più risorse HTTP in modo concorrente. Qui sotto abbiamo un esempio tipico basato su amphp/http-client che è un client HTTP asincrono su Revolt con supporto per HTTP/1 e HTTP/2, le connessioni persistenti e le richieste concorrenti.

require __DIR__ . '/vendor/autoload.php';
use Amp\Future;
use Amp\Http\Client\HttpClientBuilder;
use Amp\Http\Client\Request;

$http = HttpClientBuilder::buildDefault();
$uris = [
    'google' => 'https://www.google.com',
    'bing'   => 'https://www.bing.com',
];

$responses = Future\await(array_map(
    fn (string $uri) => Amp\async(fn () => $http->request(new Request($uri, 'HEAD'))),
    $uris
));
foreach ($responses as $name => $response) {
    printf("%s -> %d\n", $name, $response->getStatus());
}

Come è possibile notare, Future\await(...) è un combinatore che attende più future insieme e restituisce un array con gli stessi indici che sono presenti nell'input. Se per caso una delle operazioni dovesse fallire, l'eccezione "bucherà" il combinatore, un comportamento che è spesso desiderato quando i risultati sono tutti necessari.

Server, WebSocket, socket, sync e parallel in AMPHP

Oltre al supporto per la concorrenza AMPHP offre una serie di componenti per costruire servizi completi:

  • un HTTP server: un application server "non bloccante" con supporto HTTP/1.1 e HTTP/2, TLS, middleware, routing dinamico, file serving statico e molto altro. Diverse feature sono infatti disponibili tramite dei pacchetti separati dal core del progetto.
  • un client WebSocket: per consumare API realtime o implementare client di test, con connessioni ws:// e wss://.
  • Socket: un'astrazione per socket TCP, UDP e TLS in modalità non bloccante che può tornare utile quando si deve comunicare con protocolli custom o servizi non basati su protocollo HTTP.
  • Sync: delle primitive di sincronizzazione con cui tenere sotto controllo la complessità quando si ha un incremento della concorrenza.
  • Parallel: utile quando un problema non è legato all'I/O-bound ma alla CPU. amphp/parallel

Questo senza contare che si ha la possibilità di accedere a package per DNS, client per database specifici (MySQL, Postgres, Redis..), processi, cache e molto altro. Se si hanno già dei progetti basati su ReactPHP o altre librerie esistono poi degli adapter grazie ai quali scegliere di volta in volta la libreria migliore per ottenere il risultato desiderato.

Ti consigliamo anche