Un bot a larga scala per Europe Code Week

Pubblicato il da
Tag: / / /


Sono passati alcuni giorni dalla chiusura dello Europe Code Week 2016, che ha superato i risultati ottenuti dalle precedenti edizioni con un totale da record di oltre 20,000 eventi organizzati in più di 50 paesi.

All’interno di CodeMOOC, un massive open online course (corso aperto online su larga scala) offerto dall’Università di Urbino ed incentrato sul pensiero computazionale ed il coding, si è pianificato per il 20 ottobre lo svolgimento di un quiz di coding su larga scala. Utilizzando soltanto un client Telegram ed uno scanner di codici QR, i partecipanti hanno avuto la possibilità di partecipare al gioco e di sfidare oltre 900 gruppi di varie località d’Italia.

Telegram Quizzle channel

Canale Telegram.

I partecipanti si potevano registrare ad un canale Telegram, sul quale sono state pubblicate le istruzioni del gioco poco prima dell’evento. All’inizio del gioco è stato pubblicato il collegamento ad uno stream live su Youtube, attraverso il quale venivano diffuse ulteriori istruzioni e le domande del quiz.

Per ogni quiz assegnato durante il gioco, il bot Telegram pubblicava un collegamento speciale sul canale pubblico. Questo collegamento conduceva ad una conversazione privata tra partecipante e bot, sfruttando il cosiddetto deep linking di Telegram. Siccome ogni quiz del gioco era identificato da un particolare codice unico, il deep link, dopo aver condotto il partecipante alla conversazione privata, inviava anche un comando nascosto:

/start IY4

(Dove il codice IY4 identifica il 4° quiz dell’evento.)

I partecipanti potevano partecipare ai quiz anche scansionando direttamente un codice QR mostrato nello stream Youtube, che a sua volta conteneva il medesimo deep link.

Response and results of a quiz question.

Risposta e risultati di uno dei quiz.

Una volta attivato tramite il collegamento, il bot chiedeva all’utente di fornire la risposta al quiz.
Appena l’amministratore del quiz chiudeva la domanda (semplicemente scrivendo la risposta corretta al bot tramite una conversazione privata), il bot classificava tutte le risposte corrette ricevute in base al timestamp di ricezione e le rendeva pubbliche sul canale. Le prime 3 risposte corrette venivano premiate con l’assegnazione di alcune, inestimabili, medaglie emoji. ?

Gestione dei messaggi

Un totale di 974 partecipanti (intesi come singoli utenti Telegram) hanno partecipato all’evento. Siccome ogni utente poteva registrarsi per conto di un gruppo di persone (rappresentandolo come capogruppo), il conteggio sale ad un totale di 9689 persone di partecipanti. 14 domande sono state poste durante il gioco, raccogliendo un totale di 7004 risposte dai partecipanti, durante circa un’ora e mezza di gioco.

In altre parole: un sacco di messaggi sono stati scambiati con il nostro bot nell’arco di pochissimo tempo.

Telegram supporta due diverse modalità di ricezione dei messaggi: pull e push.

Modalità Pull

In modalità Pull, il bot si collega periodicamente ad un end-point HTTP dei server Telegram e scarica tutti o parte dei messaggi in coda per la consegna. Il meccanismo di consegna può essere personalizzato, ad esempio scaricando una sequenza di messaggi in un unico collegamento oppure utilizzando l’opzione di long polling per rendere bloccante la richiesta ed attendere che vi siano dati disponibili lato server.

Sulla carta questa modalità assicura maggiore efficienza: le richieste sono controllate dal server che ospita il bot, possono essere gestite con più facilità ed un gran numero di messaggi può essere trasferito all’interno della stessa comunicazione HTTP.

Tuttavia, operazioni pull sono, per natura, sincrone. Le API di Telegram non permettono più di una richiesta concorrente (visto che, ovviamente, le singole richieste pull operano sequenzialmente sulla stessa coda di messaggi). Mentre trasferire un singolo grande payload di messaggi e processarli in un unico passo di decodifica JSON è potenzialmente più efficiente, quello che accade in effetti è che in questa modalità il tempo medio di risposta aumenta. Inoltre, dopo la fase di scaricamento e di decodifica, il parallelismo è interamente compito dello sviluppatore. La gestione dei messaggi su diversi processi o thread paralleli può essere più o meno difficile in base al proprio ambiente di programmazione: in Go si può invocare una goroutine per ogni messaggio, mentre la stessa cosa può essere fatta usando dei task async su .NET.

Modalità Push

Questa modalità—che per inciso è l’unica modalità disponibile su diverse altre piattaforme di messaggistica—baratta la fase di un singolo trasferimento dati molto efficiente per una moltitudine di operationi di gestione messaggi che avvengono in parallelo.

Invece di aspettare che il bot contatti il server Telegram per ottenere nuovi messaggi, eventuali aggiornamenti sono inviati direttamente al server web del bot attraverso un end-point ad un URL definito dallo sviluppatore (Telegram richiede una connessione HTTPS, un dominio ed un certificato valido). Invece di doversi occupare dei dettagli implementativi della gestione parallela dei messaggi, questa modalità permette di sfruttare i punti di forza intrinseci di un server web: la gestione di un grande numero di connessioni in ingresso e la loro gestione efficiente.

Risultati

In base ai nostri log, ben 7,414,458 messaggi sono stati inviati al nostro bot tramite Telegram, durante circa 80 minuti di gioco.

An average of over 1500 messages per second were handled.

In media il bot ha ricevuto oltre 380 messaggi per minuti, con un picco di circa 1200. Guardando attentamente il grafico è possibile intuire quando sono state poste le 14 domande del quiz.

Inizialmente il nostro bot era stato configurato per operare in modalità pull, con una gestione sincrona dei messaggi in ingresso, visto che questa modalità permette di sviluppare e fare debug in maniera molto comoda. Tuttavia, appena l’evento ha avuto inizio, abbiamo subito scoperto che la coda dei messaggi in ingresso stava crescendo a dismisura e il nostro bot semplicemente non riusciva a tenere il passo dei giocatori.
Siamo riusciti a passare rapidamente alla modalità push. Dopo un paio di minuti il bot è riuscito a mettersi in paro con i messaggi, dopodiché non si sono verificati altri problemi di responsività nella comunicazione con i partecipanti.

Il bot era installato su una macchina quad-core a 2.6 GHz, con 2 GB di RAM.

Concludendo, la modalità pull è perfettamente adatta per lo sviluppo dei bot, visto che permette agli sviluppatori di controllare il flusso di messaggi in ingresso e di effettuare un attento debugging del codice. Tuttavia, probabilmente non vale la pena implementare un metodo efficiente (e corretto) di gestione dei messaggi tramite modalità pull. Come già suggerito da altri, è molto più sensato affidarsi ad un server web per la gestione efficiente di richieste parallele invece di provare a reinventare la ruota.

Più generalmente—e questo è molto importante nel contesto della recente attenzione ai bot come rimpiazzo delle applicazioni mobili—l’utilizzo di un bot al posto di un sito web o altro ci ha dato un fondamentale vantaggio. La piattaforma di messagistica, Telegram in questo caso, funge da “load balancer” estremamente scalabile tra gli utenti ed il proprio servizio. La piattaforma gestisce la coda dei messaggi, l’invio, la consegna e la notifica degli utenti—in sostanza Telegram offre una incredibile infrastruttura molto sofisticata ad un costo nullo. Questo permette agli sviluppatori di bot di concentrarsi sullo sviluppo del servizio invece di doversi occupare dei fondamenti.

Questo evento dello Europe Code Week è stato un’ottima opportunità per valutare gli effetti di un carico di lavoro inusuale su un bot (per quanto ci riguarda). Altri eventi di questa natura verranno organizzati in futuro e ci aspettiamo di poter valutare altri aspetti legati alle prestazioni ed alla scalabilità in maggiore dettaglio.

Il codice utilizzato durante l’evento è disponibile su Github.

Share on Google+Share on FacebookTweet about this on TwitterShare on LinkedInDigg thisEmail this to someone

Lascia un commento

  • (non sarà pubblicato)