Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sticky Sessions ? #389

Closed
kulicuu opened this issue Apr 13, 2014 · 92 comments
Closed

Sticky Sessions ? #389

kulicuu opened this issue Apr 13, 2014 · 92 comments

Comments

@kulicuu
Copy link

kulicuu commented Apr 13, 2014

For some Realtime app implementations, it is important to have sticky sessions support. I'm using SocketStream, whose architecture is built around assuming sticky sessions.

I found a module sticky-session that implements sticky session support with Node's cluster module.

Since this automatically clusters over all available processors, the best way to integrate using it with pm2 is just to run one pm2 process, correct ?

Wondering if anyone else has interest in testing this.

I'd considered asking if it would be possible to assimilate the code and logic from that module into pm2, but I don't think that's doable since it has to be invoked from within the app code, whereas pm2 is strictly applied externally.

Still, it would be nice to compile some best practices and maybe document them.

@kulicuu
Copy link
Author

kulicuu commented Apr 13, 2014

Almost forgot to ask, but this question is very important:

What (if any) is the advantage of clusterisation vs 'fork mode'. When I use pm2 without sticky-sessions, I use fork mode, in which all requests are routed appropriately. Why indeed, shouldn't I simply continue to use the 'fork mode' ? (I'm not too hung up on the graceful reload and I don't mind specifying the number of processes to match number of cores / cpu's ; am I missing something critical ?) Why bother trying to implement the clusterisation and scaling with NodeJS's cluster module instead of the fork mode (which uses what ?) ...

...many questions , much thanks for any info !

@gorangajic
Copy link

I am also interested in this, it would be great if pm2 supported sticky-sessions with 0s downtime reload

@kulicuu
Copy link
Author

kulicuu commented Jul 10, 2014

Update July 10:

I've been use this sticky-session which automatically clusters via the native Node module. I'm still using pm2 for the ever-on effect, logging etc, but it's running fork mode uni-process.

I'm not really up to date on changes in pm2 since April, so I don't know what new is possible.

@matthew-dean
Copy link

@kulicuu Can you post an example using both pm2 and sticky-session?

@kulicuu
Copy link
Author

kulicuu commented Jul 11, 2014

@matthew-dean They are really two separate issues:

The sticky-session part I won't touch, because they have good documentation and your implementation needs are going to be specific to your particular app characteristics. It's written into your main app file.

In my package.json I have a script:

"startScript": "pm2 -x -n theName start start.js", where as you know, the -x flag induces fork mode (defaulting to one 'prong' / process).

start.js looks like:

require('./node_modules/ss-iced/node_modules/iced-coffee-script/lib/coffee-script/coffee-script.js').register()

require('./myAppFile')

I'm using Iced-CoffeeScript on the server side, your use case may indicate a slightly different approach.

Anyways, I start with npm run-script startScript from prompt.

Let me know if you have more questions or need clarifications.

@peteruithoven
Copy link

Could one of the contributors answer whether their planning to implement Sticky sessions in PM2's cluster_mode?

@kulicuu
Copy link
Author

kulicuu commented Sep 24, 2014

I don't know if it's possible for them to implement a general solution at that level. The way the sticky-session module works requires you to invoke it from within your main app file. It's a delicate splice.
The nodejs cluster module is good.

@kulicuu
Copy link
Author

kulicuu commented Sep 24, 2014

this is my open-sourced version of something I did for a recent closed-sourced project. It's a project in SocketStream, which requires sticky-sessions to work. It's running clustered on Linode under pm2 fork mode.

@matthew-dean
Copy link

I ended up using a NoSQL database (Redis) for sessions, which removed the problem entirely and had some additional benefits over in-memory sessions anyway.

@kulicuu
Copy link
Author

kulicuu commented Sep 24, 2014

I use Redis for sessions also, but for some reason think it still needs to hit the same Node process; embarassed to not be able to explain why off-hand it's because for SocketStream the sessions are stored in memory and only saved to Redis as a backup.

@peteruithoven
Copy link

Alright.
Just to note, using a database doesn't solve the problem for socket.io, to support the polling transport you need sticky sessions.

@kulicuu
Copy link
Author

kulicuu commented Sep 25, 2014

@peteruithoven: thanks that's the detail I was looking for.

@iliakan
Copy link
Contributor

iliakan commented Nov 4, 2014

why is it labelled as a discussion and not a feature request?

@geyang
Copy link

geyang commented Jan 2, 2015

I just run into this problem too. I am now reducing the total number of instances to one per worker type.

@geekyme
Copy link

geekyme commented Jan 29, 2015

+1 having this issue too. downgraded to fork_mode instead of cluster mode. Otherwise, I will always see:

WebSocket connection to 'wss://chat.abc.com:8443/socket.io/?EIO=3&transport=websocket&sid=JfS4-36MdT074qjoAAAB' failed: Connection closed before receiving a handshake response

EDIT: I ended up using https://github.com/indutny/sticky-session

Then running pm2 start app.js in fork_mode will be equivalent to cluster_mode, except that socket.io will work here with the cluster. However, the connection will fail again if any client is behind a proxy / VPN.

@Unitech I think it should be possible for us to specify a sticky option in the pm2 command that takes care of establishing a cluster that will work with socket.io (regardless of whether the client is behind a proxy or vpn).

@tschiela
Copy link

tschiela commented Feb 2, 2015

I used node.js with cluster-module, redis as session storage and nginx as load balancer with sticky sessions (ip_hash). All worked fine.
Yesterday I migrated to PM2. Now I have problems with the socket.io handshake. So because PM2 act as load balancer here, in my opinion PM2 is responsible for the sticky sessions.

@geekyme
Copy link

geekyme commented Feb 8, 2015

This issue has been ongoing for quite a while already. @Unitech any thoughts?

@aidanxyz
Copy link

Same thing here. I was planning to use sticky-session with fork_mode on PM2, BUT sticky-session has troubles delivering static files :(

@olasfar
Copy link

olasfar commented Apr 30, 2015

Ping ?

@soyuka
Copy link
Collaborator

soyuka commented May 1, 2015

I've tried to embed sticky sessions inside pm2 with no success. In fact, we would have to implement this directly inside the cluster code, which we don't own, for now.

If you need sticky sessions, you could implement something like https://github.com/indutny/sticky-session or https://github.com/elad/node-cluster-socket.io (better perfs) and run your own cluster in a fork mode.

@BrandonCopley
Copy link

Is there a way to set the "cluster" mode in pm2 to start on different ports, ex: start on 80,81,82,83,84 because then I can cluster behind my load balancer.

@soyuka
Copy link
Collaborator

soyuka commented Oct 23, 2015

@BrandonCopley use 4 forks with your load balancer ?

@BrandonCopley
Copy link

Yes, I figured this out - how can I help write some better documentation on
that ecosystem file?

On Friday, October 23, 2015, Antoine Bluchet notifications@github.com
wrote:

@BrandonCopley https://github.com/BrandonCopley use 4 forks with your
load balancer ?


Reply to this email directly or view it on GitHub
#389 (comment).

[image: Giftnix]

Brandon Copley

Founder & CEO

t: 512.784.6060

e: copley.brandon@gmail.com

@vmarchaud
Copy link
Contributor

@douira You could use an ecosystem like this :

module.exports = {
  apps : [
      {
        name: "myapp",
        script: "./app.js",
		exec_mode: "fork",
        instances: 4,
        instance_var: 'INSTANCE_ID',
        env: {
            "PORT": 3000,
            "NODE_ENV": "production"
        }
      }
  ]
}

and in your app :

const port = parseInt(process.env.PORT) + parseInt(process.env.INSTANCE_ID) 
server.listen(port)

This will spawn 4 applications in fork mode but each one listening to a different port starting from 3000.

@douira
Copy link

douira commented Dec 6, 2018

Ok thanks, I didn't know the fork mode also worked with an instance amount.

@knoxcard
Copy link

I havent ran into this problem. I think if you have cluster mode on with pm2 and setup nginx as a frontend to your app, nginx handles it all for you.

I have 8 instances of app.js running and they all share the same port.

upstream app_service {
      server                              127.0.0.1:4000;
      keepalive                           16;
  }

@Lwdthe1
Copy link

Lwdthe1 commented Jan 19, 2019

@knoxcard would you mind sharing more of your nginx config as well as how you setup your app.js to accept incoming requests? I'm still trying to understand how to make this work with nginx

@knoxcard
Copy link

knoxcard commented Jan 20, 2019

Another user posted this earlier, then it appears he deleted it. I got an email notice, read over it and felt it was a viable solution.

"For anyone who needs sticky session with load balancing without having to worry about routing every request by the same user to the same server, I've been using the node-client-sessions module by Mozilla for over a year now; basically, it stores session data in a secure manner on the client's cookies so you don't have to use an external storage such as redis or mongo for session keeping across multiple processes/machines. This blog post explains it more.

Thanks to this, as well as using Pusher instead of socketio, I just remembered that I don't have to worry about sticky-sessions as I migrate to PM2."

@soyuka
Copy link
Collaborator

soyuka commented Feb 7, 2019

I just thought about this, maybe that using something stateless like http://mercure.rocks (spec here) would resolve this issue for good.
We're thinking about integrating this in socket.io as well, I'll keep you updated here.

@lerit
Copy link

lerit commented Feb 21, 2019

all issues 'pm2'+'socket.io' reference this famous issue #389.
two great nodejs project 'pm2' and 'socket.io',but so hard to use them together.
search in socket.io issues,guide me here;search here,guide me back or to nodejs issue

is it really impossible to use pm2 cluster mode with socket.io?
or i must give up something?

so sorry for my 'complaint',i just want to say:i like pm2,and i need socket.io too

@efkan
Copy link

efkan commented Feb 21, 2019

I don't know what you can not accomplish but there is a reasonable solution in the issue you pointed #389 (comment)

And of course there is a con about horizontally auto-scaling. However it is not an issue at the start for most of scenarios. Hope it can help you too.

@MickL
Copy link

MickL commented Mar 10, 2020

Hey guys, I didnt read the full issue so sorry if I ask: Are sticky sessions now working with PM2 cluster? If not, and PM2 is using node.js cluster then it could be easily integrated. Here is a very nice code-example / explanation which is also field tested by me: https://github.com/elad/node-cluster-socket.io

Anyway, according to this article the performance using node.js cluster is much worse than just spawning the same app multiple times and let Nginx or Linux iptables do the load balancing.

In my opinion, since PM2 already has this out-of-the-box cluster option, sticky sessions should be integrated even tho there are better options.

@stale
Copy link

stale bot commented May 23, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label May 23, 2020
@MickL
Copy link

MickL commented May 23, 2020

Please dear stale bot, this issue is 6 years old but still relevant.

@stale stale bot removed the stale label May 23, 2020
@grahamtallen
Copy link

Same, we're looking to implement something similar, whats the current state of things?

@stale
Copy link

stale bot commented Jul 14, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Jul 14, 2020
@douira
Copy link

douira commented Jul 14, 2020

not stale

@stale stale bot removed the stale label Jul 14, 2020
@MickL
Copy link

MickL commented Jul 14, 2020

As I said implementing sticky sessions in node (as pm2 would do) is not very performant compared to other solutions. Instead I would recommend to use PM2 to spawn max processes but in fork mode and then let Nginx handle the balancing with sticky sessions.

Anyway it would not be much work to integrate stick sessions into the pm2 cluster mode as shown in the github project i linked above but is pm2 still actively maintained?

@douira
Copy link

douira commented Jul 14, 2020

I believe it is since there's a company behind it now, so yes. They just don't seem to be very active in the issues...

@soyuka
Copy link
Collaborator

soyuka commented Jul 17, 2020

Anyway it would not be much work to integrate stick sessions into the pm2 cluster mode as shown in the github project i linked above but is pm2 still actively maintained?

Yes it is maintained. No it's not as easy as the code you showed above.
Please check nodejs/node#18315 which lead to nodejs/node#11546 but was abandoned. This gives more control over the cluster module which would then let us handle sessions.

I'd definitely recommend using a stronger load balancer with forked processes then the one from nodejs, for example caddy/nginx/haproxy on top of pm2.

@stale
Copy link

stale bot commented Aug 16, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Aug 16, 2020
@yangsibai
Copy link

No, it's not stale.

@soyuka
Copy link
Collaborator

soyuka commented Jan 22, 2021

Were there any progress on the nodejs side of things to give more control over the cluster?

@kulicuu
Copy link
Author

kulicuu commented Feb 4, 2021

Yeah, my older self to younger self: Don't. Use. 'Sticky-sessions' or whatever. Use a very thin layer, stateless servers over likely a Redis cluster. Since 2015 used Primus for websocket handling. These days I'm into Wasm/Rust for web-clients, React-Native for mobile-clients, very thin stateless websocket-server layer connected to a Redis cluster for state management, some kind of messaging "lambda" architecture. CDN support for static stuff.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests