socket.io rooms or namespacing? - node.js

I am investigating nodejs/socket.io for real time chat, and I need some advice for implementing rooms.
Which is better, using namespace or using the room feature to completely isolate grops of chatters from each other?
what is the real technical difference between rooms and namespace?
Is there any resource usage difference?

This is what namespaces and rooms have in common (socket.io v0.9.8 - please note that v1.0 involved a complete rewrite, so things might have changed):
Both namespaces (io.of('/nsp')) and rooms (socket.join('room')) are created on the server side
Multiple namespaces and multiple rooms share the same (WebSocket) connection
The server will transmit messages over the wire only to those clients that connected to / joined a nsp / room, i.e. it's not just client-side filtering
The differences:
namespaces are connected to by the client using io.connect(urlAndNsp) (the client will be added to that namespace only if it already exists on the server)
rooms can be joined only on the server side (although creating an API on the server side to enable clients to join is straightforward)
namespaces can be authorization protected
authorization is not available with rooms, but custom authorization could be added to the aforementioned, easy-to-create API on the server, in case one is bent on using rooms
rooms are part of a namespace (defaulting to the 'global' namespace)
namespaces are always rooted in the global scope
To not confuse the concept with the name (room or namespace), I'll use compartment to refer to the concept, and the other two names for the implementations of the concept. So if you
need per-compartment authorization, namespaces might be the easiest route to take
if you want hierarchically layered compartments (2 layers max), use a namespace/room combo
if your client-side app consists of different parts that (do not themselves care about compartments but) need to be separated from each other, use namespaces.
An example for the latter would be a large client app where different modules, perhaps developed separately (e.g. third-party), each using socket.io independently, are being used in the same app and want to share a single network connection.
Not having actually benchmarked this, it seems to me if you just need simple compartments in your project to separate and group messages, either one is fine.
Not sure if that answers your question, but the research leading up to this answer at least helped me see clearer.

It's an old question but after doing some research on the topic I find that the accepted answer is not clear on an important point. According to Guillermo Rauch himself (see link):
although it is theoretically possible to create namespaces dynamically on a running app you use them mainly as predefined separate sections of you application. If, on the other hand you need to create ad hoc compartments, on the fly, to accommodate groups of users/connections, it is best to use rooms.

It depends what you wanna do.
The main difference is that rooms are harder to implement.
You must make a method for join the rooms with each page reload.
With namespaces you just need to write var example = io.connect('http://localhost/example'); in your javascript client and client are automatically added in the namespaces.
Example of utilization:
rooms: private chat.
namespaces: the chat of the page.

Rooms and namespaces segment communication and group individual sockets.
A broadcast to a room or to a namespace will not reach everyone just the members.
The difference between namespaces and rooms is the following:
Namespaces: are managed in the frontend meaning the user, or an attacker, joins through the frontend and the joining and disconnecting is managed here.
Rooms: are managed in the backend, meaning the server assigns joining and leaving rooms.
The difference is mainly who manages them
To decide what to use you must decide if the segmentation should be managed in the frontend or in the backend

There can be rooms within namespaces, which helps to organize the code but there cannot be namespaces inside of rooms. So namespace is a top level segmentation and rooms is a lower level one.

Namespaces allow you to create objects with the same name, but they would be separate as they will live in different namespaces, otherwise known as scopes.
This is the same thought process you should have with Socket.IO namespaces. If you are building a modular Node web application, you will want to namespace out the different modules. If you look back at our namespace code, you will see that we were able to listen for the same exact events in different namespaces. In Socket.IO, the connection event on the default connection and connection event on a /xxx namespace are different. For example, if you had a chat and comment system on your site and wanted both to be real time, you could namespace each. This allows you to build an entire Socket.IO application that lives only in its own context.
This would also be true if you were building something to be packaged and installed. You cannot know if someone is already using certain events in the default namespace, so you should create your own and listen there. This allows you to not step on the toes of any developer who uses your package.
Namespaces allow us to carve up connections into different contexts. We can compare this to rooms, which allow us to group connections together.We can then have the same connection join other rooms, as well.
Namespaces allow you to create different contexts for Socket.IO to work in. Rooms allow you to group client connections inside of those contexts.

Related

Uniqueness of socket.id of websocket in distributed web applications

Suppose you want to scale your web application that relies on websocket technology (e.g Socket.io library). You have multiple servers and you are using a shared database (e.g Redis) to have a communication with these servers.
In this case you store socket ids of each socket connection in that db. My question is:
Is it possible that two users that are connected to two different
servers get the same socket.id so that you couldn't differentiate them?
In this case, if you want to notify a specific user, you will do it for another user too!
How it is possible?
If it is possible how people solve this problem in real world use cases ?
Is there any trick in programming or in the design ?
EDIT
I want to emphasize on distributed environments.

How to do personal chat using socke.io?

I'm new to node.js. I tried socket.io as it emits message to all clients, but I don't know how to do personal chat using socke.io, without using php.
I recommend you to explore the Rooms and Namespaces section of socket.io documentation. It is designed for the exact use cases you are looking for.
Socket.IO allows you to “namespace” your sockets, which essentially
means assigning different endpoints or paths.
This is a useful feature to minimize the number of resources (TCP
connections) and at the same time separate concerns within your
application by introducing separation between communication channels.
About rooms:
Within each namespace, you can also define arbitrary channels that sockets can join and leave.
So each conversation would be single channel with two subscribers. To ensure privacy you can use a unique token as channel identifier that is distributed to only the relevant parties.

Communication between RESTful API's on same server with NodeJS

I am building two sets of services on a website (all written in NodeJS on the server), both are using a RESTful approach. For the sake of modularity I decided to make both services separate entities. The first service deals with the products of the site and the second specifically deals with user related functions. So the first might have functions like getProducts, deleteProduct etc... The second would have functions like isLoggedIn, register, hasAccessTo etc... The product module will make several calls to the user module to make sure that the person making the calls has the privilege to do so.
Now the reason I separated them like this, was because in the near future I foresee a separate product range opening up, but will need to use the same user system as the first (even sharing the same database). The user system will use a database that spans the entire site and all subsequent products
My question is about communication between these projects and the users project. What is the most effective way of keeping the users module separate without suffering any significant speed hits. If the product API made a call to the user API on the same server (localhost), is there a signifcant cost to this, versus building the user API into each of the subsequent projects? Is there a better way to do this through interprocess communication maybe? Is simply having the users API run as its own service an effective solution?
If you have two nodes on same server (machine) then you have not bad performance in terms of network latency because both are on localhost.
Then, nodes will be communicating using a rest api, so on the underground, you will use node js sockets. You could use unix sockets instead of http sockets because are faster BUT are worst to debug, so I recommend you don't to that (but it's ok know alternatives).
And finally, your system looks like an "actor design pattern". At first glance this design patter is a little difficult to understand but you could have a look at this if you want more info about actor model pattern:
Actor model for NodeJS https://github.com/benlau/nactor
Actor model explanation http://en.wikipedia.org/wiki/Actor_model

How to make a node.js server with rooms scalable

I have designed a Node.JS server that allows users to log in, join a room and exchange data with other users in this room using websockets. However I am now looking for a way to make this setup scalable.
I spend all afternoon researching various loadbalancers such as nginx and haproxy, but I still can't figure out how to organise my setup.
Initally users can login and view the active rooms. No biggie to makes this part scalable. However then they can join a specific room and at that point they need to be connected to the same node.js instance as the others in the room. It's this part I have trouble figuring out.
For now my solution exists out of creating two different types of node.js instances. One generic type to handle the login and room overview request methods and one roomtype that handle a number of rooms. The generic type then keeps track of which specific instance is responsible for which room and can deliver the correct address to the user's application.
However I am not satisfied with this solution, so I am open for suggestions. I understand that this is a rather vague question, but I am not looking for a exact solution, rather hints as to how to organize everything.
udidu touched on a possible solution, but to expand, you should look at a scalable pub/sub solution; Redis, a popular data store, has pub/sub built in and I use it often to great effect.
Using Redis (or some other system) to help make sure every instance of your Node.js app receives information about who's chatting in which room removes the dependency that all users in a room are connected to the same Node.js instance.

Building a web app to support team collaboration using Socket.io

I'm building a web application that will allow team collaboration. That is, a user within a team will be able to edit shared data, and their edits should be pushed to other connected team members.
Are Socket.io rooms a reasonable way of achieving this?
i.e. (roughly speaking):
All connected team members will join the same room (dynamically created upon first team member connecting).
Any edits received by the
server will be broadcast to the room (in addition to being persisted,
etc).
On the client-side, any edits received will be used to update
the shared data displayed in the browser accordingly.
Obviously it will need to somehow handle simultaneous updates to the same data.
Does this seem like a reasonable approach?
Might I need to consider something more robust, such as having a Redis database to hold the shared data during an editing session (with it being 'flushed' to the persistant DB at regular intervals)?
All you need is Socket.IO (with RedisStore) and Express.js. With Socket.IO you can setup rooms and also limit the access per room to only users who are auth.
Using Redis you can make your app scale outside a process.
Useful links for you to read:
Handling Socket.IO, Express and sessions
Scaling Socket.IO
How to reuse redis connection in socket.io?
socket.io chat with private rooms
How to handle user and socket pairs with node.js + redis
Node.js, multi-threading and Socket.io

Resources