tjanczuk / iisnode

Hosting node.js applications in IIS on Windows
Other
1.86k stars 586 forks source link

Feature request: Dispatching requests from one client to same node process #381

Open queequac opened 10 years ago

queequac commented 10 years ago

Currently iisnode supports just the round robin approach for dispatching requests across several node.exe processes. While this is a good approach for load distribution in general, this might screw up an application’s session state.

To have access to consistent session information through-out processes some needs at least additional infrastructure (e.g. redis), adding complexity and overhead for IPC. In certain cases (e.g. socket.io, which sends several requests for the initial handshake) the usage of multiple node.exe processes is not even possible, because a sequence of requests belonging together terminates in different processes.

The basic idea to overcome this limitation would be introducing something like sticky sessions, but on process level.

Instead of generating real session IDs, the ID could simply be a hint for the assigned process. This avoids also the necessity of book-keeping individual sessions.

An incoming request might carry a cookie with the hint for the target process the request belongs to, e.g. iisnode.p=2 would indicate that the request belongs to the node.exe process with index 2.

If no cookie is present, a new node.exe process will be selected (now according to round robin again). The selected process will then be set as cookie in the response. All subsequent requests will be dispatched to exactly the same process.

The process hint must only be checked for pointing into valid boundaries. Malicious modification of the cookie could skrew up the session state, but that results in exactly the same what happens today without such cookie. Since the cookie is for process affinity of the local iisnode instance only, it would neither counteract nor replace load balancing on web server level. It would rather complement such load balancing mechanisms in the network infrastructure, since requests routed to the same web server (application) would now also reach the correct underlying node process.

This feature could be activated via a separate configuration entry (e.g. nodeProcessStickySessions, default: false). Without explicitly setting this configuration key, the behavior should remain completely unchanged to nowadays process of dispatching.

This lightweight feature would help lots of projects which cannot utilize multiple cores today, while being able to stick to the official iisnode module instead of creating custom builds (as I did) or adding additional infrastructure.

I have already an implementation for the above feature. Depending on your feedback I would adjust my code and send a pull-request --- just in case the feature request won't be rejected. :smile:

rramachand21-zz commented 10 years ago

I believe this will be very useful - Great that you already have an implementation - please submit a pull request, I can review.

tjanczuk commented 10 years ago

I have mixed feelings about this feature. I can see how a very advanced user can use it as a way to optimize their application, while the fundamental application architecture still relies on externalized state for correctness. I am concerned that an average user can treat this feature as a "guarantee" and rely on in-memory state in their application as the basis for the application design. These are some of the pitfalls false assumptions will lead to:

  1. Processes can come and go at any time with or without reason. App that relies on their continued existence for correctness is badly designed.
  2. Once the app needs to scale beyond one VM, the LB in front of the farm must support the same stickiness mechanism. I am not sure if e.g. WAWS load balancing is there yet.
  3. Cookies are only as good as the client's willingness to preserve them.
rramachand21-zz commented 10 years ago

Agreed - Yes it depends on how the application uses this feature and I am not sure how many applications would need to use this instead of storing the state externally..

queequac commented 10 years ago

That was the reason why I turned this feature off by default, so behavior would remain unchanged for the usual developer as long as not explicitly activated.

I do also agree that an app should not rely on the continued existence of the process. But could the same false assumption not be made with a single process? Nowadays people simply set the number of processes to 1 to get socket.io working or to have a session state. But in this scenario the proess can also come and go.

I can also understand the concers about LB and cookies... but as I said this would simply complement a sticky session approach on web farm level.

iamhenning commented 10 years ago

Is the feature request rejected (in that case close it, don’t keep it dangling open-end please) or still in consideration?

We are also struggling with iisnode and socket.io when scaling up.

Searching for solutions uncovered lots of posts where people are stating that this is simply not possible with iisnode. Even worse, it seems to be a “best practice” to set nodeProcessCountPerApplication = 1 when using socket.io. (see “Brief notes on iisnode and socket.io”, http://www.jokecamp.com/blog/getting-started-with-iisnode/)

Last week I have forked iisnode and merged the referenced pull-request into it, compiled and installed it for testing purposes ...and voila, the issue with socket.io is gone, not being stuck to a single core.

+1

vilicvane commented 9 years ago

Also facing the issue scaling up socket.io, I was thinking about other ways but it would be great if we may get through this "easy" path.

ramijarrar commented 8 years ago

Any possibility this will be integrated? We are facing the same issue running on Azure (which already provides the stickiness at the server level)

ryanmcafee commented 7 years ago

This was integrated into the Azure iisnode fork at: https://github.com/Azure/iisnode/releases/tag/v0.2.25