SocketCluster / socketcluster-client

JavaScript client for SocketCluster
MIT License
292 stars 91 forks source link

[Question] Private messages #39

Closed zalmoxisus closed 8 years ago

zalmoxisus commented 8 years ago

Is there a way to emit a message from one socket to another one (knowing the socket.id) instead of creating a channel, subscribing to it and adding a middleware to prevent watching it by other users (which is somehow cumbersome)?

jondubois commented 8 years ago

Yes but you should keep in mind that a user could have multiple sockets open (on different browser tabs for example).

There are multiple ways to do what you want:

  1. If you only intend to ever have 1 worker process, then on the client you can simply emit the message to the server, then you can handle that event from inside your worker, then get a reference to the target client socket using the scServer.clients property here: http://socketcluster.io/#!/docs/api-scserver and then emit the message to that socket directly. Note that this approach is not scalable - As soon as you add a second worker, half of the sockets will be hosted by a different worker than the one which is handling the message so it won't work. This approach is not recommended.
  2. You can setup backend-only channels using the worker.exchange object here: http://socketcluster.io/#!/docs/api-scworker. With this approach; whenever a new socket becomes connected, you can create a new channel from the server which is based on that socket's ID and subscribe to it (E.g. worker.exchange.subscribe('someSocketId123').watch(handlerFunction)) - The handlerFunction can then just capture all messages published to that channel and forward them to the appropriate client socket using socket.emit(...). Your server logic will be responsible for listening to events from clients using socket.on(eventName, handler) and relaying them to the appropriate backend channel using worker.exchange.publish('someSocketId123', message). You may want to set the allowClientPublish config of SC to false (see http://socketcluster.io/#!/docs/api-socketcluster) so that only the server can publish to channels. The idea of this approach would be to setup all channels on the backend only - That way clients only communicate to the server using socket.emit(...) and by listening to events using socket.on(...). Unlike the first approach, this one can scale quite well, but it means you have to manage channels on the backend (you have to remember to unsubscribe and destroy() the channel when the socket disconnects for example).

I think handling the channels on the frontend is generally a better/simpler approach overall but I understand that every case is different.

zalmoxisus commented 8 years ago

Thanks a lot for such a detailed explanation!

The first approach is exactly what I was searching for, but I see it is not scalable unless we find a way to notify all workers, and the one who handle such client id will emit the message (which I think is a worth direction to explore).

What concerns me in the second approach is the performance. Having thousands of users means handling thousands of channels (additionally to the regular ones) just in case some users may receive some messages once in a while. Maybe I am mistaken and pub/sub is fast enough to ignore it?

jondubois commented 8 years ago

Channels in SC are pretty efficient, you can have many thousands of channels. The main problem would be if they all tried to subscribe at the same time (which could happen after a worker crash). But you can tweak the reconnect options to add randomness to the reconnect delay in socketcluster-client.

zalmoxisus commented 8 years ago

Thanks a bunch! It's awesome to have such a complex functionality done in just few lines of code. SocketCluster is a brilliant and handy piece of software!

In case someone will follow this instruction, we have also not to forget to set socketChannelLimit to a higher value, as we will have maximum 1000 users by default. Maybe is there a way to set it to unlimited?

jondubois commented 8 years ago

@zalmoxisus Note that there was an issue with the socketChannelLimit option in SC v4 - Basically the limit wasn't enforced. This was fixed in v4.2.1.

If you don't want any limit, you can set it to null, 0 or Infinity.

Kamelia2000 commented 5 years ago

hello,I think this is not wise way to implement a chat room like Telegram or Wechat with socketcluster.You will have millon of channels.How possible you have not only million its billion of channels?Pls just have a look your whats app or Telegram there is channels with 1 millions subscriber.Everytime they come and need to communicate with huge of channels.its impossible.

Kamelia2000 commented 5 years ago

Because you understand better just refer to your whats app and look you want to implement this by Socketcluster.forst Socketcluster advise make channel and destroy them :

1- It means you never have all people inside your chat room anytimes you need to access need to make channel and subscriber its huge of access

jondubois commented 5 years ago

@Kamelia2000 Each SC channel can have millions of subscribers. Creating a channel in SC is extremely cheap so yes you can also have millions of them too. I don't think there would be any issues implementing something like Telegram or Wechat with SC. You can just keep adding more machines to handle more channels and users.

Kamelia2000 commented 5 years ago

Hello thank you for your email.The only problem is Pub/Sub is not possible by SC.So we need to find some platform such as Kafka work beside SocketCluster So the jobs related to Pub/Sub handle by Kafka have use over three subscriber and others realtime handle by SC.It means for tiny and small subscriber maximum 5 use Socket cluster and rest of huge use Kafka or any others.One of the biggest problem if a worker Crashed we should find some way to handle concurrency and ingestion go to build another worker and its really danger.Imagine 100,000 users in Worker A if all of them Crashed going to move another I am sure because of Low polling in Kuber will encounter problem and make huge of error and request to do. Kamelia

jondubois commented 5 years ago

In case of worker crash, the clients should not all reconnect at the exact same time. The SC JavaScript client has a random delay which can be configured. This randomness ensures that client reconnections are spread out over a certain period of time. Also, problems like this can simply be handled by adding more machines.

Kamelia2000 commented 5 years ago

So whats your suggestion for Pub/Sub and Group chat in enterprise? Could you tell me how possible to connect Pub/sub inside this system and connect to cluster ? Because as i understand Socketcluster is not suitable for Pub/Sub

jondubois commented 5 years ago

@Kamelia2000 Pub/Sub: https://socketcluster.io/#!/docs/full-stack Clustering: https://github.com/SocketCluster/socketcluster/blob/master/scc-guide.md

Kamelia2000 commented 5 years ago

I would like to know whwther possible to use Socketcluster for Geolocation ? Kamelia