I have an app on heroku that uses socket.io for server-client communication. Everything is working just fine. However, once I scale my app to more than 1 dyno, I get several http request errors:
can't establish a connection to the server at wss://***/socket.io/?EIO=2&transport=websocket&sid=Hky6IHdckNADdU_tAACm. socket.io.js:4520
The connection to wss://***/socket.io/?EIO=2&transport=websocket&sid=Hky6IHdckNADdU_tAACm was interrupted while the page was loading. socket.io.js:4520
can't establish a connection to the server at wss://***/socket.io/?EIO=2&transport=websocket&sid=kWymv6ItJHBcUybZAAAA. socket.io.js:4520
The connection to wss://***/socket.io/?EIO=2&transport=websocket&sid=kWymv6ItJHBcUybZAAAA was interrupted while the page was loading. socket.io.js:4520
As well as a load of
HTTP status 400
{ code: 1, message: "Session ID unknown" }
My socket.io is using the redis adapter, so the state should be shared correctly. I kind of verified this by connecting to redis and issuing the following command:
PSUBSCRIBE socket.io#*
Since I can see data traveling back and force on this channel, I am assuming my socket.io redis adapter is working fine.
Anyone know how to make socket.io work on heroku with more than 1 dyno?
You need sticky load balancing. Socket.io has a great article on it, so I'll leave it to them to explain the topic:
https://socket.io/docs/using-multiple-nodes/
Related
I'm new in socket-io. socket-io working fine but keep sending connect request infinitely to server.
Here is my client ts :
private url = environment.socketServer;
constructor() { this.socket = io(this.url) }
The usual reason for a socket.io client to try to connect over and over is if the socket.io version on the server and client are not compatible. The client connects, the server finds the version is incompatible and drops the connection and the client then tries to connect again, over and over.
Other possible issues:
Server infrastructure (such as load balancers, proxies, firewalls, etc...) are not properly configured to allow webSocket connections.
You're trying to connect to a cluster, but it isn't configured for sticky connections that will "bind" a socket.io client to the same server.
You're confused about how a socket.io connection starts. It is normal for the client to start with a couple web connections in a row (polling) until it realizes that both sides support a webSocket and then socket.io switches over to webSocket.
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.
We have a server which do implement socket.io in NodeJS on Heroku.
We have a bunch of clients (Raspberry pi's) destributed on different networks across our country. They do implement socket.io clients in a NodeJS application.
It do work very well on 17/18 devices. We do have one device which are not able to upgrade the socket.io connection from a long-polling type to an actual websocket.
I cannot find the reason why.
Our server is setup with the following options:
Server settings
This is what the logs on our heroku server tells about the connection with the problematic client:
Heroku logs
As all clients are setup exactly the same way, i do not actually suspect any problems on the raspberries themselves.
Could it be a network problem where this one client is located?
- Behind the router, blocking some port etc?
Hope you have some suggestions to what the problem could be.
You tell if you need anymore information.
I have a Node/Express app on server dedicated to sockets and on the client it's Angular 1.5. Running the code locally on http using the same architecture e.g. separate socket server it all works perfectly fine.
When I run the code locally it creates one connection and does very little polling via xhr. On cloudflare with https it does a lot of polling, reconnects continually and not all the messages seem to be getting to the web client
messages hit cloudflare which then redirects them to a loadbalancer running haproxy which then routes the requests to an app running in a docker instance on another machine.
Your Issue is most likely occuring beacause of an issue with cloudflare only allowing traffic to a limited set of ports. Try one of the ports listed in the below link for your server and try connecting to it.
https://support.cloudflare.com/hc/en-us/articles/200169156-Which-ports-will-Cloudflare-work-with-
After a lot of investigation I found the issue to be down to the config in haproxy. I needed to alter the timeouts around the socket routing.
This was nothing to do with ports not being open on cloudflare.
The following link helped me
http://blog.haproxy.com/2012/11/07/websockets-load-balancing-with-haproxy/
Okay, so I have created an ubuntu vm in the azure cloud, I have successfully launched nodejs, redis, socket.io, Express and all the components for a game I am writing.
I have setup azure endpoints on internal and external port 8080, and use app.listen(8080) in my js code.
When I browser to http://< app-name >.cloudapp.net:8080/ I can view the result of my nodejs application fine, it displays the html, css etc.
However when it attempts to start a socket connection (using socket.io) I get only this (on my chrome dev console under websockets):
HeadersPreviewResponseWebSocket Frames
Request URL:ws://<app-name>.cloudapp.net:8080/socket.io/1/websocket/13510496541533398587
Request Method:GET
Status Code:101 Switching Protocols
Request Headersview source
Connection:Upgrade
Host:<app-name>.cloudapp.net:8080
Origin:http://<app-name>.cloudapp.net:8080
Sec-WebSocket-Extensions:x-webkit-deflate-frame
Sec-WebSocket-Key:y5vueHE66phl70gle7KCtw==
Sec-WebSocket-Version:13
Upgrade:websocket
(Key3):00:00:00:00:00:00:00:00
Response Headersview source
Connection:Upgrade
Sec-WebSocket-Accept:dn+2lA6sMIXHLEmDS/Q4j/IIwxI=
Upgrade:websocket
(Challenge Response):00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
It will also crash the nodejs app on azure when i try send anything using socket.emit() on the client (browser); in my azure ssh, it just says 'DEBUG: Program node app.js exited with code null' which isn't particularly helpful.
So it obviously isn't connecting properly? I have also tried in my nodejs listening on port 80, but then I don't even get the standard webpage (html,css,etc).
From what I have read online, it is very possible to get sockets working providing your not using the web role (which I assume the vm is not).
Any idea how I can get this to work? (and preferably on port 80)?
Edit: starting to wonder if this has nothing todo with sockets, realized I get the same switching protocol message, on my home vm (where it is working). Spin off question: How can I view crash details for a nodejs program on a ubunu azure vm?
There is a time out of around 60s on the Windows Azure loadbalancer.
Does it work if you send a message back to the client just after the websocket connection is established?
If it is the case you will have to implement some keep a live message send every minutes.