Zampa Games — MMORPG browser a microservizi
Undici servizi, fisica in tempo reale su Socket.IO e NPC guidati da FSM, RL e un LLM.
- .NET 8
- YARP
- Node.js
- Socket.IO
- Python
- FastAPI
- Three.js
- PostgreSQL
- Redis
- MongoDB
- RabbitMQ
Il problema
Un gioco multiplayer in tempo reale mette sotto pressione tutto insieme: latenza, stato condiviso, autorevolezza del server e costo per giocatore. Volevo capire dove si rompe davvero un'architettura a microservizi, e l'unico modo onesto era costruirne una che dovesse reggere sessantina di aggiornamenti al secondo.
Risultato
Undici servizi coordinati, con la fisica separata dalla logica di dominio e l'IA degli NPC isolata in un servizio proprio. Il sistema non è attualmente in esecuzione: l'ho spento per liberare risorse sul server.
Questo progetto non è attualmente online: gira su un Raspberry Pi condiviso con altri sistemi e l’ho rimosso per liberare memoria e disco. È incluso qui perché il codice e le decisioni architetturali restano il pezzo più interessante che ho scritto.
La divisione dei servizi
| Servizio | Tecnologia | Ruolo |
|---|---|---|
api-gateway |
.NET 8 + YARP | Reverse proxy HTTP e WebSocket |
user-be |
.NET 8 | Autenticazione, inventario, quest, gilde |
physics-server |
Node.js + Socket.IO | Fisica, combattimento e NPC in tempo reale |
ai-service |
Python + FastAPI | Comportamento degli NPC |
game-client |
Three.js + Vite | Client 3D nel browser |
ai-dashboard |
React | Metriche del comportamento IA |
Sotto: PostgreSQL per i dati relazionali, Redis per la cache, MongoDB per i documenti e RabbitMQ per gli eventi fra servizi.
Perché la fisica sta da sola
Il ciclo di simulazione ha un vincolo che nessun altro servizio ha: deve chiudere ogni frame entro una finestra fissa. Metterlo nello stesso processo della logica di dominio significa che una query lenta sull’inventario diventa uno scatto visibile a schermo. Separarlo permette di scalarlo secondo una metrica diversa — giocatori simultanei per zona, non richieste al secondo.
NPC: tre livelli, non uno
Il comportamento degli NPC combina tre meccanismi con costi molto diversi:
- Macchina a stati finiti per le decisioni immediate: pattugliare, inseguire, fuggire. Costo trascurabile, esecuzione a ogni tick.
- Reinforcement learning per le politiche che si affinano nel tempo.
- Modello linguistico come consulente, non come pilota: interviene di rado, per il dialogo e le decisioni di alto livello.
La regola che rende il sistema sostenibile è la terza: un LLM chiamato a ogni frame è impagabile in tutti i sensi del termine. Il modello suggerisce, la macchina a stati esegue.
Cosa mi ha insegnato
Che il numero giusto di microservizi è quello che i confini del dominio impongono, non quello che sembra moderno. Undici servizi per un progetto personale sono molti, e la parte più costosa non è stata scriverli: è stata tenere allineati i contratti fra di loro.