We are facing a problem where clients connect to the server and a socket is created and is working.
But for example if the server goes down / we upgrade the version and restart the server,
the sockets are lost until clients refresh the page.
Our clients are passive, and will not refresh the page often leaving the server disconnected for updates and notifications.
We would like to know if it is possible to store the sessions somehow like a mongo store.
Related
I am working on a nodejs app with Socket.io and I did a test in a single process using PM 2 and it was no errors. Then I move to our production environment(We use Google Cloud Compute Instance).
I run 3 app processes and a iOS client connects to the server.
By the way the iOS client doesn't keep the socket connection. It doesn't send disconnect to the server. But it's disconnected and reconnect to the server. It happens continuously.
I am not sure why the server disconnects the client.
If you have any hint or answer for this, I would appreciate you.
That's probably because requests end up on a different machine rather than the one they originated from.
Straight from Socket.io Docs: Using Multiple Nodes:
If you plan to distribute the load of connections among different processes or machines, you have to make sure that requests associated with a particular session id connect to the process that originated them.
What you need to do:
Enable session affinity, a.k.a sticky sessions.
If you want to work with rooms/namespaces you also need to use a centralised memory store to keep track of namespace information, such as the Redis/Redis Adapter.
But I'd advise you to read the documentation piece I posted, things might have changed a bit since the last time I've implemented something like this.
By default, the socket.io client "tests" out the connection to its server with a couple http requests. If you have multiple server requests and those initial http requests don't go to the exact same server each time, then the socket.io connect will never get established properly and will not switch over to webSocket and it will keep attempting to use http polling.
There are two ways to fix this.
You can configure your clients to just assume the webSocket protocol will work. This will initiate the connection with one and only one http connection which will then be immediately upgraded to the webSocket protocol (with socket.io running on top of that). In socket.io, this is a transport option specified with the initial connection.
You can configure your server infrastructure to be sticky so that a request from a given client always goes back to the exact same server. There are lots of ways to do this depending upon your server architecture and how the load balancing is done between your servers.
If your servers are keeping any client state local to the server (and not in a shared database that all servers access), then you will need even a dropped connection and reconnect to go back to the same server and you will need sticky connections as your only solution. You can read more about sticky sessions on the socket.io website here.
Thanks for your replies.
I finally figured out the issue. The issue was caused by TTL of backend service in Google Cloud Load Balancer. The default TTL was 30 seconds and it made each socket connection tried to disconnect and reconnect.
So I updated the value to 3600s and then I could keep the connection.
I am using a websocket library on server for establishing socket connection.
https://github.com/websockets/ws
I have a more than one server in cluster, I want to know how can I use same socket connection object on another server in cluster.
And also I want to know what is the best option for webchat implementation native websocket or socket.io
You cannot use the same actual socket object across multiple servers. The socket object represents a socket connection between a client and one physical server process. It is possible to build a virtual socket object that would know what server its connection is on, send that server a message to then send out over the actual socket from that other server.
The socket.io/redis adapter is one such virtual ways of doing this. You set up a node.js cluster and you use the redis adapter with socket.io. It uses a central redis-based store to keep track of which serve process each physical connection is one. Then, when you want to send a message to a particular client from any of the server processes, you send that message through socket.io and it looks up for you in the redis database where that socket is connected, contacts that actual server and asks it to send the message to that particular client over the socket.io connection that is currently present on that other server process. Similarly, you can broadcast to groups of sockets and it will do all the work under the covers of making sure the message gets to the clients no matter which actual server they are connected to.
You could surely build something similar yourself for plain webSocket connections and others have built pieces of it. I'm not familiar enough with what exists out there in the wild to offer any recommendations for a plain webSocket. There plenty of articles on scaling webSocket servers horizontally which you can find with Google and read to get started if you want to do it with a plain webSocket.
i have progged a community.
At the Login.php i connect and listen via
var socket = io.connect("http://ajkfh.com:8080");
socket.on("connect", function() { ......
but then, if the user changed on another site from the community, his connection will be closed and he is not longer listen.
how can i hold open the connection over underlying sites of the community. THANKS and sorry for my bad english
A socket connection is available only when the user remains on the page. There is no way for you to make a socket connection available across page loads. What you can do, is emulate page loads into ajax requests which load content inside a container.
Or you could just re-establish connection on page load, and have a mechanism to keep a track of clients (storing a client ID on a cookie or something)
Seemed you use socket.io, which is websocket. The websocket connection does lost if the page refreshed or closed.
If you want to retain something between pages, use Cookie or Session, just like the normal http way. And on browser side, you can read the data out(e.g. via the document.cookie or some lib) and send back to the server over websocket.
My app is in browser, which connects to socket.io server, it works fine, but, when client disconnect for a while ( sleep for example ) , the connection will be automatically closed by server, this is the default behavior for socket.io
How can I re-establish the connection at client side without refreshing the page? is there a status that would tell me that connection is currently off at client side? so that I re-connect when necessary?
I can't rely on an event, I think I need to know if connection is on or off in an easy way locally .. well?
socket.io does reconnect automatically. To check if your socket is connected check socket.socket.connected has Boolean value. See socket.socket.connecting if you are trying to connect.
var socket = io.connect(''); //reconnects by default
console.log(socket.socket.connected);
console.log(socket.socket.connecting);
What is best solution to manage connection in NodeJS connected via SockJS (websocket) to be durable(do not disconnect) for some time during user reloads the page?
Can I do that with session?
SockJS, native websockets and all resources that the browser maintains are released when the user reloads (or leaves) the web page. Cache, localstorage (and friends) and cookies are notable exceptions.
If you wish to have a SockJS connection when a page is open - well, you need to establish a connection when the page is opened.
SockJS is pretty fast and apparently it works fine even if you have loads of short-lived connections.
(BTW, take a look at web workers with websockets)