Background:
I am building a reactJS application using AWS cognito, dynamo and S3. The application is based in the recruitment sector where employers and employees can post and view jobs respectively. When an employee applies for a job the employer can view the employees profile and decided whether or not to message them. Employees and employers converse via an on-site messaging service.
The Question:
What is the best method to facilitate user chat?
i.e. what is a nice & efficient way to store messages and notify users when they have a new message.
Our current approach is to have a setTimeout() on the site and check for new messages but this will be very inefficient so i'm looking for some guidance.
I would like to stay inside the amazon infrastructure as much as possible but I am open to all suggestions.
I'm currently building something similar for a startup I'm working at. Our React app is served by node.js server, while the API backend is provided by a django API with drf. As in your user chat case, we need to handle some real time data arriving in the frontend.
Our approach
The solution may be split up into inter server and server-browser realtime communication:
We use redis (aws elasticache to be exact) as a publish/ subscribe message queue to push incoming data from the API backend to the nodejs server. Specifically, whenever an instance of the model in question is created due to an HTTP POST call (i.e. in your case a message, which is send to the server), we publish JSON serialized information on a channel specific to the actors of concern.
On the node.js servers, we subscribe to channels of interest and receive information from the backend in real-time. We then use socket.io to provide a websocket connection to the frontend, which may be easily integrated with React.
Limitations of this approach
You cannot simply server your React app as a static website from S3 and have to rely on a node x React approach. react-boilerplat(by Max Stoiber I think) is a great way to start.
What's more, you can also use websockets end to end. We use this approach as our data source isn't a browser but a constrained device.
Hope that helps!
Related
Case scenario:
I have few 2k concurrent users access to the website with various devices but using their browsers. Once one of them create new topic, all others currently connected should receive a notification (basically I simple update little icon number in app upper right corner).
One way to accomplish this is to have web app keep requesting updates via ajax calls but that overload my slow server with numerous requests.
I use azure to host my web app (written in PHP). There are some services included in my hosting package such as Event Hub, Service Bus etc. What service could I use in order to have my backed talk to a "service" whenever there is a new post, and than to have that "service" talk to my clients (their browsers) and informing them about new notification or any type of data updates?
You're probably looking for websockets. A websocket sets up a connection between the page in the client's browser and your webserver. Through this connection you can push new topics to all connected clients.
It is advisable to decouple the websocket sending process from the request handling of the topic creation. For this you need a background worker which sends websocket notifications when triggered from a processing event.
You can implement this in PHP using ratchet.
One simple way to do this would be to have the client poll the server every 10 seconds or so, but I don't think that's the best way to go about it.
I don't want to broadcast notifications to all clients, but only to 1 client at a time.
The internet is loaded with articles on how to do this but I can't figure out which one is more appropriate for my problem.
https://github.com/websocket-rails/websocket-rails
https://github.com/ryanb/private_pub
Consider using a hosted pub/sub broker like Pusher or Realtime (the company I work for) and focus on developing your app and not managing the required real-time infrastructure.
From your Rails backend you would send the messages through the REST API and use the websocket-based JavaScript library to receive them on browser clients (subscribe).
For private messages simply subscribe each user to their own private channel (maybe using their user id).
I have a fully working Jersey/Rest application server on an embedded device and am in the process of converting it to websockets with atmosphere-jersey to make it available through a firewall. I've just run into some design questions.
I have around 125 different rest call endpoints. I setup a websocket to a few of them and transferred data back and forth, similar to rest, but with live pushes. Since I built a socket with a subscriber for each endpoint, does this mean I'm actually maintaining a websocket on the browser side for each connecting endpoint? Or is the browser smart enough to hold a single socket open to the same domain and send requests back and forth to each endpoint? If I am maintaining a lot of websockets, then is there a particular strategy to do all communication with multiple endpoints, using a single websocket?
As well, my project is going to require an intermediary service to match up a login to a device of registered socket listeners. Is there a container that takes care of matching up logins to a websocket broker, that I could host with my own webservices (must be free)? Since all of my backend services look like rest, I don't want to have to subscribe each endpoint to the intermediary; so I'm wondering if I need to setup a single websocket broker to handle the traffic and push it out to the endpoints, or if the jersey-atmosphere service is smart enough to handle this?
Edit: added a design question:
In order to communicate between a web browser and a back end server using a single websocket interface; Is there a clean and easy way to generate a POJO for each receiving broker, or will I have to do a JSON conversion as the first step in each class that receives an object? If I build a javascript message with some sort of key to determine the broker, then I could map the key to a class and do a pojo generation for passing back the object to the handler: but it seems like this is a bit clunky and coupled.
Hi all,
My question was how to create a web chat plugin to be supportive on my companies web site.
1- which protocal is most suitable for this application ??
2-about the coding all client site.
3- about the coding at server side.
4- how the transmission of data takes place from client to server and vice versa.
The easiest approach (not taking into account using all ready existing plugins) would be to use Ajax and a database. This means that the protocol will be HTTP/HTTPS if you want to implement it into your company's website.
The client and server side depends on how you want the chat to function. Try building something similar to IRC with one room for example.
create a database table which will hold the chat
on the client side implement a method which will send a message with Ajax and also recieve all messages posted
for the server side all you need is something which will store the new message and provide them when requested from the client
As I said, this is just a quick example, if you want a more complex chat system you will have to do a bit of research.
I'm thinking about building some intranet applications that make use of websockets. I'm currently using Python/Pylons for my web framework on the server, and doing polling to update items in the DOM of the page. Pylons is not well suited to communicate with websockets (IMHO) as it uses a thread per connection. I'm considering using node.js as the server to communicate with the websocket connections from my web application. Here's the "10,000 foot view" of my application:
Pylons delivers the web content (html, css, images, javascript, etc.)
JavasSript on the page application opens up websocket(s) to the node.js server
The node.js server pushes data to the application through the websocket
JavaScript updates the page DOM elements based on the data from the websocket
The data in the case above comes from a MySQL database, which is where my question comes from. I've set up MVC type applications before, and can do the same kind of thing in node.js. However, if I have a long lived websocket open to the node.js server, how does node.js become aware of changes in the Model and push them out to the application? For instance if I want to update totals presented on the web application page, and those totals change due to actions in the system outside of node.js (other web applications), how is node.js notified of those changes? The thing that comes to mind is to have node.js poll the database for various changes and propagate the changes to the various Views. But to me that just sounds like I'm moving my polling from the web application to the node.js server?
Anyone have any ideas, suggestions or pointers on this?
Thanks in advance!
Doug
You can either:
Let the Python scripts notify the node.js application (via a socket or via HTTP)
Or poll from node.js because it is not aware of changes outside it's environment
Polling is considered bad because it doesn't scale. When having a single process that polls does scale because it doesn't need more connections when another user connects. So basically:
// query every second or so
setInterval(function () {
// query database
doSomeDatabaseStuff(function (res) {
// check dirty
if (res.changed) {
// notify all clients
allConnectedSockets.forEach(function (socket) {
socket.send({ msg: "update" });
});
}
})
}, 1000);
This way you have one single process polling the database, and a scalable architecture to notify your connected clients. The database can still be filled from any source.
Sails.js is an MVC framework for node that has the unique distinction of RESTfully routing Socket.io messages in the same way as your Express routes.
Sails currently uses Sequelize, and is configured by default to use mySQL (but also supports SQLite and Postgres). We're switching to a model that lets you choose your own ORM, which will allow us to support JugglingDB (which adds support for Mongo, amongst others)
It also comes bundled with a front-end component, Mast. Mast provides similar functionality to Meteor, in that it allows you to talk directly to the database from the client. If you need to provide more complex functionality, you just add a controller on the backend.
More here: https://github.com/balderdashy/sails