Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reliable messaging under socket.io?

Tags:

The API provides the emit/send callback mechanism to acknowledge received messages. However, this callback doesn't get fired in case of disconnect or error. It appears to me that upon a disconnection one would need to go through some rather messy procedures to clean up outstanding sent messages (e.g. - assume a use case where you may want to store messages for forwarding later, etc.). Any simple ideas out here on how to accomplish this? Wondering if I'm missing something.... Thanks.

like image 366
Mark Avatar asked Mar 06 '12 04:03

Mark


People also ask

Is Socket.IO good for chat?

This is an organization based application. In this app, I have to implement chat functionality. So as we all know Socket.io is the best solution for instant messaging app and its reliability.

How many messages per second can Socket.IO handle?

Both server and client node processes use 95-100% of a CPU core each. So pure throughput looks ok. I can emit 100 messages per second to 100 local clients at 55% CPU usage on the server process.

What is Socket.IO good for?

Socket.IO is a library that enables low-latency, bidirectional and event-based communication between a client and a server. It is built on top of the WebSocket protocol and provides additional guarantees like fallback to HTTP long-polling or automatic reconnection.

How do I check if a message sent through Socket.IO is read?

You will have to send a message back when the message is read. There is no notion of when something is "read" in socket.io. That's something you would have to invent in your own user interface and when you consider it read, you could send a message back to the sender that indicates it is now read.


1 Answers

The Real Underlying Issue

This issue isn't just limited to socket.io. It is a well known problem called the Two Generals' Problem.

Two armies, each led by a general, are preparing to attack a fortified city. The armies are encamped near the city, each on its own hill. A valley separates the two hills, and the only way for the two generals to communicate is by sending messengers through the valley. Unfortunately, the valley is occupied by the city's defenders and there's a chance that any given messenger sent through the valley will be captured (this scenario assumes that while the two generals have agreed that they will attack, they haven't agreed upon a time for attack before taking up their positions on their respective hills).

You are trying to reach Common Knowledge over an unreliable link.

At any stage of the communication over socket.io the link can be broken, and a callback can be sent but the other side could not be sure that it arrived.

What Can Be Done

You need to embrace the fact this is always a possibility. There is no trivial solution for this. This problem and its generalization are still actively studied in fields like Multi-Agent Systems research.

What can still be done in your specific case

There are some common approaches to mitigate this issue.

What I did when designing an application using socket.io is attach IDs to messages, if a disconnect happens and one side tried to send an already-sent message, the receiving side will be aware that the message was already received.

Note that in practice you don't need to do this everywhere.

More Reading on the Issue

  • Related question here in SO
  • The Byzantine Generals Problem by Microsoft Research (LESLIE LAMPORT, ROBERT SHOSTAK, and MARSHALL PEASE) which discusses the problem and suggests some solutions
  • Acclaimed Book by Yoav Shoham that talks about Multiagent systems and how they address this issue.
  • Blog post about this problem in TCP.
like image 64
Benjamin Gruenbaum Avatar answered Oct 22 '22 14:10

Benjamin Gruenbaum