Synchronized Timer on hundreds of Meteor Clients - javascript

Recently, I started developing a sports app using the Meteor platform. The app synchronizes scores of sports matches to connected clients in real-time (currently soccer matches). On each client, the current match time is shown as countdown (see screenshot of client).
The server updates the match time every second and clients subscribe to match+match time. Since the match time is a reactive variable, it needs to be published/subscribed every second. With only a few clients this is not a problem. But if thousands or even hundreds of clients subscribe, it will slow down the server, result in hanging countdowns etc...
I am searching for a proper solution on how to implement a synchronized countdown with Meteor (ideally real-time) that works with a magnitude of connected clients.
Thanks!

Two packages that will be useful for you:
mizzao:timesync for synchronizing time (like ntp) between clients and the server
remocoder:chronos for creating reactive time.
Reactive time happens on the client so it doesn't burden the server. Timesync of course synchronizes both but it doesn't need to run every second.

Related

Should I use polling or sockets in my app/game?

I am building a React browser web-app which communicates with a Node.js server (Express.js) with a REST design, and am deliberating as to which method of data transmission I should implement. My application delivers a game similar to chess. The games are long term, meaning that on average each player makes a move only every several hours.
Each game involves only a small number of players (2-3), although many unrelated games can take place concurrently (thousands).
EDIT: Unlike chess, a user can make multiple consecutive moves while he waits for his opponents. So during the several hour wait for an opponent's move, a user can post 20 or so updates of his own if he so chooses.
Given that I do not need to push a single update to many users, and that I do not need to update when users open/close their game sessions, which method of data retrieval should I use?
Short Polling?
Long Polling?
WebSockets or Sockets.io?
Server sent events?
All help is greatly appreciated

Synchronizing Socket.IO calls across multiple clients

I'm pretty new to Javascript, Node, socket.io, and multiplayer game development in general, so I apologize in advance for anything obvious that I missed.
I have a node.js server that, when a browser goes to a particular website, creates a socket.io connection with that user. The server-side code receives any messages from a player and forwards it to whatever other players need that message
I'm trying to synchronize function calls across different browsers, so that they're called at as close to the same time as possible.
The expected workflow:
Player 1 sends a message that commands players 2 and 3 to run a function at the same time (in this case, a Countdown) as soon as possible
The server receives the message and sends it to Players 2 and 3
Players 2 and 3 both receive the message and start the countdown at the same time (or as close to the same time as possible)
Is there a standard way to synchronize calls like this across different socket connections?

Real-time user notifications from backend with PubNub, scalability, and over 9000 chat rooms

I'm working on a pretty fun web app project that can become rather big, and I have a chance to play around with this handy thing called PubNub as main real-time engine of application.
So it's a web application with Node.js backend, involves potentially huge amount of chat rooms between users and realtime notifications sent to users by backend when some data in DB is updated.
Usually, developing with Sockets.io, I will just subscribe each user to channel of his unique DB id, and also to chanels representing different chat rooms.
This way I can handle chat rooms and authentication on backend and after storing some personal notification in DB I can easily push them to channel named by user id, so if user is online - he gets it, if not - fine, he will see it on next login, notification is already in DB. And theoretically this monstrocity should scale just fine horizontally with help of redis pub/sub.
Thing that worries me about PubNub in this case is scalability. As I obviously have no insight on what is going on in PubNub backend's dark corners, I want to make sure that app is built in the way that it will be prepared to handle some obscure enormously huge amount of simultaneous users.
My question is, what is the best approach to building such a system with PubNub?
Am I correct assuming that it will be better, in need of pushing notification to specific user, to subscribe to this user's pubnub, push note and unsubscribe. As if I will keep all online-user channels open - then there is no point in PubNub instead of websockets on my server, as server will be anyway under load of all of those opened online-user channels and should be scaled just to maintain huge quantity of them.
What about user authorisation? Without involving my backend how can I be sure that user posting some message will not be able to fake his personality and will have exatly the same as he have authenticated inside application?
And generally (and via PubNub) what is the best practice to tackle huge amounts of chats per users? As say during application life each user may accumulate some decent amount of garbage chat rooms that have some users in it, though havn't been touched by anyone for a long time, and users just way too lazy to leave it manually?
Thanks for Your patience in reading this wall of text!
UPDATED Dec 5, 2021
If you are implementing a chat app, please refer to the PubNub Chat use-case documentation for full details. It has new features and UI components that are built upon the PubNub Platform.
UPDATED May 15, 2020
We have some new docs that will explain much of the below in much clearer terms.
And new features that can be applied to many of the questions/answers below:
Message Actions
Message Counts
Batch History (multi-channel message fetch)
Objects (Users, Channels and Memberships Metadata)
NOTE: I've sprinkled some of the above links down in the answers below.
First, let's address this...
Thing that worries me about PubNub, in this case, is scalability. As I
obviously have no insight on what is going on in PubNub backend's dark
corners, I want to make sure that the app is built in a way that it will
be prepared to handle some obscure enormously huge amount of
simultaneous users.
and this...
then there is no point in PubNub instead of WebSockets on my server,
as the server will be anyway under the load of all of those opened online-user
channels and should be scaled just to maintain the huge quantity of them
This is sort of backward because you would use a service like PubNub to ensure that your application scales to handle millions of users. PubNub has thousands of customers that scale to millions of users and 100's of billions of messages. Not knowing how PubNub does this frees you to implement the biz logic of your application.
But I think I get what you are saying. You are under the impression that your server has to be involved in each and every chat room interaction for every user, but that is only partially true. Mostly, your server will be used for authentication, some subscription maintenance (optional), and probably for sending messages out to one, many, or all end users, as required (depends on your requirements).
Here are some attempts to answer your questions although they are kind of a bit all over the place so I will do my best to answer what I think it is you are asking.
Question 1
This question seems to be directed at maintaining lots of subscriptions to channels and the scalability of that.
Generally speaking, every end-user initializes PubNub and subscribes to channels they need to listen to and publish to channels they need to send messages on. Typically, the channels (chat rooms in your case, I assume) they are publishing on are the same channels they are subscribing to, but they are different kinds of use cases. And you can subscribe to thousands of channels at a time (up to 20K per client). If you did this with WebSockets, how would you go about scaling this to millions of users? You would implement and operate (to scale) something similar to PubNub (not easy and not cheap).
Now, if a user is subscribed to a bunch of chat room channels but some or many are stale (user hasn't viewed or posted to in a while), you could have some code on your server (or the client) that monitors the activity of users and unsubscribes them from those stale channels. This is possible using channels groups. Each end-user would have their own channel group that contains all the channels they are listening to. And the client code or the server code and add and remove channels to/from those end users' channel groups.
Question 2
UPDATED DOCS: https://www.pubnub.com/docs/platform/security/access-control
Now this question is a bit more clear and focused and is asking about authentication (login) and how to ensure someone is who they say they are and how to handle authorization (what they can and cannot do) and where/who controls this.
The answer is, you control the authentication (login) to prove that the person is what they say they are. Your log-in process checks for a valid username/password and in the user record, you will have a list of access controls for that user. With that, you generate an auth-key that you grant read and/or write access to one or more channels. This grant is a PubNub operation that your server invokes. The auth-key is passed back to the client and the client code initializes PubNub instance using the pub/sub keys and this auth-key that PubNub servers use to check for access based on the channel and the operation being requested (subscribe to this channel, publish to that channel, etc). If the auth-key does not have the proper access, the PubNub server will deny access (403 response).
There's more to all of this but this is a good start. Read up on PubNub Access Manager for the SDK you will be using on our docs page. For example, you can start with the JavaScript SDK Access Manager docs and tutorials.
Question 3
UPDATED DOCS: https://www.pubnub.com/docs/platform/channels/receive#subscribe-to-channels
I believe I answered this sufficiently with question 1 - Channel Groups. Start with the JavaScript SDK Stream Controller (which provides Channel Group feature) docs and tutorials.
I hope I have managed to move you a few steps further along your journey to a highly successful real-time, data stream application using PubNub. Please reply with any additional questions you may still have.
*Answers to your new comments:*
Thanks for your follow-up comments. It is very clear what you are asking now.
I will need to compare chat room timestamp with personal user last-read timestamp for this, so it seems that I need to listen to those channels from back-end and update user's last-reads, or to trust into the front-end, and get timestamps from a user directly
No, you do not have to listen to the channels on your server. Yes, from the client app, you will keep the timestamp of the last received message. When the user comes back online, you use this timestamp to get history for the channels the client was subscribed to. Many have done this successfully and we are going to be releasing some amazing features in the coming months that will simplify this considerably.
pushing real-time notifications to users from the back-end. Do I need to be subscribed to all of my user channels if I want to push notes to them at any time?
You can publish on any channel without actually subscribing to it first. So your server can publish to channels as it needs to.
And as before, keep coming with more questions as you require.
*Great follow-up questions again. Here's what I suggest*
... it makes sense to not request all of those chat rooms from DB and join via pubnub all of them, but rather implement pagination... how user can be aware of new messages that may appear in his old chat rooms?
Again, you can stay subscribed to 20K channels using channel groups. You can subscribe to 10 channel groups with 2K channels per channel group - but I'd recommend just limiting the user to 100 or less because that seems like a sufficient limit to impose in your app. But pick whatever upper limit you want and when the user hits that limit, force them to leave another chat room first or suggest they leave one of the top 10 most inactive, or some algorithm that makes sense for your app.
UPDATED DOCS: https://www.pubnub.com/docs/platform/channels/receive#subscribe-to-channels
Getting the # of missed messages does require a full history fetch, but we are going to be providing improved APIs to make this simpler in the near future. But if the user is registered for push notifications on all these channels, the device would be able to receive these push messages and your app can keep that count locally. We will have a "how to update the badge count in background" article being published soon. You could also use that to keep track of the number of missed messages per channel (chat room).
For now I just want to limit the number of rooms available for users to let's say a hundred and request and join them without pagination.
UPDATED DOCS: https://www.pubnub.com/docs/platform/channels/retrieve
We do have customers that do this without worrying about pagination. They just retrieve history on the 100 channels the device is subscribed to. With the background badge count updater strategy, you will have the advantage to know which channels to fetch from when the app becomes active. I will post the link to that article here once it is published.

Node.js/Socket.io realtime webpage push updates

I am looking to implement/add realtime push notification updates from node.js server to browser (client).
I looked into socket.io (http://socket.io/docs/rooms-and-namespaces/)
business requirement is - users will visit a page displaying customer info & their orders. There will be ~10,000 users visiting the page at any given time (all 10,000 could be for different customers or sometimes a user may have opened the same page in 2 or 3 tabs)
When orders flow in to elasticsearch for a customer (my datastore) i want to push notification to users who have that customer's page opened.
Questions:
Is socket.io the correct framework for this case?
Am I correct in understanding I have to use socket.io' rooms functionality to implement this? (each room identifier equals customer ID?)
Is this implementation scalable and would it be memory intensive for 10k users on node.js server?
Thanks!
Yes, but you could consider socksJS as well and write your own simple back-end.
Yes, it's the easiest way if you need authentication.
Worst case scenario you'd need to cluster your socket.io servers and use a back-end adapter. Redis should be fast enough for 10.000 connections.
EDIT: memory will depend on your specific implementation.
Also consider https://github.com/Automattic/socket.io/issues/1393

Reliable timer for a chat room

Please help to choose a solution (nodeJS + socket.io + redis) for a chat room timer.
Multiple Rooms are created, every room has exactly one HOST i.e admin for that room, every room will have 500 members in it. There can be 'n' rooms at any time 't'. A room will be destroyed after 1 hour of creation.
Node server => Process room's member related data from redis and broadcast it in every room after some interval. this interval (i.e When to broadcast) is decided by an array, call it as timerArrayForRoom1. This array holds the time in seconds when to broadcast data. This array is different for every room.
Now, two approaches -
Using setInterval() in nodeJS so that it will call its broadcasting method after some time interval. Every room will have its separate interval object.
Give timerArrayForRoom1 to the HOST of the room and let the host fire an event after some seconds as per the timer array. i.e using setinterval() on client side. And node server will take its action on that event.
First approach is HOST independent but it involves use of setInterval() in NodeJS.
Which one would be better to implement so that server will be able to support 1000 rooms having 500 members in it running and broadcasting all at a time ?
Which is more reliable? (as I read setInterval() does not guarantee its time to call the function)
Or any other approach?
Host/admin will be different device and exactly one for every room, so second approach will balance the server load to some extent.
setInterval from your node server is the way to go. You already give a good reason that it is independant of the clients. Also while it may not guarantee its time to execute. It is the closest to execute ontime.
This should work reasonably accurate unless your server hangs up because of CPU intensive execution. Also allowing HOST or any other client to initiate event is susceptible to same drawbacks.

Categories

Resources