Design: HTTP e Websockets che lavorano insieme

1

Sono qui a un bivio e volevo chiedere l'opinione della comunità.

Sto creando un'applicazione di chat per la nostra azienda. Ora, come ogni applicazione di chat là fuori, i messaggi vengono salvati su un server che consente al client, in un secondo momento, di accedere ai vecchi messaggi.

Quello che mi manca è l'utilizzo di HTTP e WebSocket insieme in una situazione specifica. Li sto già usando, perfettamente bene e tutto funziona senza intoppi. La mia attuale scelta progettuale è questa:

  1. Il client invia un evento new message su un WebSocket al server con un payload del messaggio
  2. Il server riceve questo evento new message
  3. Il server di fa un async chiama a un mongodb server che salva il messaggio con il messaggio richiesto
  4. Quando effettua la chiamata di async al DB, invia anche un evento socket agli altri client con il messaggio fornito

Il problema che vedo è che cosa succede se la chiamata di async al DB fallisce e il DB non salva effettivamente il messaggio? Il client può ricevere il messaggio, ma quando si disconnettono e ricollegano, il messaggio cesserà di esistere nella conversazione perché non è mai stato salvato nel DB.

Fortunatamente, questo non è successo nei test, ma sappiamo tutti che possiamo fare tutti i test nel mondo, e in qualche modo qualcosa si romperà. Mentre pensavo a questo problema, ho trovato una nuova soluzione al problema:

  1. Il client crea un messaggio e invia una richiesta POST al server
  2. Il server riceve questa richiesta POST
  3. Crea una chiamata async con await su di essa al DB
  4. Usando le promesse, l'operazione ha esito positivo o non riesce
  5. Se riesce, viene inviato un evento socket agli altri client e il client che ha inviato il messaggio riceve una risposta dal server che ha avuto successo
  6. Se fallisce, il client viene avvisato e l'evento socket non viene inviato

So che mantenere una connessione persistente ha un sovraccarico minore quando i messaggi vengono inviati avanti e indietro rispetto a fare una chiamata HTTP su ogni messaggio, ma le chiamate HTTP permetteranno al client di assicurarsi che il messaggio sia effettivamente inviato e salvato.

Ora, la mia idea originale può essere trasformata nella mia nuova idea usando async/await con esso e se fallisce, quindi non inviare il messaggio. Posso creare un nuovo evento socket che emette come error e il client lo visualizza di conseguenza.

Non riesco a decidere quale sarebbe meglio, e volevo chiedere se uno di questi modi è migliore o se ci sono opzioni ancora migliori là fuori per questo particolare design di applicazione.

Grazie!

    
posta Landon 01.07.2018 - 20:13
fonte

1 risposta

1

Combina entrambi, ovvero la tua terza opzione. Mantieni i messaggi websocket ma ordina l'ordine delle operazioni attendendo il risultato del database prima di notificare i client.

Pseudocodice:

function on_new_message(sender, msg):
  is_duplicate = await save_message_in_db_async(msg)
  // If this fails, catch the exception in some error handler.
  // The client could also retry
  // if they don't receive a reply within some timeout.
  // The DB can tell you whether this is a duplicate message.

  // At this point the message is saved.
  // new clients that join can load it from the DB

  sender_notification_future = notify_client_async(sender, {
      "type": "message_acknowledged",
      "msg_id": msg.id,
  })

  client_notification_futures = []
  if !is_duplicate:
    for client in connected_clients:
      if client != sender:
        client_notification_futures.push(
            notify_client_async(client, msg))

  // The order of notifications is not important,
  // so await them together
  await all(sender_notification_future, client_notification_futures)

In alternativa, la seconda opzione (utilizzando una richiesta POST per inviare il messaggio) non è un problema, presumendo che l'invio di messaggi sia infrequente (al massimo uno ogni pochi secondi) o che si stia utilizzando HTTP / 2. Questo potrebbe essere più semplice perché una richiesta POST ottiene una risposta chiara, mentre i websocket non impongono un ciclo di vita di richiesta / risposta. Il codice sembra fondamentalmente lo stesso, tranne che rispondi al mittente invece di inviare loro una notifica.

    
risposta data 01.07.2018 - 21:20
fonte

Leggi altre domande sui tag