Design del sistema: server di chat scalabile

4

Supponiamo che ti sia stato chiesto di progettare un server di chat scalabile con i seguenti requisiti:

  1. Il caso d'uso principale è: il giocatore A vede B online, A manda un messaggio a B, B lo riceve.
  2. Il caso d'uso secondario è: il giocatore A vede B offline , A manda un messaggio a B. Quando B torna online, B riceve il messaggio. (Nessuna notifica push).
  3. L'obiettivo è ridurre al minimo la latenza. La velocità conta.
  4. I messaggi dovrebbero arrivare in ordine. Non possiamo perdere i messaggi ma ricevere i duplicati una volta ogni tanto va bene.
  5. Solo dati di testo, nessun dato binario.
  6. Non è necessario memorizzare la cronologia chat. Una volta inviati, i messaggi possono essere distrutti.

Ho letto questo articolo: Come League of Legends ha scalato la chat con 70 milioni di giocatori e penso di aver perso l'architettura di base che hanno usato nel gioco. Ma comunque qui è il mio "processo di pensiero". Qualcuno può dargli un'occhiata?

  • Se il caso d'uso secondario non esistesse, non dovrei memorizzare nulla. Penso che potrei usare una rete p2p, in cui un utente invia regolarmente un messaggio ping "Sono online" a tutti i suoi amici per notificare la presenza.
  • Ma dal momento che devo archiviare i messaggi per poterli consegnare in un secondo momento, ho bisogno dei miei server che memorizzino la presenza degli utenti, gli elenchi di amicizia degli utenti e i messaggi.
  • L'obiettivo della latenza ridotta può essere ottenuto posizionando i server vicino agli utenti. Ciò significa che ci saranno più server in modo che debbano rimanere sincronizzati. Inoltre, dobbiamo bilanciare il carico in modo che un server non memorizzi tutto.
  • Ho letto da qualche parte su Internet che un modo per bilanciare il carico dei server è assegnare un server a ciascun utente. Ad esempio, al server 1 viene assegnato tutto ciò che riguarda l'utente A e al server 2 viene assegnato tutto ciò che riguarda l'utente B. Potremmo decidere in base alla vicinanza.
  • Quando A invia qualcosa a B, deve esserci un modo per inviare il messaggio al server 2. Forse usare un bus di servizio per comunicare i server.
  • Quindi il flusso sarebbe qualcosa del genere:

    1. Un messaggio di scrittura "Ciao B!"
    2. Il server 1 riceve il messaggio e B. Poiché non trova B nella propria base utente, inoltra il messaggio al bus di servizio. Memorizza una copia del messaggio.
    3. Il bus di servizio richiede a tutti i server di cercare l'utente B.
    4. Il server 2 risponde che ha B nella sua base di utenti.
    5. Il server 2 riceve il messaggio e lo memorizza.
    6. Il server 2 invia un messaggio all'utente B.
    7. Il server 2 segnala al bus di servizio che il messaggio è stato inviato. Distrugge il messaggio.
    8. Il server 1 distrugge la sua copia del messaggio.
  • Se B fosse offline, tutto il passaggio 5 rimarrebbe lo stesso. La differenza è che il server 1 può distruggere la sua copia del messaggio ma il server 2 non può.

  • Ora, archiviazione ... La mia ipotesi è che ogni server debba avere la propria memoria permanente, ma non ho idea di cosa dovrebbe essere ottimizzato qui (velocità di lettura della velocità di scrittura?). Inoltre non sono sicuro che un negozio MySQL o un negozio NoSQL sarebbe meglio. Dato che NoSQL è ottimizzato per essere partizionato e non è necessario, suppongo che MySQL sia sufficiente.
  • Se un server si arresta in modo anomalo, è necessario un modo rapido per eseguire il failover. Suppongo che potremmo posizionare come un server "primario" e "secondario" in ogni posizione, il primario sarebbe connesso allo storage primario e il secondario ai dati replicati.

Quindi l'architettura generale sarebbe simile a questa:

Mi rendo conto che mi mancano molte cose qui, mi sono perso qualcosa di ovvio? C'è qualche parte del mio processo di pensiero semplicemente sbagliato?

    
posta Maria Ines Parnisari 10.01.2017 - 16:18
fonte

0 risposte

Leggi altre domande sui tag