Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Cerca un emulatore per Cloud Tasks?

By Joshua FoxAug 10, 20205 min read

Questa pagina è disponibile anche in English, Deutsch, Español, Français, 日本語 e Português.

Un emulatore di Tasks semplice, pensato per rendere immediati deployment e debug.

Quando si sviluppa un'applicazione che usa Cloud Tasks (per esempio una web app), è fondamentale poter osservare ciò che accade ai propri Tasks: come vengono pianificati, recapitati ed elaborati dal task handler. Eppure, nonostante sia una funzionalità spesso richiesta, Google non mette a disposizione alcun emulatore per lo sviluppo con Cloud Tasks, paragonabile a quelli offerti per Datastore o PubSub.

Il mio nuovo Cloud Tasks In-Process Emulator in Python risponde proprio a questa esigenza. Se non vede l'ora di provarlo, vada direttamente alla sezione "Quick Start" qui sotto.

Come sviluppare con Cloud Tasks

Le opzioni a disposizione sono quattro:

  1. Usare il servizio Cloud Tasks reale.
  2. Usare un emulatore in localhost che espone la stessa interfaccia HTTP di Cloud Tasks.
  3. Saltare il problema: ignorare la gestione dei task. Si può lasciare che la creazione dei task fallisca silenziosamente, oppure inviare task senza alcun handler definito.
  4. Usare un emulatore in-process. Lo si inietta in fase di sviluppo, mentre nei sistemi in produzione si ricorre a un'implementazione basata su Cloud Tasks.

Il mio consiglio è:

  • Un emulatore in-process per lo sviluppo
  • Cloud Tasks reale per i test di integrazione nel cloud
  • Escludere Cloud Tasks dagli unit test.

Vediamo perché.

I vantaggi dell'approccio in-process

Debugging

In fase di sviluppo è importante sapere dove si trova ciascun task e cosa contiene. Quando l'emulatore è in-process, può farlo direttamente con il debugger, mettendo in pausa la coda e ispezionando i valori.

La semplicità paga

Il codice di questo emulatore è volutamente essenziale: supporta solo la creazione e la gestione dei task. È una scelta deliberata: una codebase più snella (in questo caso, meno di 100 righe) è preferibile in fase di debugging.

Inoltre, con un prodotto in alpha — e tutti gli emulatori per Cloud Tasks, incluso questo, sono in alpha — è preferibile mantenere tutto il codice sotto il proprio diretto controllo, così da poterlo debuggare e all'occorrenza modificare rapidamente.

Per funzionalità più complete e test più realistici, mi affiderei al Cloud Tasks reale, in un'applicazione cloud-native deployata.

Facilità d'uso

Altri emulatori per Cloud Tasks, come gcloud-tasks-emulator di Potato London e cloud-tasks-emulator di Aert van de Hulsbeek, girano in localhost e hanno il vantaggio di esporre la stessa API del servizio cloud: basta cambiare l'endpoint. Questi emulatori, inoltre, possono essere richiamati da codice scritto in qualunque linguaggio, cosa che non è possibile con l'emulatore in-process.

D'altro canto, comportano l'onere aggiuntivo di un processo separato: avviarlo prima di ogni sessione di sviluppo e tenere d'occhio se è andato in crash o si è bloccato. E sebbene si possano debuggare avviandoli in un debugger, questa difficilmente sarà parte del flusso di sviluppo principale.

Non perda i suoi Tasks

Si può scegliere di inviare i task a Cloud Tasks senza poi gestirli, oppure di lasciar fallire silenziosamente la loro creazione. È una soluzione che funziona bene se il flusso di sviluppo principale non prevede la gestione dei task: per esempio, quando vengono gestiti in un microservizio separato, sotto la responsabilità di un altro team. Funziona bene anche per gli unit test, che in genere non vengono usati per testare processi distribuiti asincroni: quello è il ruolo dei test di integrazione.

Ma se vuole vedere davvero cosa accade ai suoi task e come la callback li elabora, le serve una qualche forma di emulatore.

Sviluppare con o senza il Cloud

Per un flusso end-to-end completo, può anche utilizzare il Cloud Tasks reale dalla sua macchina di sviluppo, ottenendo la stessa API e le stesse funzionalità del sistema in produzione. È un approccio che funziona bene per i test di integrazione eseguiti nel cloud.

Se però sceglie questa strada sulla macchina di sviluppo, dovrà avere sempre una connessione di rete attiva e configurare un proxy come ngrok per consentire a Google Cloud Platform di raggiungere la sua macchina locale (come descritto qui). Usare l'API reale di Cloud Tasks richiede inoltre code reali: significa che le servirà un proprio progetto Google Cloud, oppure dovrà gestire le code in modo che ogni sviluppatore abbia il proprio set.

Vuol dire anche che il debug anche di un semplice processo sulla macchina di sviluppo la costringe a passare dalla Cloud Console per ottenere maggiori informazioni. Personalmente, preferisco evitare quella configurazione e tenere il debugging all'interno del mio processo.

Funzionalità e limiti

Questo progetto supporta le funzionalità tipicamente usate in fase di sviluppo: creare un task e poi gestirlo in una callback.

Tuttavia, per la già citata predilezione per la semplicità, non supporta altre funzionalità, come:

  • Gestione delle code, inclusa la creazione, eliminazione, svuotamento, sospensione e ripresa. (Quando si crea un task, la coda viene creata automaticamente, se non è già presente.)
  • Rate-limit e retry.
  • Deduplicazione ed eliminazione dei task.

Se desidera nuove funzionalità (e se sono abbastanza semplici da giustificare la complessità aggiunta), apra pure Pull Request o Issue su GitHub.

Quick Start

Per utilizzare questo emulatore, basta copiare emulator.py nella propria codebase — può anche fare semplicemente copia/incolla del codice del file direttamente da GitHub — ed è pronto a partire.

Crei un oggetto Emulator e gli passi una funzione di callback, che riceverà i payload dei task creati. Poi, per inviare i task, richiami il metodo Emulator.create_task. Può scegliere sia il nome della coda sia l'orario di consegna pianificato.

Esempio d'uso

Nel progetto può vedere emulator.py all'opera all'interno di una semplice webapp. La avvii eseguendo local_server.py. Poi apra il browser su http://127.0.0.1:8080 (oppure clicchi sul link che vedrà nella console) e verrà creato un task. Il task verrà gestito (stampato sullo standard output), come pianificato, tre secondi più tardi.

Se è un purista dell'igiene del codice e preferisce mantenere la codebase di produzione libera dall'emulatore — escludendo emulator.py dal deployment — questo esempio le mostra come fare. In local_server.py, usato in sviluppo, iniettiamo un Emulator. Al contrario, in un server deployato, dove nessun Emulator viene iniettato, viene istanziato un nuovo CloudTasksAccessor che invoca l'API reale di Cloud Tasks, lasciando così il codice del server (main.py) libero da qualsiasi codice dell'emulatore.