Vai al contenuto

Creare API HTTP Asincrone con Azure Container Apps

Scopri come implementare API HTTP efficienti e scalabili utilizzando Azure Container Apps.

Quando si sviluppano API HTTP, si è spesso tentati di gestire operazioni lunghe in modo sincrono direttamente nel gestore delle richieste. Tuttavia, questa pratica può portare a risposte lente, timeout e risorse esaurite. Gli utenti rischiano di non conoscere l’esito dell’operazione se la connessione viene interrotta o se la richiesta scade. In particolare, per i compiti gravosi a livello CPU, ciò può paralizzare il server, rendendolo poco reattivo a nuove richieste.

In questo articolo, esploreremo come costruire un API HTTP asincrona sfruttando le funzionalità di Azure Container Apps. Presenteremo un semplice API che segue il pattern di Richiesta-Risposta Asincrona, con l’applicazione ospitata all’interno di un contenitore e l’elaborazione asincrona gestita tramite un job. Questo approccio offre una soluzione decisamente più robusta e scalabile per la gestione di operazioni prolungate.

API LUNGHE IN AZURE CONTAINER APPS

Azure Container Apps è una piattaforma serverless ottimale per ospitare diverse tipologie di workload, comprese le API HTTP. Proprio come altre piattaforme serverless e PaaS, Azure Container Apps è progettata per elaborare richieste transitorie – i suoi ingressi attualmente hanno un timeout massimo di 4 minuti. Essendo una piattaforma che scala automaticamente, è in grado di adattarsi dinamicamente al numero di richieste in entrata, ma se un replica che gestisce una richiesta viene rimossa, operazioni lunghe possono terminare bruscamente.

JOBS IN AZURE CONTAINER APPS

In Azure Container Apps ci sono due tipi di risorse: le app e i jobs. Le app sono servizi a lungo termine che rispondono a richieste HTTP o eventi, mentre i jobs sono attività che vengono eseguite fino al termine e possono essere attivate tramite un programma o un evento.

I jobs possono anche essere avviati in modo programmatico, rendendoli una scelta ideale per implementare processi asincroni nelle API HTTP. Quando viene ricevuta una richiesta, l’API può avviare un job per elaborare l’operazione e restituire immediatamente una risposta. Il job, quindi, può terminare quando necessario e il cliente può interrogare un endpoint di stato per verificare il completamento del job e ottenere il risultato.

IL PATTTERN DI RICHIESTA-RISPOSTA ASINCRONA

Il pattern di Richiesta-Risposta Asincrona è una prassi comune per gestire operazioni lunghe nelle API HTTP. Invece di aspettare il completamento dell’operazione, l’API restituisce un codice di stato che indica che l’operazione è stata avviata. Il cliente può quindi interrogare l’API per verificare se l’operazione è terminata.

Il pattern applicato a Azure Container Apps si sviluppa come segue:

  • Il cliente invia una richiesta all’API (ospitata come app contenitore) per avviare l’operazione.
  • L’API memorizza la richiesta (nel nostro esempio utilizziamo Azure Cosmos DB), inizia un job per elaborare l’operazione e restituisce un 202 Accepted con un header di Location puntato a un endpoint di stato.
  • Il cliente interroga l’endpoint di stato. Durante l’operazione, l’endpoint restituisce un 200 OK con un header Retry-After che indica quando il cliente dovrebbe interrogare nuovamente.
  • Al termine dell’operazione, l’endpoint restituisce un 303 See Other con un header Location che punta al risultato. Il cliente seguirà automaticamente il reindirizzamento per ottenere il risultato.

APP API ASYNC

Il codice sorgente può essere trovato in questo repository GitHub.

L’API è un semplice app Node.js che utilizza Fastify. Mostra come costruire un API HTTP asincrona che accetta ordini e delega l’elaborazione a jobs.

POST /ORDERS

Questo endpoint accetta un ordine nel corpo della richiesta, salva l’ordine in Cosmos DB con uno stato di “pendente” e avvia l’esecuzione di un job per elaborare l’ordine.

fastify.post('/orders', async (request, reply) => {    const orderId = randomUUID()    // salva l'ordine in Cosmos DB    await container.items.create({        id: orderId,        status: 'pending',        order: request.body,    })    // inizia l'esecuzione del job    await startProcessorJobExecution(orderId)    // restituisce 202 Accepted con header Location    reply.code(202).header('Location', '/orders/status/' + orderId).send()})

In questo snippet il startProcessorJobExecution è una funzione che avvia il job di elaborazione utilizzando l’SDK di gestione di Azure Container Apps.

GET /ORDERS/STATUS/:ORDERID

Questo endpoint restituisce il codice di stato 202 con un header Location puntato a questo endpoint di stato. Il cliente può interrogare questo endpoint per controllare lo stato dell’ordine.

GET /ORDERS/:ORDERID

Questo endpoint restituisce il risultato dell’elaborazione dell’ordine. Se l’operazione è completata, l’endpoint di stato reindirizza qui per ottenere il risultato finale.

JOB DI ELABORAZIONE ORDINI

Il job di elaborazione degli ordini è anch’esso un’app Node.js che, in questa demo, attende un periodo prima di aggiornare lo stato dell’ordine in Cosmos DB. In uno scenario reale, il job elaborerebbe l’ordine, aggiornerebbe il suo stato e potrebbe inviare una notifica.

Le potenzialità di Azure Container Apps, combinate con l’architettura asincrona, rendono l’implementazione di servizi API sicuri e scalabili un processo altamente efficace.