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

Open
kulicuu opened this Issue Apr 13, 2014 · 79 comments

Comments

Projects
None yet
@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

This comment has been minimized.

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 !

@soyuka soyuka added the discussion label Jun 17, 2014

@gorangajic

This comment has been minimized.

Copy link

gorangajic commented Jul 9, 2014

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

@kulicuu

This comment has been minimized.

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

This comment has been minimized.

Copy link

matthew-dean commented Jul 10, 2014

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

@kulicuu

This comment has been minimized.

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

This comment has been minimized.

Copy link

peteruithoven commented Sep 24, 2014

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

@kulicuu

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

Copy link

matthew-dean commented Sep 24, 2014

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

This comment has been minimized.

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

This comment has been minimized.

Copy link

peteruithoven commented Sep 24, 2014

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

This comment has been minimized.

Copy link
Author

kulicuu commented Sep 25, 2014

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

@iliakan

This comment has been minimized.

Copy link
Contributor

iliakan commented Nov 4, 2014

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

@episodeyang

This comment has been minimized.

Copy link

episodeyang 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

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

Copy link

geekyme commented Feb 8, 2015

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

@acutexyz

This comment has been minimized.

Copy link

acutexyz commented Feb 12, 2015

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

@olasfar

This comment has been minimized.

Copy link

olasfar commented Apr 30, 2015

Ping ?

@soyuka

This comment has been minimized.

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

This comment has been minimized.

Copy link

BrandonCopley commented Oct 22, 2015

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

This comment has been minimized.

Copy link
Collaborator

soyuka commented Oct 23, 2015

@BrandonCopley use 4 forks with your load balancer ?

@BrandonCopley

This comment has been minimized.

Copy link

BrandonCopley commented Oct 23, 2015

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

@rcalabro

This comment has been minimized.

Copy link

rcalabro commented Nov 17, 2017

+1

@smonkey72

This comment has been minimized.

Copy link

smonkey72 commented Nov 29, 2017

@mattbrunetti Please keep in mind that this is not an issue with browsers only. There are also a lot of networks / firewalls which still block websocket traffic. In these cases 'polling' is also required.

@HyeonwooShin

This comment has been minimized.

Copy link

HyeonwooShin commented Jan 15, 2018

is there a plan for use of PM2 cluster mode & socket.io with successful handshake transports whatever? i need to support IE < 11. so I can't use transports websocket only. please consider about sticky session based on cookie, not based on ip.

@wallet77

This comment has been minimized.

Copy link
Collaborator

wallet77 commented Jan 25, 2018

Unfortunately Node community don't want to integrate sticky cluster into core, even if it's working and ready to merge : nodejs/node#18315

So we will do it in PM2. I will take care of it when I will have time.
I will keep you informed of progress.

@billyshena

This comment has been minimized.

Copy link

billyshena commented Jan 30, 2018

Would be awesome to have sticky session + pm2 !

@wallet77

This comment has been minimized.

Copy link
Collaborator

wallet77 commented Jan 31, 2018

Hi everybody,

After discussions with @soyuka we think the best way is to resurrect this node PR : nodejs/node#11546

This PR allows users to customize cluster algorithm. So we can inject sticky cluster, even if it's not a core algorithm.

So next steps are :

  • reopen PR and resolve conflicts with branch master
  • finalize code and add test + documentation
  • create sticky cluster algorithm and share it on github
  • integrate it into PM2
  • release PM2 ;)
@abhipanda

This comment has been minimized.

Copy link

abhipanda commented Feb 24, 2018

@wallet77 It will be good to know if there is a release which we are tagging this feature to be live with. This is an important feature for us and like to know if its going to available in coming future.

Thanks for all great work.

@wallet77

This comment has been minimized.

Copy link
Collaborator

wallet77 commented Feb 26, 2018

Hi @abhipanda

I didn't have time to work on that for 2 weeks. I will work on it this week.
Unfortunately I can say in which release it will be possible.

@abhipanda

This comment has been minimized.

Copy link

abhipanda commented Feb 26, 2018

@wallet77 Thanks for supporting this feature

@billyshena

This comment has been minimized.

Copy link

billyshena commented Mar 22, 2018

@wallet77 Sounds awesome, if you need any help let us know ;)

@billyshena

This comment has been minimized.

Copy link

billyshena commented Apr 20, 2018

Any news about having sticky session with pm2 ? In our company we need it for ajax long polling, would be awesome.

@BrandonCopley

This comment has been minimized.

Copy link

BrandonCopley commented Apr 20, 2018

@billyshena

This comment has been minimized.

Copy link

billyshena commented Jun 1, 2018

@BrandonCopley We really want to use PM2 in production and we need AJAX long polling when websockets are disabled by our customers (behind firewall). Would be really awesome to have this feature !

Any news ?

Best,

@BrandonCopley

This comment has been minimized.

Copy link

BrandonCopley commented Jun 1, 2018

@billyshena You should be using Nginx or a load balancer in order to manage sticky sessions. PM2 isn't the right solution at this point in time.

I use pm2 to setup the cluster and I predict the clusters IP addresses ex: I use 4 clusters per server, so my ports would be 8080 8081 8082 8083 and then do sticky sessions with nginx to direct to those ports.

@billyshena

This comment has been minimized.

Copy link

billyshena commented Jun 1, 2018

Thanks for those feedbacks @BrandonCopley ! I am not used to Nginx configuration, would it be possible to share your configuration ?

@BrandonCopley

This comment has been minimized.

Copy link

BrandonCopley commented Jun 1, 2018

Here's a good start - https://www.nginx.com/products/nginx/load-balancing/ It's not super easy to get sticky sessions working, but this works.

On a different note, I now recommend doing rid of sticky sessions and instead using jsonwebtokens (JWT) for sessions if possible in your project.

https://float-middle.com/json-web-tokens-jwt-vs-sessions/

There's a LOT of outdated info saying not to use json web tokens for sessions, but that data is really outdated since Auth0 has been helping grow JWT https://auth0.com/docs/jwt

@billyshena

This comment has been minimized.

Copy link

billyshena commented Oct 8, 2018

@wallet77 Is it still a planned feature on the roadmap ?
Just to know if I rather wait for a pm2 release or I should consider another solution

@vmarchaud

This comment has been minimized.

Copy link
Collaborator

vmarchaud commented Dec 5, 2018

Hello everyone,

Just wanted to update on this issue, sadly we don't have the time to move forward the PR in NodeJS that would allow to us to implement the sticky load balancing.

If at some point it's implement, we would potentially implement it in PM2 but it's not on the roadmap on the Node side for the moment i believe.

So if you are looking for this feature in PM2, i would advise to find another solution without our cluster mode (NGINX, Traefik or HAProxy allows that to quote few solutions out there)

@douira

This comment has been minimized.

Copy link

douira commented Dec 5, 2018

without our cluster mode

How do you suggest spawning a bunch of server instances without using the cluster mode? (and not just copy-pasting an extra in ecosystem.config)

@vmarchaud

This comment has been minimized.

Copy link
Collaborator

vmarchaud commented Dec 6, 2018

@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

This comment has been minimized.

Copy link

douira commented Dec 6, 2018

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

@knoxcard

This comment has been minimized.

Copy link

knoxcard commented Dec 25, 2018

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

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.