{"id":5049,"date":"2022-10-21T11:23:40","date_gmt":"2022-10-21T09:23:40","guid":{"rendered":"https:\/\/blog.besharp.it\/?p=5049"},"modified":"2022-10-21T14:54:02","modified_gmt":"2022-10-21T12:54:02","slug":"born-to-perform-build-race-analyze-repeat","status":"publish","type":"post","link":"https:\/\/blog.besharp.it\/it\/born-to-perform-build-race-analyze-repeat\/","title":{"rendered":"Born to Perform: build, race, analyze, repeat."},"content":{"rendered":"\n
Uno dei temi che pi\u00f9 ci hanno appassionato negli ultimi anni \u00e8 sicuramente quello dell\u2019estrazione del valore dal dato<\/strong>. <\/p>\n\n\n\n Complice anche la grande richiesta – da parte di clienti e non – di progetti data-centrici, ci siamo divertiti a esasperare il concetto di data-driven in molti side projects di R&D arrivando a padroneggiare sempre di pi\u00f9 l\u2019argomento<\/a>. <\/p>\n\n\n\n In beSharp non ci accontentiamo di comprendere. Noi vogliamo sperimentare. Perfezionare. Sporcarci le mani nei contesti pi\u00f9 estremi, quelli in cui anche i nerd pi\u00f9 accaniti penserebbero che siamo pazzi (true story\u2026 ma non ce la prendiamo :D). <\/p>\n\n\n\n E cos\u00ec, qualche tempo fa, in un crescendo di smanettamento sempre pi\u00f9 estremo, abbiamo assemblato il primo racing simulator by beSharp: volante direct-drive da 32 Nm di coppia, pedali con smorzatori idraulici progettati per resistere a oltre 140 kg di pressione, sedile racing con cinture a 6 punti e, soprattutto, una piattaforma di movimento a 4DOF per riprodurre la dinamica del veicolo e le asperit\u00e0 del tracciato. <\/p>\n\n\n\n Non contenti, abbiamo costruito pezzo per pezzo anche un hardware super-carrozzato<\/strong> che abbiamo subito iniziato a maltrattare installandoci sopra \u201cAssetto Corsa Competizione\u201d, uno dei software di simulazione di guida pi\u00f9 fedeli mai costruiti. <\/p>\n\n\n\n La parte veramente interessante di questo progetto – nonch\u00e9 la pi\u00f9 challenging – \u00e8 stata per\u00f2 riuscire a intercettare da \u201cAssetto Corsa\u201d il maggior numero possibile di metriche<\/strong>, di portarle efficientemente sul Cloud con un sistema di ingestion<\/strong> e, infine, visualizzarle a schermo in real-time<\/strong> durante la corsa. Una figata, vero?<\/p>\n\n\n\n D\u2019altro canto, anche Galileo Galiei lo aveva detto: \u201cMisura ci\u00f2 che \u00e8 misurabile, e rendi misurabile ci\u00f2 che non lo \u00e8\u201d.<\/p>\n\n\n\n Si sa, noi ci ispiriamo solo ai migliori \ud83d\ude09 <\/p>\n\n\n\n E\u2019 proprio sull\u2019aspetto Cloud della soluzione che ci concentreremo in questo articolo. Vi racconteremo nel dettaglio come abbiamo combinato i servizi di AWS per progetti data-centrici fino ad arrivare ad un risultato soddisfacente secondo i nostri standard.<\/p>\n\n\n\n Cominciamo!<\/p>\n\n\n\n L’obiettivo principale da tenere a mente durante la progettazione e lo sviluppo \u00e8 sempre stato solo uno: le performance<\/strong>.<\/p>\n\n\n\n Quindi dovevamo trovare un modo rapido per estrarre tutte le metriche di cui avevamo bisogno dal software che ci permetteva di girare nelle piste pi\u00f9 veloci del mondo.<\/p>\n\n\n\n Bene, come punto di partenza avevamo un noto software di simulatore di guida, che utilizziamo per divertirci virtualmente su pista. Da qui nasce la prima sfida tecnica.<\/p>\n\n\n\n Il simulatore di guida utilizzato \u00e8 infatti pensato per essere installato ed eseguito per giocarci, non per integrarsi con applicazioni terze.<\/p>\n\n\n\n Ma girando nei pi\u00f9 remoti spazi di internet, unendo pezzi di documentazione presi qua e l\u00e0, ci siamo riusciti! Abbiamo scoperto che il software espone un server UDP locale nativamente.<\/p>\n\n\n\n Il protocollo UDP, tra l\u2019altro, faceva al caso nostro, dovendo estrarre dati runtime con performance super ottimali!<\/p>\n\n\n\n Ok perfetto, nulla di pi\u00f9 facile, allora creiamo un connettore in Python, estraiamo ed \u00e8 fatta no? Sarebbe stato bellissimo ma molte metriche mancavano, quindi dovevamo cercare un altra strada.<\/p>\n\n\n\n Non ci siamo fatti abbattere e dopo altre ore di ricerche forse avevamo la risposta: prenderle direttamente dalla RAM<\/strong>.<\/p>\n\n\n\n Abbiamo trovato degli indirizzi di memoria che venivano scritti con tutti i dati di cui avevamo bisogno, direttamente dal software del simulatore.<\/p>\n\n\n\n Quindi siamo partiti a sviluppare un piccolo script in Python che estrae i dati binari e li converte in modo da vedere se c’\u00e8 tutto quello di cui abbiamo bisogno.<\/p>\n\n\n\n Eureka! Questa volta avevamo tutto.<\/p>\n\n\n\n Abbiamo concluso questa prima parte aggiungendo al nostro script di estrazione dati una parte che prende tutti i dati, li impacchetta in JSON e li spedisce in cloud.<\/p>\n\n\n\n S\u00ec, ma dove in Cloud?<\/p>\n\n\n\n Se siete dei lettori abituali saprete bene che a noi di beSharp fa impazzire la progettazione di infrastrutture cloud altamente performanti, scalabili e affidabili. In questo progetto abbiamo trovato pane per i nostri denti.<\/p>\n\n\n\n La prima cosa alla quale pensare \u00e8: quale servizio scegliere come porta di ingresso nel cloud?<\/p>\n\n\n\n Le possibilit\u00e0 a nostra disposizione erano molteplici: potevamo gestire tutto il flusso dei dati proveniente dal simulatore con uno stream Kinesis o con un cluster Fargate ad esempio.<\/p>\n\n\n\n Entrambe le soluzione sarebbero state scalabili e performanti ma queste strade avrebbero portato a dover sviluppare e gestire una componente software che smistasse il traffico in base ai dati in input.<\/p>\n\n\n\n Queste soluzioni non rispettavano pienamente i criteri di qualit\u00e0 infrastrutturale che ci eravamo posti, noi volevamo un infrastruttura interamente Event Driven e Serverless, in grado di garantire un’ elevata scalabilit\u00e0 e l’integrazione gestita out of the box con un’ampia gamma di servizi AWS.<\/p>\n\n\n\n Abbiamo trovato queste caratteristiche nel servizio IoT Core<\/strong>.<\/p>\n\n\n\n Le caratteristiche che hanno fatto vincere questo servizio rispetto agli altri sono: <\/p>\n\n\n\n Ok abbiamo capito come far entrare i dati nel nostro account AWS, adesso abbiamo bisogno di dividere questo enorme flusso di dati grezzi in 3 parti:<\/p>\n\n\n\n Ingestion metriche per Real Time Analysis<\/strong>: serve per la visualizzazione real time di tutte le metriche.<\/p>\n\n\n\n I servizi principali che avevamo a disposizione per raggiungere questo obiettivo sono 2: Amazon QuickSight e OpenSearch.<\/p>\n\n\n\n Il nostro scopo era avere un servizio che mostrasse i dati in near real time passanti da una regola creata su IoT core e non fosse da gestire a livello infrastrutturale.<\/p>\n\n\n\n Analizziamo il primo servizio: Amazon QuickSignt, consente di creare una dashboard con numerosi oggetti grafici per una reportistica avanzata.<\/p>\n\n\n\n Il problema fondamentale di questa soluzione \u00e8 che non \u00e8 direttamente integrabile con IoT Core.<\/p>\n\n\n\n Bisognerebbe far passare i dati dalla regola creata su IoT Core a un kinesis stream per poi depositare il tutto in un data lake all’interno di Amazon S3.<\/p>\n\n\n\n Solo dopo aver fatto questo potremmo integrarlo con Amazon QuickSight ma in maniera non realtime.<\/p>\n\n\n\n Quindi abbiamo bocciato Amazon QuickSignt con un ottimo livello di certezza, visto che \u00e8 un servizio pensato per fare business analysis e non realtime analysis.<\/p>\n\n\n\n Passiamo al prossimo candidato: OpenSearch, anche lui ci permette di creare oggetti grafici per report avanzati.<\/p>\n\n\n\n Ma la caratteristica che fa da game changer per questo servizio \u00e8 l’integrazione diretta e nativa con la nostra regola su IoT Core.<\/p>\n\n\n\n Per creare questa connessione non basta altro che inserire come target, all’interno di una regola, l’endpoint del nostro cluster OpenSearch e l’indice sul quale mandare i dati.<\/p>\n\n\n\n Facile no? Quindi direi che abbiamo un vincitore!<\/p>\n\n\n\n Ingestion informazioni circa il tempo del giro: <\/strong>Il forwarding dei dati, acquisiti dal campo, \u00e8 stato facilmente implementato usando una regola su IoT Core che seleziona i dati in transito relativi ad un singolo giro e invoca una componente computazionale che prende i dati elaborati e li inserisce all’interno di un servizio di storage.<\/p>\n\n\n\n Quindi per questo flusso dobbiamo scegliere 2 servizi.<\/p>\n\n\n\n Iniziamo dalla parte computazionale: su AWS abbiamo un mare di possibilit\u00e0 per scrivere un software e farlo eseguire in ambiente cloud, ma proviamo a restringere un po’ il campo.<\/p>\n\n\n\n Dobbiamo tenere a mente che il nostro requisito \u00e8 sempre quello di avere un’infrastruttura serverless, estremamente scalabile e che adotti il modello di pagamento Pay As You Use e che sia integrabile direttamente con le regole di IoT Core.<\/p>\n\n\n\n Quindi possiamo gi\u00e0 restringere il campo a Fargate e Lambda, i 2 servizi principali per lo sviluppo serverless su AWS.<\/p>\n\n\n\n Il primo servizio ci consente di creare un cluster di container Docker, la parte di scalabilit\u00e0 \u00e8 da configurare e gestire, inoltre un cluster Fargate non si spegne automaticamente se non viene invocato andando quindi a rincarare sul nostro billing anche quando non siamo in pista.<\/p>\n\n\n\n Quindi non ci resta che utilizzare una Lambda Function, questa a differenza di Fargate rispetta in pieno il concetto di Pay As You Use in quanto, una volta terminato il runtime, il container si spegne, per poi riaccendersi solo alla successiva invocazione.<\/p>\n\n\n\n Una volta scelta la parte computazionale dovevamo scegliere lo storage.<\/p>\n\n\n\n Sicuramente avevamo bisogno di uno storage che fosse facilmente interrogabile per mezzo di query, con performance estremamente elevate, anche questo deve rispettare il concetto di Pay As You Use ed essere totalmente gestito a livello di scalabilit\u00e0.<\/p>\n\n\n\n Dati questi requisiti quello che abbiamo a disposizione su AWS \u00e8 Aurora Serverless e DynamoDB.<\/p>\n\n\n\n Il primo ci porterebbe alla configurazione di un cluster che avrebbe sempre un nodo acceso e che quindi non ci farebbe ottimizzare il nostro billing, inoltre non avevamo la necessit\u00e0 di avere dei dati strutturati con delle relazioni.<\/p>\n\n\n\n Quindi abbiamo scelto di utilizzare una singola tabella del servizio DynamoDB che ci fornisce un database NoSQL e key-value per la parte di memorizzazione dei tempi e della leaderboard.<\/p>\n\n\n\n Ingestion metriche per storicizzazione e future analisi: <\/strong>Il terzo ed ultimo flusso \u00e8 relativo alla parte di DataLake, la nostra soluzione genera una grande mole di dati grezzi che va messa in uno spazio nel quale sar\u00e0 possibile fare analisi e trasformarli in dati utilizzabili, questo deve essere possibile in qualsiasi momento senza dover ripensare all’infrastruttura.<\/p>\n\n\n\n Quindi la prima domanda a cui dovevamo rispondere era dove conservare i dati.<\/p>\n\n\n\n Volevamo uno storage service scalabile, pay as you use, con la possibilit\u00e0 di suddividere lo spazio con diversi livelli di sicurezza e con diverse lifecycle policy.<\/p>\n\n\n\n In questo caso la scelta \u00e8 stata molto semplice, la nostra scelta non poteva che ricadere su Amazon S3 poich\u00e8 \u00e8 l’unico servizio all’interno di AWS con tutti i requisiti di cui avevamo bisogno.<\/p>\n\n\n\n Adesso non ci restava altro che capire come mettere i dati sul bucket S3 senza dover leggere da IoT Core e riscrivere sul bucket con un applicativo custom.<\/p>\n\n\n\n Anche in questo caso la scelta \u00e8 molto semplice, qui \u00e8 il caso di implementare un Kinesis Stream che grazie alla sua integrazione nativa con Amazon S3 ci consente di mettere dati sul nostro bucket senza gestirne il trasferimento.<\/p>\n\n\n\n Adesso che abbiamo creato il nostro DataLake, siamo gi\u00e0 predisposti per future operazioni di businiss analysis, grazie a servizi come Athena o QuickSignt che hanno l’integrazione nativa con il servizio S3.<\/p>\n\n\n Vi starete sicuramente chiedendo: “ma vi siete tenuti questo progetto tutto per voi?\u201d <\/p>\n\n\n\n Assolutamente no! Dal primissimo momento in cui abbiamo acquistato il simulatore, avevamo gi\u00e0 in mente di fare le cose in grande. Era solo questione di definire la strada (anzi, la pista) da percorrere. <\/p>\n\n\n\n Ed \u00e8 cos\u00ec che siamo arrivati all’edizione 2022 dell\u2019AWS summit di Milano, l\u2019evento Cloud italiano per definizione, finalmente in presenza dopo due anni di versione virtuale.<\/p>\n\n\n\n Se siete passati di l\u00ec, avrete sicuramente percepito il rumore che abbiamo fatto al nostro stand: una Cloud Band che suonava live, poster divertenti, buon caff\u00e9 e un mare di \u201cviola-beSharp\u201d\u2026 ma la star indiscussa \u00e8 stata sicuramente proprio lui, il Simulatore. <\/p>\n\n\n\n Questa nostra creazione non \u00e8 stata un semplice punto di partenza, n\u00e9 tanto meno un traguardo; \u00e8 invece uno dei protagonisti principali di un progetto ambizioso molto pi\u00f9 ampio che abbiamo deciso di battezzare come \u201cbeSharp Performance Technology\u201d, per gli amici \u201cbPT\u201d. <\/p>\n\n\n\n bPT \u00e8 un vero e proprio nuovo brand in cui ci sentiremo liberi di dare sfogo a tutta l\u2019R&D possibile e (IN)immaginabile. <\/p>\n\n\n\n Il perch\u00e9 sia nato, \u00e8 storia\u2026 Anche molto divertente! Per i pi\u00f9 curiosi, la trovate qui<\/a>.\u00a0<\/p>\n\n\n\n beSharp declina ogni responsabilit\u00e0 per eventuali schizzi di nerditutidine dopo aver letto questo articolo\u2026 ma accetta di sapere nei commenti cosa ne pensate di tutto questo folle progetto!<\/p>\n\n\n\n A presto, su Proud2beCloud!<\/p>\n\n\n\nLe sfide tecniche incontrate<\/h2>\n\n\n\n
L’archittettura su AWS<\/h2>\n\n\n\n
Ingestion<\/h3>\n\n\n\n
Computational Component<\/h3>\n\n\n\n
Database<\/h3>\n\n\n\n
Data Lake<\/h3>\n\n\n\n
<\/figure><\/div>\n\n\n
Conclusioni<\/h2>\n\n\n\n
\n\n\n\nAbout Proud2beCloud<\/h4>\n\n\n\n