Crea pipeline di streaming stateful che tracciano milioni di sessioni attive di dispositivi di gioco, producendo heartbeat in tempo reale con latenza inferiore al secondo in Apache Spark
Nel settore del gaming, ogni millisecondo conta. Per guidare la personalizzazione in-game, alimentare i motori di raccomandazione e prendere decisioni dinamiche sulla programmazione dei contenuti, le piattaforme devono elaborare i dati delle sessioni di milioni di giocatori in tutto il mondo con una latenza inferiore al secondo.
Oggi, soddisfare questi requisiti di latenza ultra-bassa non richiede più un'architettura frammentata con più motori. In questo blog esploreremo un'implementazione reale di Apache Spark Real-Time Mode. Sfruttando il nuovo operatore transformWithState per logiche con stato complesse, mostreremo come Spark offra prestazioni end-to-end nell'ordine dei millisecondi. Scopri come il tuo team può accelerare lo sviluppo e creare applicazioni operative mission-critical utilizzando il familiare ecosistema Structured Streaming.
Per le piattaforme di gaming, sapere quali dispositivi sono attivi e per quanto tempo non è solo una questione di infrastruttura, ma guida il business. I dati delle sessioni in tempo reale alimentano esperienze in-game personalizzate, motori di raccomandazione, decisioni sulla programmazione dei contenuti e forniscono segnali sullo stato di salute dei dispositivi su milioni di console e PC. I team operativi li utilizzano per applicare il parental control e rilevare pattern di sessione anomali.
I eventi di sessione provenienti sia da console che da PC fluiscono nei topic Kafka. Ogni evento contiene un ID dispositivo e un ID sessione. L'ID dispositivo identifica la console o il PC; l'ID sessione identifica la sessione di gioco. Può essere attiva solo una sessione per dispositivo alla volta.
La pipeline gestisce quattro scenari:
Spark Structured Streaming in modalità micro-batch può gestire la sessionizzazione con stato, ma quando il caso d'uso richiede una precisione inferiore al secondo sia per l'elaborazione degli input che per l'output basato su timer, il micro-batch non è sufficiente. In passato, questo divario spingeva i team a gestire motori specializzati aggiuntivi o a creare soluzioni personalizzate.
Con Apache Flink: è possibile implementare la gestione dello stato e i timer, ma adottare Flink significa adottare un intero ecosistema parallelo: un cluster separato, uno state backend, un modello di deployment, uno stack di monitoraggio e una codebase, il tutto insieme alla piattaforma Databricks. Il risultato è la frammentazione dell'infrastruttura, la complessità operativa e i costi di gestione e personale per un secondo motore di streaming.
Con soluzioni interne personalizzate: alcuni team creano il proprio servizio di sessionizzazione, ad esempio un sistema di attori basato su Akka in cui ogni dispositivo riceve un attore che gestisce lo stato della sessione, i timer e l'emissione di heartbeat. Questi comportano lo stesso sovraccarico infrastrutturale e operativo di Flink, con una sfida in più: non sono scalabili. Distribuire milioni di attori con stato tra i nodi è qualcosa che devi progettare da solo. Questi sistemi funzionano inizialmente, ma nel tempo finiscono in modalità di manutenzione: abbastanza stabili da funzionare, ma non facilmente estensibili.
Oggi, Real-Time Mode colma questo divario per i clienti, offrendo una precisione inferiore al secondo con le stesse API Spark che i team già utilizzano, il tutto in un unico motore unificato.
transformWithState è un operatore di nuova generazione in Spark Structured Streaming che rende flessibile e scalabile l'elaborazione complessa con stato. Le caratteristiche principali includono la gestione dello stato orientata agli oggetti, tipi di dati compositi, logica basata su timer, supporto automatico TTL e l'evoluzione dello schema. Combinato con Real-Time Mode, offre una precisione inferiore al secondo sia per l'elaborazione degli input che per l'output basato su timer.
Il caso d'uso della sessionizzazione nel gaming richiede due cose:
transformWithState offre entrambe le funzionalità in una singola classe StatefulProcessor con due metodi dedicati.
handleInputRows() reagisce agli eventi Kafka in arrivo, elaborando l'inizio e la fine delle sessioni e mantenendo lo stato di sessionizzazione man mano che arrivano gli eventi.
handleExpiredTimer() gestisce tutto ciò che accade nel mezzo, attivandosi per produrre output proattivi come heartbeat e timeout, indipendentemente dall'arrivo di nuovi dati.

Per una panoramica dettagliata dell'architettura, dell'implementazione del codice e delle considerazioni sulla produzione, consulta questo blog di accompagnamento , in cui esaminiamo il codice StatefulProcessor, il ciclo di vita dei timer, i pattern di gestione dello stato e il monitoraggio con StreamingQueryListener. I seguenti risultati illustrano le caratteristiche di throughput e latenza della pipeline, evidenziando le significative differenze di latenza tra la modalità micro-batch (MBM) e la Real-Time Mode (RTM):
Per convalidare la pipeline in condizioni di carico reali, abbiamo effettuato dei test con il seguente throughput sostenuto:
Metrica (al minuto) | Valore |
Eventi di input (inizi + fini sessione) | ~500.000 |
Numero di sessioni attive | ~4 milioni |
Record di heartbeat emessi | ~8 milioni |
Amplificazione input-to-output | ~16x |
La stragrande maggioranza dell'output non è attivata dai dati in arrivo, ma è generata interamente da handleExpiredTimer(), che emette proattivamente heartbeat in modo pianificato.
La latenza viene misurata end-to-end, dal timestamp del topic Kafka di input al timestamp del topic di output. Con la Real-Time Mode, la pipeline raggiunge una latenza p99 di 432 ms, ovvero 20 volte più veloce rispetto alla modalità micro-batch.

Casi d'uso come la sessionizzazione dei giochi richiedono pipeline che vanno oltre l'elaborazione degli eventi in arrivo: emettere in modo proattivo heartbeat secondo una pianificazione, tracciare milioni di sessioni simultanee e gestire lo stato in modo efficiente. Questo pattern non è limitato al gaming. Qualsiasi carico di lavoro che necessiti di un output basato su timer (heartbeat IoT, tracciamento delle sessioni, avvisi in tempo reale, monitoraggio delle apparecchiature) può essere creato nello stesso modo.
I timer in transformWithState rendono tutto questo possibile. Una singola classe StatefulProcessor gestisce l'intero ciclo di vita della sessione: elaborazione reattiva degli input e output proattivo basato su timer. In combinazione con la Real-Time Mode, i record di input vengono elaborati e i timer si attivano con una precisione inferiore al secondo, non al successivo intervallo di batch, ma subito. Tutto all'interno di Databricks, senza un secondo motore.
Se utilizzi già pipeline di Structured Streaming in modalità micro-batch e stai cercando un secondo motore per ottenere una latenza inferiore, prova prima la Real-Time Mode. Il passaggio richiede solo la modifica di un singolo trigger: nessuna riscrittura, nessuna migrazione di piattaforma:
Provalo tu stesso:
La Real-Time Mode è ora generalmente disponibile.
(Questo post sul blog è stato tradotto utilizzando strumenti basati sull'intelligenza artificiale) Post originale
Iscriviti al nostro blog e ricevi gli ultimi articoli direttamente nella tua casella di posta.