55

I thought about getting rid of all client-side Ajax calls (jQuery) and instead use a permanent socket connection (Socket.IO).

Therefore I would use event listeners/emitters client-side and server-side.

Ex. a click event is triggered by user in the browser, client-side emitter pushes the event through socket connection to server. Server-side listener reacts on incoming event, and pushes "done" event back to client. Client's listener reacts on incoming event by fading in DIV element.

Does that make sense at all? Pros & cons?

DShah
  • 9,768
  • 11
  • 71
  • 127
ezmilhouse
  • 8,933
  • 7
  • 29
  • 38
  • 2
    Take a look at this: http://blog.nodejitsu.com/single-page-apps-with-nodejs – Mohsen Aug 25 '11 at 17:01
  • Detailed answer I made to a similar question: http://stackoverflow.com/questions/6806263/websocket-api-to-replace-rest-api/6829366#6829366 – Tauren Aug 26 '11 at 09:54

3 Answers3

74

There is a lot of common misinformation in this thread that is very inaccurate.

TL/DR; WebSocket replaces HTTP for applications! It was designed by Google with the help of Microsoft and many other leading companies. All browsers support it. There are no cons.

SocketIO is built on top of the WebSocket protocol (RFC 6455). It was designed to replace AJAX entirely. It does not have scalability issues what-so-ever. It works faster than AJAX while consuming an order of magnitude fewer resources.

AJAX is 10 years old and is built on top of a single JavaScript XMLHTTPRequest function that was added to allow callbacks to servers without reloading the entire page.

In other words, AJAX is a document protocol (HTTP) with a single JavaScript function.

In contrast, WebSocket is a application protocol that was designed to replace HTTP entirely. When you upgrade an HTTP connection (by requesting WebSocket protocol), you enable two-way full duplex communication with the server and no protocol handshaking is involved what so ever. With AJAX, you either must enable keep-alive (which is the same as SocketIO, only older protocol) or, force new HTTP handshakes, which bog down the server, every time you make an AJAX request.

A SocketIO server running on top of Node can handle 100,000 concurrent connections in keep-alive mode using only 4gb of ram and a single CPU, and this limit is caused by the V8 garbage collection engine, not the protocol. You will never, ever achieve this with AJAX, even in your wildest dreams.

Why SocketIO so much faster and consumes so much fewer resources

The main reasons for this is again, WebSocket was designed for applications, and AJAX is a work-around to enable applications on top of a document protocol.

If you dive into the HTTP protocol, and use MVC frameworks, you'll see a single AJAX request will actually transmit 700-900 bytes of protocol load just to AJAX to a URL (without any of your own payload). In striking contrast, WebSocket uses about 10 bytes, or about 70x less data to talk with the server.

Since SocketIO maintains an open connection, there's no handshake, and server response time is limited to round-trip or ping time to the server itself.

There is misinformation that a socket connection is a port connection; it is not. A socket connection is just an entry in a table. Very few resources are consumed, and a single server can provide 1,000,000+ WebSocket connections. An AWS XXL server can and does host 1,000,000+ SocketIO connections.

An AJAX connection will gzip/deflate the entire HTTP headers, decode the headers, encode the headers, and spin up a HTTP server thread to process the request, again, because this is a document protocol; the server was designed to spit out documents a single time.

In contrast, WebSocket simply stores an entry in a table for a connection, approximately 40-80 bytes. That's literally it. No polling occurs, at all.

WebSocket was designed to scale.

As far as SocketIO being messy... This is not the case at all. AJAX is messy, you need promise/response.

With SocketIO, you simply have emitters and receivers; they don't even need to know about each-other; no promise system is needed:

To request a list of users you simply send the server a message...

socket.emit("giveMeTheUsers");

When the server is ready, it will send you back another message. Tada, you're done. So, to process a list of users you simply say what to do when you get a response you're looking for...

socket.on("HereAreTheUsers", showUsers(data) );

That's it. Where is the mess? Well, there is none :) Separation of concerns? Done for you. Locking the client so they know they have to wait? They don't have to wait :) You could get a new list of users whenever... The server could even play back any UI command this way... Clients can connect to each other without even using a server with WebRTC...

Chat system in SocketIO? 10 lines of code. Real-time video conferencing? 80 lines of code Yes... Luke... Join me. use the right protocol for the job... If you're writing an app... use an app protocol.

I think the problem and confusion here is coming from people that are used to using AJAX and thinking they need all the extra promise protocol on the client and a REST API on the back end... Well you don't. :) It's not needed anymore :)

yes, you read that right... a REST API is not needed anymore when you decide to switch to WebSocket. REST is actually outdated. if you write a desktop app, do you communicate with the dialog with REST? No :) That's pretty dumb.

SocketIO, utilizing WebSocket does the same thing for you... you can start to think of the client-side as simple the dialog for your app. You no longer need REST, at all.

In fact, if you try to use REST while using WebSocket, it's just as silly as using REST as the communication protocol for a desktop dialog... there is absolutely no point, at all.

What's that you say Timmy? What about other apps that want to use your app? You should give them access to REST? Timmy... WebSocket has been out for 4 years... Just have them connect to your app using WebSocket, and let them request the messages using that protocol... it will consume 50x fewer resources, be much faster, and 10x easier to develop... Why support the past when you're creating the future?

Sure, there are use cases for REST, but they are all for older and outdated systems... Most people just don't know it yet.

UPDATE:

A LOT of people have been asking me recently how can they start writing an app in 2018 (and now soon 2019) using WebSockets, that the barrier seems really high, that once they play with Socket.IO they don't know where else to turn or what to learn.

Fortunately the last 3 years have been very kind to WebSockets...

There are now 3 major frameworks that support BOTH REST and WebSocket, and even IoT protocols or other minimal/speedy protocols like ZeroMQ, and you don't have to worry about any of it; you just get support for it out of the box.

Note: Although Meteor is by far the most popular, I am leaving it out because although they are a very, very well-funded WebSocket framework, anyone who has coded with Meteor for a few years will tell you, it's an internal mess and a nightmare to scale. Sort of like WordPress is to PHP, it is there, it is popular, but it is not very well made. It's not well-thought out, and it will soon die. Sorry Meteor folks, but check out these 3 other projects compared to Meteor, and you will throw Meteor away the same day :)

With all of the below frameworks, you write your service once, and you get both REST and WebSocket support. What's more, it's a single line of config code to swap between almost any backend database.

Feathers Easiest to use, works the same on the front and backend, and supports most features, Feathers is a collection of light-weight wrappers for existing tools like express. Using awesome tools like feathers-vuex, you can create immutable services that are fully mockable, support REST, WebSocket and other protocols (using Primus), and get free full CRUD operations, including search and pagination, without a single line of code (just some config). Also works really great with generated data like json-schema-faker so you can not only fully mock things, you can mock it with random yet valid data. You can wire up an app to support type-ahead search, create, delete and edit, with no code (just config). As some of you may know, proper code-through-config is the biggest barrier to self-modifying code. Feathers does it right, and will push you towards the front of the pack in the future of app design.

Moleculer Moleculer is unfortunately an order of magnitude better at the backend than Feathers. While feathers will work, and let you scale to infinity, feathers simply doesn't even begin to think about things like production clustering, live server consoles, fault tolerance, piping logs out of the box, or API Gateways (while I've built a production API gateway out of Feathers, Moleculer does it way, way better). Moleculer is also the fastest growing, both in popularity and new features, than any WebSocket framework.

The winning strike with Moleculer is you can use a Feathers or ActionHero front-end with a Moleculer backend, and although you lose some generators, you gain a lot of production quality.

Because of this I recommend learning Feathers on the front and backend, and once you make your first app, try switching your backend to Moleculer. Moleculer is harder to get started with, but only because it solves all the scaling problems for you, and this information can confuse newer users.

ActionHero Listed here as a viable alternative, but Feathers and Moleculer are better implementations. If anything about ActionHero doesn't Jive with you, don't use it; there are two better ways above that give you more, faster.

NOTE: API Gateways are the future, and all 3 of the above support them, but Moleculer literally gives you it out of the box. An API gateway lets you massage your client interaction, allowing caching, memoization, client-to-client messaging, blacklisting, registration, fault tolerance and all other scaling issues to be handled by a single platform component. Coupling your API Gateway with Kubernetes will let you scale to infinity with the least amount of problems possible. It is the best design method available for scalable apps.

Update for 2021:

The industry has evolved so much that you don't even need to pay attention to the protocol. GraphQL now uses WebSockets by default! Just look up how to use subscriptions, and you're done. The fastest way to handle it will occur for you.

If you use Vue, React or Angular, you're in luck, because there is a native GraphQL implementation for you! Just call your data from the server using a GraphQL subscription, and that data object will stay up to date and reactive on it's own.

GraphQL will even fall-back to REST for you when you need to use legacy systems, and subscriptions will still update using sockets. Everything is solved when you move to GraphQL.

Yes, if you thought "WTH?!?" when you heard you can simply subscribe, like with FireBase, to a server object, and it will update itself for you. Yes. That's now true. Just use a GraphQL subscription. It will use WebSockets.

Chat system? 1 line of code. Real time video system? 1 line of code. Video game with 10mb of open world data shared across 1m real-time users? 1 line of code. The code is just your GQL query now.

As long as you build or use the right back-end, all this realtime stuff is now done for you with GQL subscriptions. Make the switch as soon as you can and stop worrying about protocols.

Community
  • 1
  • 1
Nick Steele
  • 7,419
  • 4
  • 36
  • 33
  • A lot of the pitfalls you mention concerning ajax are solved with https://http2.github.io/ – Kevin B Dec 21 '15 at 20:12
  • HTTP/2 is not supported by all browsers, SocketIO is. HTTP/2 is still a document protocol that transfers headers. WebSocket is intended to be the thing that we use after the connection is established. – Nick Steele Dec 21 '15 at 20:19
  • Regarding the comment about socket.io being faster than ajax. The amount of data transmitted up to the side of one network frame will take the same amount of time. Typically 1 packet can hold up to 1500. Transmitting a request that's 80 bytes, or 1400 bytes will take exactly the same amount of time. Really, at this point it will be a function of your network latency. In fact http://www.cubrid.org/blog/cubrid-appstools/nodejs-speed-dilemma-ajax-or-socket-io/ tests shows that ajax was only slightly slower than socket.io over a constant connection. – Atif Feb 10 '16 at 21:12
  • The comparison you listed is from someone who doesn't understand what Socket.IO offers. They were using the AJAX method of Socket.IO, otherwise there is no way it would actually be significantly slower than AJAX, as obviously an open socket requires no handshake :) Also, the tester claimed AJAX is faster to code... evented systems require no promises. Also, the overhead of the 1400 bytes you'll be compressing/decompressing, parsing and otherwise holding in memory may be fine for a single client, but what about a server with 10,000 connections? – Nick Steele Feb 12 '16 at 00:03
  • 1
    @NickSteele an old post, but thanks for the awesome and thorough information on socket.io. Can you help me understand what the HEARTBEAT implementation in socket.io does and how to use it? Im working on proposing something to my coworkers and I know one thing they'll raise as potential issue is 'what about lost connections'? – tamak Feb 21 '16 at 03:14
  • I think you're referring to basically a keepalive, just a confirmation that the client and server are both running. Only a few bytes are transferred. There are proofs online that show you can connect over 500,000 clients to a single server (with enough memory) with heartbeats, or general idle connection status. In Socket.IO, when you loose a connection and re-establish, any events that were meant for a client or for the server are *automatically* resent when the connection is established. Socket.IO certainly beats XHR/AJAX on every level; it was designed to replace it. – Nick Steele Feb 22 '16 at 15:26
  • A very interesting answer, thanks for that but I think there is no need to sound like a 5 year old raging though – Hassek Jan 23 '17 at 14:46
  • 3
    @Hassek Thank you for the comment and noted... I will try to act as if I've hit puberty in the future. – Nick Steele Jan 23 '17 at 20:58
  • Thank you for the informative answer. Do you know of any downsides with regards to a cellular tablet web app? We have AJAX polling every 20 seconds, being used for hours, and doesn't seem to run down the battery or use too much data. It also persists through cellular ATT network disconnects / reconnects. Do you think Socket.IO could also help in this case? Do you know of possible effects on battery life or problems with cellular internet re-connections? Thanks. – wayofthefuture Mar 26 '17 at 18:01
  • @wayofthefuture WebSocket has 2 orders of magnitude less processing vs HTTP to complete identical tasks, i.e. no gzip/headers/text processing, however, if you are only polling once per 20 seconds, the difference it will make will certainly be less than 0.001% of an avg. tablet battery because this processing is going to be less than 0.0000001% of your CPU cycles. The biggest draw is going to be data transfer (a cell will use 5 watts to transfer packets) - and both a websocket and HTTP packet will usually be within the MTU (size per packet) and so consume identical data transfer draw. – Nick Steele Mar 28 '17 at 00:11
  • 3
    The last part of your answer was golden. I love Timmy. Very informative. Good job. – kemicofa ghost Aug 16 '17 at 20:56
  • 3
    Amazing answer. This clarified a lot of concerns that most people have. Your passion for the technology shows in your answer :) – raja kolluru Aug 22 '17 at 02:49
  • love the answer, that Timmy is such a young buck! – buycanna.io May 01 '19 at 04:00
23

Socket.IO uses persistent connection between client and server, so you will reach a maximum limit of concurrent connections depending on the resources you have on server side, while more Ajax async requests can be served with the same resources.

Socket.IO is mainly designed for realtime and bi-directional connections between client and server and in some applications there is no need to keep permanent connections. On the other hand Ajax async connections should pass the HTTP connection setup phase and send header data and all cookies with every request.

Socket.IO has been designed as a single process server and may have scalability issues depending server resources that you are bound to.

Socket.IO in not well suited for applications when you are better to cache results of client requests.

Socket.IO applications face with difficulties with SEO optimization and search engine indexing.

Socket.IO is not a standard and not equivalent to W3C Web Socket API, It uses current Web Socket API if browser supports, socket.io created by a person to resolve cross browser compatibility in real time apps and is so young, about 1 year old. Its learning curve, less developers and community resources compared with ajax/jquery, long term maintenance and less need or better options in future may be important for developer teams to make their code based on socket.io or not.

Reza Hashemi
  • 1,768
  • 14
  • 13
  • 3
    Some good points here, except for the last two. SEO problems are as applicable to Ajax-based sites as those using web sockets. Socket.io will use the browsers W3C Web Socket implementation where available, and only fall back to other methods when not. – roryf Aug 25 '11 at 16:20
  • 2
    one good point is the limited number of concurrent connections, the SEO thing is history - http://code.google.com/web/ajaxcrawling/docs/getting-started.html – ezmilhouse Aug 25 '11 at 21:17
  • @ezmilhouse - what do you mean? how is it history? – vsync Aug 03 '15 at 15:58
  • This is completely off. With Ajax you launch 1 thread per request. With WebSocket you add 1 object to an array... About 80 bytes for a basic connection. That means if you have a minimal app, you can connect about 1 million users on a single server with about 80mb of data, in a single thread, meaning all users can exchange messages in the same thread... this is many orders of magnitude *more* efficent. There is no way on Earth you could support 1 million ajax requests on a single server, much less a single thread :) – Nick Steele Aug 29 '17 at 17:27
  • If you use Google cloud app engine, the number of users on a server won't be an issue because of the automatic creation of a new server instance when resources are taken up. – SwiftNinjaPro Dec 18 '19 at 01:20
6

Sending one way messages and invoking callbacks to them can get very messy.

$.get('/api', sendData, returnFunction); is cleaner than socket.emit('sendApi', sendData); socket.on('receiveApi', returnFunction);

Which is why dnode and nowjs were built on top of socket.io to make things manageable. Still event driven but without giving up callbacks.

Talha Awan
  • 4,573
  • 4
  • 25
  • 40
generalhenry
  • 17,227
  • 4
  • 48
  • 63
  • thx a lot, nowjs was exactly what I was looking for, I love this new world. Any security concerns? – ezmilhouse Aug 25 '11 at 21:18
  • There are some minor security concerns with the websockets protocol (no exploits but known weaknesses) and they're being sorted out. If there every are exploits you can simply turn off websockets. – generalhenry Aug 25 '11 at 21:31
  • 4
    This answer is akin to saying light bulbs are messy because when you try to light them, they make carbon scoring and eventually break and pop, so you should stick with fire. You're doing it wrong. events need no callbacks in the first place :) You're using the right tech (events) and the wrong paradigm (callbacks). Events let you simply make calls (no backs). With events you *do not* make requests, you make declarations. You aren't asking for something, you're simply saying what happened. socket.emit('clickedLogin'). Then when login works, Node sends socket.emit('loadApp'). Boom, done. – Nick Steele Aug 29 '17 at 17:20
  • 1
    With socket.io, it provides callback `socket.emit('sendApi', sendData, returnFunction)` – andyf Aug 01 '19 at 06:06