Gestire gli errori in applicazioni serverless

con AWS Step Functions e AWS Lambda

In questo tutorial, imparerai a utilizzare AWS Step Functions per gestire gli errori di runtime dei flussi di lavoro. AWS Step Functions è un servizio di orchestrazione serverless che consente di coordinare facilmente più funzioni Lambda in flussi di lavoro flessibili, di cui è semplice eseguire il debug, e facili da modificare. AWS Lambda è un servizio di elaborazione che consente di eseguire codice senza dover effettuare il provisioning né gestire server. 

Le funzioni Lambda possono talvolta non andare a buon fine, come quando viene sollevata un’eccezione non gestita, quando le funzioni sono in esecuzione per un tempo maggiore del timeout configurato o quando esauriscono la memoria. Scrivere e mantenere la logica di gestione degli errori in tutte le funzioni Lambda per gestire situazioni come il throttling API o i timeout dei socket può richiedere tempo ed è spesso complicato, specie per le applicazioni distribuite. Incorporare questo codice in ogni funzione Lambda crea dipendenze tra esse e può essere difficile mantenere tutte queste connessioni mentre le cose cambiano.

Per evitare il problema e per ridurre la quantità di codice per la gestione di errori che devi scrivere, puoi utilizzare AWS Step Functions per creare un flusso di lavoro serverless che supporti la gestione degli errori delle funzioni. Indipendentemente dal fatto che l'errore sia l'eccezione di una funzione creata dallo sviluppatore (ad es. file non trovato) o imprevisto (ad es. memoria non sufficiente), puoi configurare Step Functions affinché risponda con una logica condizionale in base al tipo di errore che si è verificato. Separando in questo modo la logica del flusso di lavoro dalla logica di business, puoi modificare il modo in cui il tuo flusso di lavoro risponde agli errori senza modificare la logica di business delle tue funzioni Lambda.

In questo tutorial, progetterai ed eseguirai un flusso di lavoro serverless utilizzando AWS Step Functions che gestiranno elegantemente questi errori. Imparerai a creare una funzione AWS Lambda che simula le chiamate a un’API RESTful e restituisce vari codici di risposta ed eccezioni. Quindi, utilizzerai AWS Step Functions per creare una macchina a stati con funzionalità Retry e Catch che risponda con logica diversa in base all’eccezione sollevata.

Questo tutorial richiede un account AWS

Non sono previsti costi aggiuntivi per l'utilizzo di AWS Step Functions o AWS Lambda. Le risorse create in questo tutorial sono idonee per il piano gratuito. 

Ulteriori informazioni sul piano gratuito >>


Fase 1. Creazione di una funzione Lambda per simulare un’API

In questa fase, creerai una funzione Lambda che simulerà alcune interazioni API di base. La funzione Lambda solleva eccezioni per simulare le risposte di un’API fittizia, in base al codice di errore che fornisci come input nel parametro dell’evento.


a.  Apri la Console di gestione AWS e tieni sotto mano questa guida dettagliata. Quando viene caricata la schermata, inserisci nome utente e password per iniziare. Quindi, digita Lambda nella barra di ricerca e seleziona Lambda per aprire la console di servizio.

(fai clic per ingrandire l'immagine)


b. Scegli Create a function (Crea una funzione).

(fai clic per ingrandire l'immagine)


c. Lascia selezionato Author from scratch (Crea da zero). Quindi, configura la funzione Lambda come segue:

Per Name (Nome), digita MockAPIFunction.
Per Runtime, scegli Python 3.6.
Per Role (Ruolo), seleziona Create custom role (Crea ruolo personalizzato).

Si apre una nuova finestra IAM. In Role name (Nome ruolo), mantieni lambda_basic_execution e fai clic su Allow (Consenti). Vieni riportato automaticamente alla console Lambda.

Fai clic su Create function (Crea funzione).

(fai clic per ingrandire l'immagine)


d. Nella schermata MockAPIFunction , scorri verso il basso fino alla sezione Function code (Codice funzione). In questo tutorial, imparerai a creare una funzione che utilizza il modello di programmazione per la creazione delle funzioni Lambda in Python. Nella finestra del codice, sostituisci tutto il codice con il codice seguente, quindi scegli Save (Salva).

class TooManyRequestsException(Exception): pass
class ServerUnavailableException(Exception): pass
class UnknownException(Exception): pass

def lambda_handler(event, context):
    statuscode = event["statuscode"]    
    if statuscode == "429":
        raise TooManyRequestsException('429 Too Many Requests')
    elif statuscode == "503":
        raise ServerUnavailableException('503 Server Unavailable')
    elif statuscode == "200":
        return '200 OK'
    else:
        raise UnknownException('Unknown error')

(fai clic per ingrandire l'immagine)


e. Una volta creata la funzione Lambda, scorri fino all’inizio della finestra e nota il relativo Amazon Resource Name (ARN) nell’angolo in alto a destra della pagina. Amazon Resource Names (ARNs) identifica in modo univoco le risorse AWS e ti consente di monitorare e utilizzare le voci e le policy AWS nei servizi AWS e nelle chiamate API. Quando devi fare riferimento a una risorsa specifica da Step Functions, serve un ARN.

(fai clic per ingrandire l'immagine)


Fase 2. Creazione di un ruolo AWS Identity and Access Management (IAM)

AWS Step Functions può eseguire codice e accedere ad altre risorse AWS (ad es. dati archiviati nei bucket Amazon S3). Per conservare la sicurezza, devi concedere l’accesso Step Functions a queste risorse utilizzando AWS Identity and Access Management (IAM).


a. In un’altra finestra del browser, spostati sulla Console di gestione AWS e digita IAM nella barra di ricerca. Fai clic su IAM per aprire la console del servizio.

(fai clic per ingrandire l'immagine)


b. Fai clic su Roles (Ruoli), quindi scegli Create Role (Crea ruolo).

(fai clic per ingrandire l'immagine)


c. In Seleziona il tipo di entità affidabile, in AWS service (servizio AWS), seleziona Step Functions dall’elenco, quindi scegli Next: Permissions (Successivo: Autorizzazioni).

(fai clic per ingrandire l'immagine)


d. Nella pagina Attach permissions policy (Collega policy autorizzazioni), scegli Next: Review (Successivo: Esamina).

 

(fai clic per ingrandire l'immagine)


e. Nella pagina Review (Esamina), digita step_functions_basic_execution per Role name (Nome ruolo) e fai clic su Create role (Crea ruolo).

(fai clic per ingrandire l'immagine)


f. Viene creato il nuovo ruolo IAM che viene visualizzato nell’elenco sotto al ruolo IAM per la tua funzione Lambda.

(fai clic per ingrandire l'immagine)


Fase 3. Crea una macchina a stati AWS Step Functions

Ora che hai creato la funzione Lambda semplice che simula la risposta API, puoi creare una macchina a stati Step Functions per chiamare la API e gestire le eccezioni.

In questa fase, utilizzerai la console Step Functions per creare una macchina a stati che utilizza uno stato Attività con un campo Retry e Catch per gestire i diversi codici di risposta API. Utilizzerai uno stato Attività per invocare la funzione Lambda API simulata, che restituirà il codice di stato API che hai fornito come input nella macchina a stati.


a. Apri la console AWS Step Functions. Nella pagina Creazione di una macchina a stati, seleziona Author from scratch (Crea da zero). Nella sezione Details (Dettagli), assegna alla tua macchina a stati il nome MyAPIStateMachine, quindi seleziona I will use an existing role (Utilizzerò un ruolo esistente).

(fai clic per ingrandire l'immagine)


b. Quindi, progetterai una macchina a stati che svolgerà diverse operazioni a seconda della risposta della tua API simulata. Se non è possibile raggiungere l’API, il flusso di lavoro riprova. I nuovi tentativi sono un metodo utile per affrontare errori temporanei. Il flusso di lavoro acquisisce anche eccezioni diverse sollevate dall’API simulata.

Sostituisci il contenuto della sezione State machine definition (Definizione macchina a stati) con il seguente codice:

{
  "Comment": "An example of using retry and catch to handle API responses",
  "StartAt": "Call API",
  "States": {
    "Call API": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
      "Next" : "OK",
      "Comment": "Catch a 429 (Too many requests) API exception, and resubmit the failed request in a rate-limiting fashion.",
      "Retry" : [ {
        "ErrorEquals": [ "TooManyRequestsException" ],
        "IntervalSeconds": 1,
        "MaxAttempts": 2
      } ],
      "Catch": [ 
        {
          "ErrorEquals": ["TooManyRequestsException"],
          "Next": "Wait and Try Later"
        }, {
          "ErrorEquals": ["ServerUnavailableException"],
          "Next": "Server Unavailable"
        }, {
          "ErrorEquals": ["States.ALL"],
          "Next": "Catch All"
        }
      ]
    },
    "Wait and Try Later": {
      "Type": "Wait",
      "Seconds" : 1,
      "Next" : "Change to 200"
    },
    "Server Unavailable": {
      "Type": "Fail",
      "Error":"ServerUnavailable",
      "Cause": "The server is currently unable to handle the request."
    },
    "Catch All": {
      "Type": "Fail",
      "Cause": "Unknown error!",
      "Error": "An error of unknown type occurred"
    },
    "Change to 200": {
      "Type": "Pass",
      "Result": {"statuscode" :"200"} ,
      "Next": "Call API"
    },
    "OK": {
      "Type": "Pass",
      "Result": "The request has succeeded.",
      "End": true
    }
  }
}

(fai clic per ingrandire l'immagine)


c. Trova la riga “Resource” nello stato dell’Attività “Call API” (riga 7). Per aggiornare questo ARN all’ARN della funzione Lambda API simulata appena creata, fai clic sul testo ARN e seleziona l’ARN dall’elenco.

(fai clic per ingrandire l'immagine)


d. Fai clic sul pulsante di aggiornamento accanto al pannello del flusso di lavoro visivo affinché Step Functions crei un diagramma per la macchina a stato che corrisponda al flusso di lavoro appena progettato. Dopo avere esaminato il flusso di lavoro visivo, fai clic su Create state machine (Crea macchina a stati).

(fai clic per ingrandire l'immagine)


Fase 4. Verifica il flusso di lavoro di gestione errori

Per verificare il flusso di lavoro di gestione errori, invocherai la macchina a stati per chiamare l’API simulata fornendo il codice di errore come input.


a. Fai clic su Start execution (Avvia esecuzione).

(fai clic per ingrandire l'immagine)


b. Viene visualizzata una nuova finestra di dialogo di esecuzione dove puoi inserire l’input per la macchina a stati. Interpreterai il ruolo dell’API e fornirai il codice di errore che vogliamo che l’API simulata restituisca. Sostituisci il testo esistente con il codice seguente, quindi scegli Start execution (Avvia esecuzione):

{
    "statuscode": "200"
}

(fai clic per ingrandire l'immagine)


c. Nella schermata Execution details (Dettagli esecuzione), fai clic su Input per vedere l'input fornito sulla macchina a stati. Quindi, fai clic su Output per visualizzare il risultato dell’esecuzione della macchina a stati. Puoi vedere che il flusso di lavoro ha interpretato lo statuscode 200 come una chiamata API andata a buon fine.

(fai clic per ingrandire l'immagine)


d. In Visual workflow (Flusso di lavoro visivo), puoi vedere il percorso di esecuzione di ogni esecuzione, visualizzata in verde nel flusso di lavoro. Fai clic sullo stato dell’Attività "Call API" ed espandi quindi i campi Input e Output nella schermata Step details (Dettagli fase).

Puoi vedere che questo stato dell’Attività ha invocato correttamente la funzione Lambda API simulata con l’input fornito e ha acquisito l’output di tale funzione Lambda, “200 OK”.

(fai clic per ingrandire l'immagine)


e. Quindi, fai clic sullo stato dell’Attività “OK” nel flusso di lavoro visivo. In Step details (Dettagli fase) puoi vedere che l’output della fase precedente (lo stato dell’Attività “Call API”) è stato passato come input a questa fase. Lo stato OK è uno stato Pass, che ha semplicemente passato il proprio input al proprio output, senza eseguire lavoro. Gli stati Pass sono utili nella creazione e nell’esecuzione del debug della macchine a stati.

(fai clic per ingrandire l'immagine)


Fase 5. Ispeziona l’esecuzione della macchina a stati


a. Scorri fino alla parte superiore della schermata Execution details (Dettagli esecuzione) e fai clic su MyAPIStateMachine.

(fai clic per ingrandire l'immagine)


b. Fai clic di nuovo su Start execution (Avvia esecuzione) e, questa volta, fornisci l’input seguente e fai clic su Start execution (Avvia esecuzione).

{
    "statuscode": "503"
}

(fai clic per ingrandire l'immagine)


c. Nella sezione Execution event history (Cronologia eventi di esecuzione), espandi ogni fase di esecuzione per confermare che il flusso di lavoro si sia comportato come previsto. Era previsto che questa esecuzione non andasse a buon fine, quindi non allarmarti. Noterai che:

  1. Step Functions hanno acquisito il tuo input
  2. Quell’input è stato passato allo stato dell’attività Call API
  3. Lo stato dell’attività Call API ha chiamato la MockAPIFunction utilizzando quell’input
  4. MockAPIFunction eseguita
  5. MockAPIFunction non riuscita con ServerUnavailableException
  6. L’istruzione Catch nello stato dell’attività Call API ha rilevato tale eccezione
  7. L’istruzione Catch non è andata a buon fine nel flusso di lavoro
  8. La macchina a stati ha completato la propria esecuzione

(fai clic per ingrandire l'immagine)


d. Quindi, simulerai un’eccezione 429. Scorri fino alla parte superiore della schermata Execution details (Dettagli esecuzione) e fai clic su MyAPIStateMachine. Fai clic su Start execution (Avvia esecuzione), fornisci l’input seguente e fai clic su Start execution (Avvia esecuzione):

{
    "statuscode": "429"
}

(fai clic per ingrandire l'immagine)


e. Ora ispezionerai il comportamento Retry del tuo flusso di lavoro. Nella sezione Execution event history (Cronologia eventi di esecuzione), espandi ogni fase di esecuzione ancora una volta per confermare che Step Functions ha tentato di chiamare la funzione MockAPILambda altre due volte, entrambe le quali non sono andate a buon fine. A quel punto, il flusso di lavoro è passato dallo stato Wait allo stato Try Later (mostrato nell’immagine a destra) nella speranza che l’API sia stata soltanto temporaneamente non reattiva.

Quindi, lo stato Wait ha adottato la forza bruta per modificare il codice di risposta in 200 e il tuo flusso di lavoro ha completato correttamente l’esecuzione. Probabilmente questo non sarebbe il modo in cui gestiresti un’eccezione 429 in un’applicazione reale ma cerchiamo di semplificare le cose ai fini del tutorial.

(fai clic per ingrandire l'immagine)


f. Esegui un’altra istanza del tuo flusso di lavoro e, questa volta, fornisci una risposta API casuale che non viene gestita dalla tua macchina a stati:

{
    "statuscode": "999"
}

Ispeziona di nuovo l’esecuzione utilizzando la Execution event history (Cronologia eventi di esecuzione). Al completamento, fai clic ancora una volta su MyAPIStateMachine. Nel riquadro Executions (Esecuzioni), puoi visualizzare la cronologia di tutte le esecuzioni del tuo flusso di lavoro e accedervi singolarmente, come preferisci.

(fai clic per ingrandire l'immagine)


Fase 6. Interruzione delle risorse

In questa fase interromperai le tue risorse relative ad AWS Step Functions e AWS Lambda.

Importante: l'interruzione delle risorse che non vengono utilizzate attivamente consente di ridurre i costi e costituisce una best practice. La mancata interruzione delle risorse potrebbe determinare costi non desiderati.


a. Nella parte superiore della finestra della console AWS Step Functions, fai clic su State machines (Macchine a stati).

(fai clic per ingrandire l'immagine)


b. Nella finestra State machines (Macchine a stati), fai clic su MyAPIStateMachine e seleziona Delete (Elimina). Conferma l'azione selezionando Delete state machine (Elimina macchina a stati) nella finestra di dialogo. La tua macchina a stati verrà eliminata entro uno o due minuti, dopo che Step Functions avrà confermato che qualsiasi esecuzione in corso è stata completata.

(fai clic per ingrandire l'immagine)


c. Successivamente, eliminerai le funzioni Lambda. Dal menu della console di gestione AWS, fai clic su Servizi e seleziona Lambda.

(fai clic per ingrandire l'immagine)


d. Nella schermata Functions (Funzioni), fai clic su MockAPIFunction, seleziona Actions (Azioni) e quindi Delete (Elimina). Conferma l'eliminazione facendo di nuovo clic su Delete (Elimina).

(fai clic per ingrandire l'immagine)


e. Infine, eliminerai i tuoi ruoli IAM. Dal menu della console di gestione AWS, fai clic su Servizi e seleziona IAM.

(fai clic per ingrandire l'immagine)


f. Seleziona entrambi i ruoli AEM creati per questo tutoria, quindi fai clic su Delete role (Elimina ruolo). Conferma l'eliminazione facendo clic su Sì, elimina sulla finestra di dialogo.


Ora, puoi disconnetterti dalla console di gestione AWS.

(fai clic per ingrandire l'immagine)


Complimenti!

Hai utilizzato AWS Step Functions e AWS Lambda per creare un flusso di lavoro di gestione degli errori per un’API di rete. Con AWS Lambda, puoi eseguire codice per qualsiasi tipo di applicazione o servizio di back-end, senza bisogno di amministrazione. Una volta caricato il codice, Lambda si prende carico delle azioni necessarie per eseguirlo e ricalibrarne le risorse con la massima disponibilità.

Unendo AWS Step Functions e AWS Lambda facilita l'orchestrazione delle funzioni di AWS Lambda per le applicazioni serverless. Step Functions consente di controllare i flussi di lavoro complessi utilizzando le funzioni Lambda senza l’applicazione sottostante per gestire e orchestrare lo stato. Puoi anche utilizzare Step Functions per l'orchestrazione di microservizi utilizzando risorse di calcolo quali Amazon EC2 e Amazon ECS.

Esplora AWS Step Functions