Se ha mai dovuto affrontare un caso d'uso di data streaming sul cloud, con ogni probabilità ha aperto più schede del browser di quante vorrebbe ammettere mentre cercava di orientarsi tra le varie opzioni AWS disponibili e le loro, diciamolo, corpose FAQ.

Chi ha tempo di leggere cinquanta pagine di documentazione solo per capire quale servizio scegliere?
Di seguito sono elencati alcuni dei principali servizi AWS che si occupano di acquisire, trasformare, archiviare e analizzare dati in streaming. Quando leggerà questo articolo, l'elenco potrebbe non essere più esaustivo:
- Kinesis Data Streams
- Kinesis Firehose con integrazione Lambda opzionale
- Kinesis Data Analytics
- Managed Streaming for Apache Kafka (MSK)
- Spark Streaming con Elastic MapReduce (EMR)
- Glue Streaming ETL
- IoT Analytics all'interno di IoT Core
Se si sente frustrato o sta dedicando troppo tempo a decidere quale strada imboccare, continui a leggere: farò chiarezza illustrando i concetti fondamentali e il caso d'uso ideale di ciascun servizio.
In fondo all'articolo trova un breve riepilogo che indica quale scegliere a seconda delle circostanze.
Kinesis: la scelta predefinita
La proposta di punta di Amazon per il data streaming, e il servizio da considerare come opzione predefinita nella maggior parte dei casi d'uso, è Kinesis. All'interno di Kinesis, però, esistono diversi sotto-servizi dai nomi un po' criptici; i più rilevanti sono:
- Kinesis Data Streams (spesso indicato come Streams)
- Kinesis Firehose (o semplicemente Firehose)
- Kinesis Data Analytics (o semplicemente Analytics)
Vediamo nel dettaglio ciascuno di questi servizi.
Kinesis Data Streams vs. Kinesis Firehose
Streams vs. Firehose: panoramica delle funzionalità
Sia Data Streams sia Firehose acquisiscono dati e li riversano in un sink. Perché allora esistono due servizi distinti che sembrano svolgere la stessa funzione?
La differenza principale sta nel fatto che Streams è pensato per inviare dati a servizi di calcolo con consumer personalizzati — come applicazioni in esecuzione su EC2, EMR o Lambda — che gestiscono trasformazione ed elaborazione in near real-time con una latenza minima di circa 70 ms. Questo rende Streams particolarmente utile per dashboard in tempo reale, rilevamento di anomalie e altre applicazioni sensibili al fattore tempo. Streams si integra ottimamente con Apache Spark, semplificando la manipolazione dei dati in tempo reale tramite streaming Data Frames quando entrano in gioco analisi più complesse.
Firehose, al contrario, non è pensato per la consegna in near real-time. Aggrega in batch i messaggi in arrivo, eventualmente li comprime e/o li trasforma con AWS Lambda, quindi convoglia i dati, di solito verso un servizio AWS. Tipicamente si tratta di S3, Redshift o Elasticsearch.
Mentre i messaggi di Stream vengono solitamente consumati da applicazioni personalizzate, è anche possibile configurare Streams in modo che faccia confluire i dati in uno stream Firehose, abilitando così sia analisi in tempo reale sia il batching e l'archiviazione a lungo termine.
Se il suo caso d'uso non richiede elaborazione in near real-time, Firehose è probabilmente la scelta più indicata, oltre a essere più semplice da utilizzare direttamente.
Firehose: di solito la scelta migliore
Perché Firehose risulta la scelta più indicata tra questi due servizi?
In primo luogo: Kinesis Streams richiede uno sforzo di sviluppo più consistente, con programmi scritti tramite la sua Kinesis Producer Library (KPL) e Kinesis Consumer Library (KCL), entrambe orientate a Java. Firehose, al contrario, è progettato principalmente per riversare i dati in specifici servizi AWS, quindi non serve scrivere codice per il componente di sink. Anche pubblicare messaggi su Firehose è semplice:
import boto3firehose_client = boto3.client('firehose')
response = firehose_client.put_record(
DeliveryStreamName='string',
Record={'Data': b'bytes'} # base64-encoded
)
Se accetta che Kinesis Streams subisca probabilmente penalizzazioni di performance sia lato producer sia lato consumer, oltre a rinunciare ad altri vantaggi, può utilizzare gli AWS SDK per pubblicare messaggi in modo più semplice anziché impegnarsi in uno sviluppo più articolato basato su KPL:
import boto3kinesis_client = boto3.client('kinesis')
response = kinesis_client.put_record(
StreamName='string',
Data=b'bytes', # base64-encoded
PartitionKey='string'
)
In secondo luogo: sia Streams sia Firehose sono completamente gestiti e con auto-scaling, ma quello di Streams è un auto-scaling "più limitato" e non è del tutto serverless.
L'auto-scaling di Firehose consente di aumentare immediatamente e senza intoppi il throughput, passando dai test di sviluppo a GB di dati al secondo, sempre che non si superino i limiti AWS di throughput di Firehose.
Lo scaling di Streams è più articolato. Pur non gestendo direttamente l'infrastruttura sottostante, deve definire per uno stream Kinesis un numero di "shard" che si traduce nel throughput supportato dallo stream. Uno shard può corrispondere al massimo a 1 MB/s o 1.000 record/s di throughput in scrittura e 2 MB/s in lettura. Occorre quindi pre-provisionare una certa quantità di shard per supportare un dato livello di throughput. Può modificare manualmente il numero di shard di uno stream o impostare l'auto-scaling, sebbene quest'ultima procedura sia più macchinosa di quanto dovrebbe.
Quindi, per ottenere un throughput maggiore, si scala il numero di shard dello stream. C'è però un grosso caveat: in media, uno shard impiega circa 30 secondi per essere aggiunto o rimosso da uno stream, e si può aggiungere o rimuovere un solo shard alla volta.
Vediamo come può tradursi in un esempio concreto: con uno stream da 1.000 shard (~1 GiB/s di throughput in scrittura) e la previsione di dover raddoppiare il throughput nel prossimo futuro, ci vorrebbero oltre 8 ore perché lo stream scali completamente con altri 1.000 shard.
Se ha motivo di ritenere che un giorno potrebbe trovarsi davanti a un picco improvviso e imprevisto del volume di dati, Kinesis Data Streams non sarà in grado di scalare con la rapidità necessaria.
Tenendo presente questo, Streams non è adatto a casi d'uso con elevata variabilità del throughput in streaming, a meno che non sia disposto ad accettare l'over-provisioning e a pagare di più in tali occasioni, oppure se confida nella propria capacità di anticipare i picchi di scaling e pianificare di conseguenza. Firehose è semplicemente più facile da scalare, da sviluppare e, come vedremo a breve, da preventivare. Kinesis Streams andrebbe utilizzato solo quando sono richieste analisi in tempo reale.
Streams vs. Firehose: confronto sulla complessità del pricing
L'approccio serverless e con auto-scaling di Firehose al data streaming si traduce anche in uno schema di prezzi pay-as-you-go lineare basato su:
- GB di dati ingeriti al mese e, per i casi d'uso pertinenti:
- GB di conversioni di formato dati eseguite
- GB di dati consegnati a una VPC
Il pricing di Data Streams è più complesso da prevedere, dato che si basa su:
- Numero di shard-ora provisionati, che può variare con l'auto-scaling. Con ogni probabilità dovrà sovra-provisionare per garantire un uptime affidabile.
- Numero di payload PUT da 25 KB inviati
- Eventuali modifiche della retention dei dati a lungo termine
- Attivazione opzionale dell'enhanced fan-out, una funzionalità che migliora il throughput quando molti consumer leggono dallo stesso shard
Streams vs. Firehose: in sintesi
Se l'obiettivo è eseguire trasformazioni di base e il caricamento batch dei dati in streaming in un data store, e non ha esigenze di elaborazione in tempo reale, dovrebbe pubblicare i dati direttamente su Firehose. Scelga Firehose anche se vuole ridurre al minimo il tempo dedicato allo sviluppo applicativo o le preoccupazioni legate alla rapida scalabilità infrastrutturale.
Se deve elaborare i dati in tempo reale, li invii tramite Streams, ma sappia che, anche con l'auto-scaling abilitato, potrebbe non gestire abbastanza bene aumenti di throughput a picchi.
Se deve elaborare i dati in tempo reale e poi archiviarli per analisi successive, può inviarli prima a Streams e poi, dalla console web di Kinesis, configurare facilmente Streams per inoltrarli a Firehose senza scrivere codice (a meno che non desideri eseguire passaggi di trasformazione opzionali su Lambda).
Può essere utile pensare a Streams come funzionalmente simile ad Apache Kafka, ma con archiviazione persistente temporanea dei messaggi che possono essere inoltrati a numerosi consumer. I consumer possono essere applicazioni personalizzate (EC2 o EMR) o gestiti da AWS (Firehose). Firehose viene spesso considerato un batch loader per servizi specifici, di solito incentrati su AWS (S3, Redshift, Elasticsearch), con trasformazioni dati serverless opzionali alimentate da Lambda.
Kinesis Data Analytics: window analytics serverless
Streams e Firehose coprono piuttosto bene l'acquisizione, la trasformazione e il trasporto dei dati in streaming verso applicazioni di analisi in tempo reale (Streams) e sink di archiviazione a lungo termine (Firehose). Quale ruolo riveste, allora, Analytics?
Data Analytics, l'offerta Apache Flink completamente gestita e serverless di Amazon:
- Si integra con Data Streams o Firehose
- Esegue query SQL sui dati in streaming
- Invia i risultati a un servizio AWS, come un altro Data Stream, uno stream Firehose o Lambda
- Data Analytics può inoltre trattare file CSV o JSON statici presenti in S3 come tabelle SQL, abilitando JOIN tra dati di riferimento e dati in streaming.
Data Analytics viene utilizzato principalmente per calcolare in modo continuo aggregazioni di dati in streaming, arricchite con dati di riferimento statici, su finestre temporali — di solito a fini di alerting in tempo reale — senza alcun codice né infrastruttura provisionata, soltanto SQL lineare. Si potrebbe scrivere codice Flink e fare il deploy al posto di SQL, ma per facilità di manutenzione consiglio di restare su SQL, dato che Scala e Java sono meno utilizzati nel mondo della data science.
La documentazione AWS mostra un esempio di sliding window analytics con dati di quotazioni borsistiche, ma raccomando piuttosto di studiare questo esempio reale più interessante, in cui le velocità del traffico in tutto il Belgio vengono ingerite in uno stream Firehose, Data Analytics viene usato per confrontare velocità correnti e passate con l'ausilio di dati di riferimento in S3, la presenza di ingorghi viene determinata con SQL e gli alert in tempo reale vengono inviati con Lambda.
Managed Streaming for Apache Kafka (MSK)
Sia Kinesis Data Streams sia MSK, l'offerta gestita da AWS per Apache Kafka, sono efficaci sistemi "pub-sub" che consentono la pubblicazione e il consumo di messaggi con throughput elevato, bassa latenza, alta disponibilità e tolleranza ai guasti. In termini generali di scalabilità e affidabilità come piattaforma di ingestion e delivery dei dati, non c'è una grande differenza tra i due, almeno in superficie.
Ci sono però differenze critiche nei dettagli, e generalmente favoriscono Kinesis:
- È possibile soltanto aumentare il numero di message broker. Significa che non si può ridurre la scala di un deployment MSK.
- Sebbene MSK sia completamente gestito, non è Kafka serverless. MSK comporta quindi una certa configurazione del cluster: deve definire le zone e le subnet in cui avviare i broker, il numero di broker per zona, il tipo di istanza che li alimenta e così via.
- Dato che MSK non è serverless, paga anche lo storage basato su EBS che supporta le istanze. Anche questo non può essere ridotto.
- Non può cambiare il tipo di istanza dopo il setup iniziale del cluster. L'unica opzione per scalare verso l'alto è aumentare il numero di istanze.
- Kinesis è il servizio di streaming proprietario di AWS, completamente gestito e serverless, quindi avrà naturalmente una migliore integrazione con i servizi AWS. Alcuni consumer Kinesis possono essere collegati senza codice, mentre MSK richiede che tutte le applicazioni consumer siano sviluppate ad hoc, ad esempio su EC2, EKS, EMR oppure con codice Flink distribuito su Kinesis Data Analytics.
- In Kafka, all'interno di un dato "consumer group" può leggere da una partizione un solo consumer alla volta. Kinesis, invece, supporta più consumer per shard.
La configurazione iniziale e continua del cluster, unita all'impossibilità di ridurre la scala dei deployment, comporta un overhead di DevOps maggiore, sia nel breve sia nel lungo termine, con MSK rispetto a Kinesis.
Anche il pricing è diverso tra i due servizi e, ancora una volta, generalmente favorisce Kinesis.
Come accennato in precedenza, il pricing di Kinesis Data Streams è in larga parte on-demand. Si basa principalmente sul numero di payload PUT da 25 KB inviati e sul numero di shard-ora provisionati per abilitare il throughput PUT e GET desiderato. Il numero di shard può essere configurato per l'auto-scaling, simulando così un pricing on-demand, anche se l'implementazione è un po' macchinosa.
MSK, invece, viene fatturato in base al numero di istanze della dimensione scelta in esecuzione e alle dimensioni dei volumi EBS che le supportano. Né il numero di istanze né la dimensione dei volumi EBS possono essere ridotti; se sovra-provisiona, resta con il conto da pagare a meno che non termini il cluster. Lo storage può essere impostato per l'auto-scaling, ma le dimensioni e il numero di istanze no. Dovrà invece monitorare costantemente le metriche CloudWatch delle istanze, quante partizioni vengono utilizzate per broker e altri indicatori di performance, scalando poi il servizio manualmente. Per giunta, è "fortemente raccomandato" che l'utilizzo della CPU nel cluster resti sotto il 60%, quindi finirà inevitabilmente per pagare in eccesso la capacità di calcolo.
C'è un grosso vantaggio nell'uso di MSK: Kinesis offre la consegna at-least-once dei messaggi, mentre Kafka garantisce la consegna exactly-once. In generale, però, gestire la deduplicazione dei messaggi è molto più semplice rispetto alle sfide della scalabilità infrastrutturale a costi contenuti.
Anche se riuscisse a far funzionare un cluster MSK su scala molto elevata in modo cost-optimized, riuscendo a quotare il deployment a costi inferiori rispetto a Kinesis, scommetterei che risparmierebbe comunque di più con Kinesis grazie alle minori ore-uomo DevOps (e ai loro stipendi elevati) impiegate per mantenere operativo un servizio pub-sub business-critical, quando un equivalente completamente gestito avrebbe svolto lo stesso lavoro praticamente senza sforzo.
Personalmente raccomando AWS MSK soltanto alle aziende che hanno un'applicazione Kafka esistente che, per vincoli di tempo, costi di refactoring o risorse di personale, deve essere migrata in lift-and-shift senza modifiche architetturali.
Se desidera approfondire, le consiglio di leggere questa "honest AWS MSK review". Anche i commenti all'articolo sono interessanti e si concentrano su esempi di pricing MSK vs. Kinesis.
Spark Streaming con EMR
AWS EMR è l'offerta di Amazon completamente gestita e con auto-scaling (ma non serverless) che consente l'esecuzione basata su cluster di script scritti per strumenti open source di big data processing. Tra questi figura Apache Spark.
Spark abilita analisi basate su DataFrame eseguibili sia su dataset statici sia su dataset in streaming. Può eseguire analisi sui DataFrame con tipiche chiamate di funzione programmatiche oppure utilizzare Spark SQL, conforme ad ANSI SQL. Lavorare con Spark SQL su dati in streaming è simile a usare SQL con Apache Flink / Kinesis Data Analytics. Spark può prendere come fonte di ingestion in streaming monitorata Apache Kafka e Apache Flume, oltre ad AWS S3 e AWS Kinesis Data Streams.
Date le ottime integrazioni native di Spark con Streams e S3, oltre alla curva di apprendimento contenuta di PySpark, raccomando di utilizzare Spark Streaming con DataFrame su EMR quando occorre:
- Eseguire analisi in tempo reale su Kinesis Data Streams o S3
- Quando la scala o la complessità delle analisi supera alcune delle numerose limitazioni di Kinesis Data Analytics.
In particolare, deve essere consapevole che con Data Analytics:
- Nessuna riga di dati può superare i 512 KB. Il limite di Spark è molto più alto: 2 GB.
- Il dataset di riferimento non può superare 1 GB. Spark non ha questo limite.
- Ogni applicazione deve avere esattamente una sorgente di streaming e al massimo una sorgente di dati di riferimento. Con Spark può unire più sorgenti di streaming e più sorgenti statiche di dati di riferimento.
- Le query con finestra non dovrebbero superare i 60 minuti, poiché i dati sono memorizzati in storage volatile da cui lo stream può essere ricostruito in caso di interruzioni inattese dell'applicazione. Spark non ha limiti sulla finestra temporale.
Glue Streaming ETL
Glue Streaming è un'offerta Spark Streaming DataFrames completamente gestita, con auto-scaling e serverless. Lo userebbe quindi se ha esperienza con Spark e desidera eseguire trasformazioni e analisi personalizzate sui dati in streaming da Kinesis con questo servizio anziché con un cluster EMR auto-gestito o funzioni Lambda. Glue Streaming può convogliare verso i tipici sink di dati come S3, Redshift e DynamoDB.
Glue può, in una certa misura, generare automaticamente il codice Spark sulla base di un elenco di trasformazioni richieste nella console web, quindi non è strettamente necessaria una grande esperienza con Spark, anche se è utile padroneggiarne le basi.
Personalmente ho trovato questo servizio un po' ostico. Sebbene l'idea di Spark serverless sembri allettante, presenta alcune limitazioni:
- Quando si utilizza la rilevazione dello schema, non è possibile eseguire join su dati in streaming.
- Non si può modificare il numero di shard di Kinesis Streams mentre un job Glue Streaming ETL è in esecuzione. Bisogna fermare il job, modificare il numero di shard di Data Streams, attendere il completamento dell'operazione e quindi riavviare il job.
Solo per la scalabilità a monte, personalmente sceglierei di gestire un cluster Spark auto-gestito con auto-scaling abilitato piuttosto che Glue Streaming ETL, ma nei suoi test potrebbe scoprire che la natura serverless e con auto-scaling di Glue Streaming ETL ne compensa i contro.
IoT Analytics all'interno di IoT Core
Cosa facciano i componenti di IoT Analytics non è così trasparente come dovrebbe essere — al punto che ho scritto un intero articolo a riguardo! Production-Scale IoT Best Practices: Implementation with AWS (part 2). Qui vediamo l'essenziale e lasciamo molti dettagli a quell'articolo.
I dispositivi IoT che inviano dati in streaming ad AWS arrivano a IoT Core. Da qui, quei messaggi possono essere inoltrati ad altri servizi per analisi personalizzate. Ad esempio, con le IoT Rules può facilmente inoltrare i dati di IoT Core verso:
- DynamoDB
- Firehose, che a sua volta riversa i dati in DynamoDB, S3, Redshift o Elasticsearch
- Data Streams, che può inviare dati a EC2, EMR, Lambda o Firehose
Come può vedere, esiste un'ampia gamma di possibili dataflow IoT da configurare.
Tuttavia, se vuole elaborare tutti i suoi dati IoT — dallo streaming verso la piattaforma fino allo storage e all'analytics — interamente in una piattaforma unificata IoT-centrica completamente serverless, con auto-scaling e fully managed, e con molteplici integrazioni con altri servizi AWS come Sagemaker e Quicksight, allora la scelta giusta è IoT Analytics. IoT Core consente di elaborare i dati IoT all'interno di un singolo servizio, anziché mettere insieme più servizi.
Procedendo con il wizard di IoT Analytics si configura quanto segue:
- Un IoT Channel, dove arrivano i dati IoT
- Una IoT Pipeline, che prende i dati dal Channel e consente facoltativamente di arricchire, trasformare e filtrare i messaggi in base ai loro attributi
- Un IoT Data Store, dove i dati in streaming vengono archiviati, indefinitamente o per un periodo di tempo specificato. Dietro le quinte, questi dati sono memorizzati in un bucket S3 gestito da AWS.
- Un IoT Data Set può essere creato a partire da un Data Store. Si tratta di un sottoinsieme di un IoT Data Store creato con IoT SQL, dotato di un proprio periodo di retention e della capacità di rigenerarsi su richiesta o secondo una pianificazione ricorrente. Come i Data Store, i Data Set sono memorizzati come file CSV in un bucket gestito. I Data Set, in definitiva, le permettono di creare un dataset statico basato su un filtro personalizzato (ad esempio, selezionare tutti i dati di temperatura in un intervallo temporale ristretto ma interessante), generare quel dataset on-demand una sola volta e conservarlo indefinitamente per analisi a valle, mentre i messaggi grezzi del data store originale possono scadere secondo un periodo di retention ritenuto dalla sua organizzazione il più adatto a bilanciare la conservazione dei dati grezzi con l'efficienza dei costi.
- Alcuni servizi AWS che si integrano con IoT Analytics, come Quicksight, attingono solo dai data set, mentre altri come SageMaker possono attingere sia dai data store sia dai data set. In generale, tutti i servizi dovrebbero poter attingere dai data set. Data la connettività più limitata con i data store e le implicazioni di costo legate all'archiviazione indefinita dei dati grezzi in IoT Analytics, in un caso d'uso di produzione dovrebbe abituarsi alla metodologia di creare dataset filtrati e discreti da utilizzare in analytics o nella generazione di modelli ML, lasciando scadere nel tempo i data store grezzi, a meno che la sua organizzazione non ritenga accettabile pagare per l'archiviazione dell'intero storico dei dati IoT.
Quale servizio scegliere?
Nel tentativo di spiegare in modo conciso le varie opzioni di streaming AWS, temo di aver scritto troppo! Ecco un rapido riepilogo su quando scegliere ciascun servizio:
- Kinesis Data Streams: quando deve eseguire analisi in tempo reale su EC2, EMR o Lambda e non le pesano una certa complessità di sviluppo aggiuntiva e l'impossibilità di scalare rapidamente il throughput.
- Kinesis Firehose: quando deve aggregare in batch i dati in streaming, opzionalmente trasformarli e/o comprimerli e archiviarli a lungo termine su S3, Redshift o Elasticsearch. Quando desidera una piattaforma di ingestion di dati in streaming facile da usare, serverless e con auto-scaling immediato e non le importa che scriva i dati in batch anziché inviarli ai consumer in tempo reale.
- Kinesis Data Analytics: quando vuole eseguire analisi di base con finestre temporali su dati di Data Streams o Firehose, tipicamente per alerting in tempo reale, con SQL su una piattaforma semplice, serverless e con auto-scaling.
- Managed Streaming for Apache Kafka (MSK): quando ha un'applicazione esistente basata su Kafka e vuole effettuare un lift-and-shift su AWS. Vincoli di tempo o di risorse le impediscono di riprogettare l'applicazione per usare Kinesis.
- Spark Streaming con EMR: quando deve eseguire analisi avanzate con finestre temporali su Kinesis Data Streams tramite operazioni di JOIN che coinvolgono più sorgenti di streaming e/o dataset di riferimento statici.
- Glue Streaming ETL: simile a Spark Streaming con EMR, con la differenza che può eseguire workloads Spark in un ambiente serverless con auto-scaling. Non consente lo scaling a monte degli shard di Data Streams senza arrestare e riavviare i job di Glue Streaming connessi.
- IoT Analytics all'interno di IoT Core: una piattaforma all-in-one di ingestion, storage e analytics per dati IoT in streaming, completamente gestita, serverless e con auto-scaling. IoT Core le consente di evitare di mettere insieme servizi AWS separati per ottenere la stessa funzionalità.
Grazie per la lettura! Per restare in contatto, ci segua sul DoiT Engineering Blog , sul canale LinkedIn di DoiT e sul canale Twitter di DoiT . Per esplorare le opportunità di carriera, visiti https://careers.doit-intl.com .