Venerdì 25 Novembre si è ripetuto l’appuntamento annuale con il Black Friday, l’evento di vendita più importante dell’anno negli Stati Uniti. Negli ultimi anni questo evento ha assunto un crescente successo anche in altri paesi, tra cui l’Italia – per rendersene conto, basta un’occhiata al sito di Google Trends:

 

Interesse nel termine “black friday”, in Italia, periodo 2012-2016 - fonte: Google Trends

Interesse nel termine “black friday”, in Italia, periodo 2012-2016 – fonte: Google Trends

Nel settore retail (non solo elettronico) è sempre più importante monitorare – e presidiare – eventi come questo in ogni ambito, anche (e soprattutto) quello social.

Il Black Friday può essere infatti una ghiotta occasione per sponsorizzare i propri prodotti, far conoscere il proprio brand, e avviare con “slancio” la stagione degli acquisti natalizi.

Mettiamoci ad esempio nei panni di ACME Corporation, una famosa azienda che, come lo stesso nome suggerisce*, produce e commercializza… letteralmente di tutto.

 

CLOUD ACADEMY 1 DICEMBRE

Alcuni prodotti ACME Corporation

Con l’avvicinarsi del Black Friday, il Marketing Director di ACME Corp. decide di commissionare un’indagine sui social, e in particolare su Twitter, per catturare insights utili a posizionare correttamente i propri prodotti, prima e durante l’evento. Questo è tanto più cruciale quanto si considera l’enorme dimensione del catalogo aziendale: indirizzare in modo sbagliato la propria campagna pubblicitaria e promozionale sarebbe un errore fatale.

Gli esperti Data Architect di ACME Corp. si mettono immediatamente al lavoro. Memori di esperienze simili, decidono di affidarsi ad un’infrastruttura Cloud: il dimensionamento dell’infrastruttura è infatti operazione tutt’altro che facile, e qualsiasi errore di valutazione rischierebbe di compromettere il successo del progetto.

image03

Il processo di analisi ipotizzato riprende uno schema piuttosto usuale nei progetti di real-time Data Analytics:

image00

Tuttavia, per gestire il forte traffico atteso durante l’evento, gli ingegneri di ACME decidono di abbandonare le tecnologie tradizionali, e di implementare questa architettura su Google Cloud Platform, attraverso sole componenti serverless:

image07

Ingestion

Per recuperare i dati viene implementata una semplice applicazione Python che, attraverso la libreria TweePy, accede alle Streaming API di Twitter recuperando il flusso di messaggi riguardanti il Black Friday e le tematiche ad esso connesse. TweePy mette a disposizione un metodo filter, che consente di recuperare tutti i tweet che rispettano specifici predicati. Nel nostro caso, tutti quelli che contengono una serie di parole chiave:

"blackfriday", "blackfriday2016", "blackfridaysale", "cybermonday", "givingtuesday", "thanksgiving", "handsupdontspend", "blackoutblackfriday", "notonedime", "deals", "giveaway", "sale", "christmas", "retail", "amazon", "walmart", "apple", "best buy", "bestbuy", "target", "kohls", "bigsale"

L’elenco di parole chiave comprende, oltre a una serie di brand e vendor di rilievo, anche alcuni termini “ostili” al Black Friday (come “hands up don’t spend” o “black out Black Friday”). D’altronde, “nel bene o nel male, purché se ne parli”!

Per fare in modo che anche questa componente mantenga gli standard di affidabilità prefissati, si decide di eseguirla, all’interno di un container Docker, su Google Container Engine, l’implementazione di Kubernetes su Google Cloud Platform. In questo modo, non dovremo preoccuparci di eventuali outage o malfunzionamenti. Tutto è gestito (e all’occorrenza automaticamente riavviato) da Kubernetes.

image16

Innanzitutto creiamo l’immagine Docker che utilizzeremo per il deploy. A questo scopo è sufficiente redigere opportunamente un Dockerfile che contenga le istruzioni per installare le librerie necessarie, copiare la nostra applicazione ed avviare lo script:

image13

Et voilà! L’immagine Docker è pronta per essere eseguita ovunque: sul nostro laptop, su un server on-prem o, come nel nostro caso, all’interno di un cluster Kubernetes. Il deploy su Container Engine è semplicissimo, con il tool da riga di comando di Google Cloud Platform: tre sole istruzioni che servono a creare il cluster Kubernetes, acquisire le credenziali di accesso ed eseguire l’applicazione in modo scalabile ed affidabile all’interno di un ReplicationController.

$ gcloud container clusters create codemotion-2016-demo-cluster
Creating cluster cluster-1...done.
Created [...projects/codemotion-2016-demo/.../clusters/codemotion-2016-demo-cluster].

$ gcloud container clusters get-credentials codemotion-2016-demo-cluster
Fetching cluster endpoint and auth data.
kubeconfig entry generated for cluster-1.

$ kubectl create -f ~/git/kube-pubsub-bq/pubsub/twitter-stream.yaml
replicationcontroller “twitter-stream” created.

Il secondo elemento della nostra catena, la componente cioè verso la quale la nostra applicazione invierà i tweet, è Google Pub/Sub.

  • Pub/Sub è una soluzione middleware fully-managed, che realizza un’architettura Publisher/Subscriber in modo affidabile e scalabile.

Il suo ruolo in una Data Architecture è disaccoppiare le componenti che producono i dati dalle componenti che li consumano; ciò migliora la flessibilità e l’affidabilità del sistema, poiché se anche un consumatore dovesse andare offline, Pub/Sub mantiene una coda dei messaggi non consegnati, che verranno recapitati nel momento in cui il sistema tornerà online.

image11

Processing e storage

Ottimo! Abbiamo implementato un meccanismo di ingestion affidabile e scalabile. Per mantenere gli stessi standard nella successiva fase di processing, utilizziamo altri due strumenti della suite Google Cloud Platform:

  • Google Cloud Dataflow è un SDK Java open source – adesso noto sotto il nome di Apache Beam – per la realizzazione di pipeline di processing parallele. Inoltre, Cloud Dataflow è il servizio fully managed operante sull’infrastruttura Google, che esegue in modo ottimizzato pipeline di processing scritte con Apache Beam.
  • Google BigQuery è una soluzione di Analytic Data Warehouse fully managed. Le sue performance strabilianti, che abbiamo avuto modo di sottolineare più volte, lo rendono una soluzione ottimale all’interno di architetture di Data Analytics.

La pipeline che andiamo a progettare è estremamente semplice. Di fatto non farà altro che trasformare la struttura JSON che identifica ogni Tweet, inviata dalle API di Twitter e recapitata da Pub/Sub, in una struttura record BigQuery. Successivamente, attraverso le BigQuery Streaming API, ogni record verrà scritto in una tabella in modo tale che i dati possano essere immediatamente analizzati.

image15

Il codice della pipeline è estremamente semplice; questo è in effetti uno dei punti di forza di Apache Beam rispetto ad altri paradigmi di processing, come MapReduce. Tutto ciò che dobbiamo fare è creare un oggetto di tipo Pipeline e poi applicare ripetutamente il metodo apply() per trasformare i dati in modo opportuno. È interessante osservare come i dati vengano letti e scritti utilizzando due elementi di I/O inclusi nell’SDK: PubSubIO e BigQueryIO. Non è quindi necessario scrivere codice boilerplate per implementare l’integrazione tra i sistemi.

image09

Essendo un programma Java, l’esecuzione della pipeline può essere invocata direttamente da riga di comando attraverso un tool come Maven:

$ mvn compile exec:java Dexec.mainClass=it.noovle.dataflow.TwitterProcessor

-Dexec.args="--streaming"

[...]

INFO: To cancel the job using the 'gcloud' tool, run:
> gcloud alpha dataflow jobs --project=codemotion-2016-demo cancel 2016-11-19_15_49_53-5264074060979116717
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 18.131s
[INFO] Finished at: Sun Nov 20 00:49:54 CET 2016
[INFO] Final Memory: 28M/362M
[INFO] ------------------------------------------------------------------------

Una volta lanciata l’esecuzione, la pipeline può essere monitorata dalla Web Console per assicurarsi del suo effettivo funzionamento.

image10

A questo punto, se tutto funziona come deve, possiamo cominciare ad osservare i dati che fluiscono all’interno della tabella BigQuery. Il miglior modo per verificare è lanciare qualche query direttamente sui dati, utilizzando la comoda interfaccia Web:

image18

Analysis

Wow, i dati ci sono davvero! Proviamo allora, dopo qualche giorno di raccolta, a fare qualche analisi più complessa. La seguente query è un esempio della ricca espressività del linguaggio SQL di interrogazione di BigQuery:

SELECT
 date,
 AVG(pacific_count) OVER (ORDER BY date ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) AS pacific,
 AVG(central_count) OVER (ORDER BY date ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) AS central,
 AVG(mountain_count) OVER (ORDER BY date ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) AS mountain,
 AVG(eastern_count) OVER (ORDER BY date ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) AS eastern,
FROM (
 SELECT
   SUM(IF(user.time_zone = "Pacific Time (US & Canada)",1,0)) AS pacific_count,
   SUM(IF(user.time_zone = "Central Time (US & Canada)",1,0)) AS central_count,
   SUM(IF(user.time_zone = "Mountain Time (US & Canada)",1,0)) AS mountain_count,
   SUM(IF(user.time_zone = "Eastern Time (US & Canada)",1,0)) AS eastern_count,
   DATE(created_at) AS date
 FROM
   [codemotion-2016-demo:rtda.tweets]
 GROUP BY
   date)

Si tratta di una query che ne contiene un’altra innestata (sì, BigQuery supporta query innestate). Quella più interna conta il numero di Tweet provenienti ogni giorno da ognuno dei quattro fusi orari statunitensi – una sorta di pivot, elaborata attraverso l’utilizzo delle funzioni SUM() e IF(). Quella più esterna utilizza una delle potenti funzioni analitiche (o Window Functions) di BigQuery per calcolare una rolling average dei valori sui tre giorni precedenti.

Ora, per chiudere il giro, troviamo alcune analisi interessanti, e rendiamo fruibile e condivisibile il risultato attraverso delle belle visualizzazioni grafiche. A tale scopo utilizziamo Google Data Studio, uno strumento della suite Google Analytics che consente di costruire visualizzazioni grafiche di vario tipo a partire da diverse sorgenti dati, tra le quali ovviamente figura anche BigQuery. Possiamo poi condividere le dashboard, oppure renderle pubblicamente accessibili, esattamente come faremmo con un documento Google Drive.

image05

In questo grafico è riportato il numero di Tweet collezionato da ogni stato dell’Unione. Sicuramente d’impatto, ma non molto utile per il nostro scopo. In effetti, dopo un po’ di analisi esplorativa dei dati, ci accorgiamo che con i soli tweet collezionati non riusciamo a fare analisi molto “avanzate”. Dobbiamo quindi rivedere la nostra procedura di processing per cercare di inferire qualche elemento di conoscenza più “interessante”.

Google Cloud Platform ci viene in aiuto, in questo caso offrendoci una serie di API, basate su algoritmi di Machine Learning, il cui scopo è esattamente aggiungere un pizzico di “intelligenza” al nostro processo di analisi. In particolare utilizzeremo le Natural Language API, che ci saranno utili per recuperare il sentiment di ogni tweet, cioè un indicatore numerico della positività (o negatività) del testo contenuto nel messaggio.

image14

La API è molto semplice da usare: prende in ingresso un testo (il nostro tweet) e restituisce due parametri:

  • Polarity (FLOAT variabile da -1 a 1) esprime l’umore del testo: valori positivi denotano sentimenti positivi.
  • Magnitude (FLOAT variabile da 0 a +inf) esprime l’intensità del sentimento. Valori più alti denotano sentimenti più forti (siano essi rabbia o gioia).

La nostra personale semplicistica definizione di “sentiment” altro non è che il prodotto di questi due valori. In questo modo siamo in grado di assegnare un valore numerico ad ogni tweet – ed auspicabilmente, di tirarne fuori delle statistiche interessanti!

La pipeline Dataflow viene modificata in modo da includere, oltre al flusso precedente, anche questo nuovo step. Tale modifica è molto semplice, e visto il modello di programmazione di Cloud Dataflow, permette un notevole riuso del codice esistente.

image01

L’update della pipeline non richiede di interrompere il flusso dei dati, in quanto esiste un meccanismo di rolling update. Basta soltanto specificarlo all’interno del comando Maven che effettua il build, utilizzando il flag –update:

$ mvn compile exec:java -Dexec.mainClass=it.noovle.dataflow.TwitterProcessor
-Dexec.args="--streaming --update --jobName=twitterprocessor-lorenzo-1107222550"

Con questi nuovi dati possiamo realizzare delle analisi molto più interessanti, che ci informano sulla distribuzione geografica e temporale del “sentimento” riguardante l’evento Black Friday.

La mappa che segue, ad esempio, mostra il sentiment medio registrato in ognuno degli stati degli US, colori più scuri rappresentano sentiment più negativi (quel quadrato rosso là in mezzo è il Wyoming).

image08

Quest’altra analisi invece riporta l’andamento del sentiment legato ai tre maggiori vendor statunitensi: Amazon, Walmart e Best Buy. A partire da questa semplice analisi, con un po’ di drill-down sui dati, siamo riusciti a carpire alcuni fatti interessanti:

  • il popolo di Twitter non ha apprezzato la decisione di Walmart di anticipare l’apertura delle proprie vendite al giorno precedente il Black Friday, la festa nazionale del Thanksgiving Day. La popolarità di Walmart è stata infatti minata fin dai primi di Novembre da questa decisione  – d’altronde, la tutela dei lavoratori è un tema universale.
  • Le vendite promozionali di Amazon (aperte il 18 Novembre, quindi con anticipo rispetto al Black Friday) sono state inizialmente duramente criticate dagli utenti, con un crollo della popolarità che ha raggiunto il suo minimo il 22. In seguito però il colosso delle vendite online ha recuperato terreno rispetto a Best Buy, che invece sembra aver mantenuto intatta la sua buona reputazione per tutto il periodo.

image02