Support multiple workers / instances behind load balancer / reverse proxy (for example Gunicorn or similar) #1539
Replies: 8 comments 14 replies
-
Thanks for bringing this up @aersam. We would love to remove this limitation. But it might not be so simple.
The data part may become tricky. Let us consider a simple scenario with a load balancer / reverse proxy in the front and two workers / instances named A and B in the back. The correct page-builder function (decorated with Last week @falkoschindler voiced a possible alternative approach: what if the page builder does not execute the decorated function directly but only serves a super tiny, generic html page which establishes a websocket connection. Then the the page builder is executed after the websocket connection is established. We have not found the time to investigate this approach. Anybody interested in giving it a shot? |
Beta Was this translation helpful? Give feedback.
-
If we're running the page builder on incoming websocket instead of incoming http request, we need to abandon the ability to return Starlette/FastAPI responses. And we won't have access to the request parameters any longer. Another problem with multiple workers is the loss of global state. For example in a simple chat app, only the users on the same worker would see each other. |
Beta Was this translation helpful? Give feedback.
-
If we could auto-discover and reach all other workers we may be able to route the websocket stream to the correct worker. Or we simply write a tutorial on how to use a load balancer like Traefik which supports session affinity instead of plain gunicorn. |
Beta Was this translation helpful? Give feedback.
-
Do you have experience setting up session affinity with ngnix and nicegui? Would be interesting to see an example. |
Beta Was this translation helpful? Give feedback.
-
Has anyone considered the possibility of storing the The clients would be serialized using pickle, dill, cloudpickle. (Note that dill and cloudpickle have better support than pickle for serializing code such as Python lambdas.) For scaling across multiple servers, the I understand the earlier point about side effects, but I think this can be minimized or avoided through documentation. The basic guidance would be to that state is only accessible via fields of the |
Beta Was this translation helpful? Give feedback.
-
I think this (well-defined state) is the typical case for many applications. How many web applications have a USB camera device connected to the server? Regardless, perhaps the way to approach this would be to enhance NiceGUI to support pluggable state backends. Then people could select or build a state backend based on their needs. Another advantage of this approach is that the best backend could vary based on the scale of the application. E.g. an application with a handful of users may choose to use a SQL backend, while a high-volume application might use Redis or a NoSQL backend. |
Beta Was this translation helpful? Give feedback.
-
Related: Last year, I contributed a pluggable backend for MLflow (PR link). In that case, it was for authentication, not for state management. I mention this because, if there's potential interest in this idea, I may be able to contribute. I think this capability could significantly expand the potential number of users for NiceGUI. It's a really great package, and I'd love it if it were suitable for higher-volume applications. |
Beta Was this translation helpful? Give feedback.
-
can we using SSE technology to avoid websocket http upgrade? so that we can use gunicorn works. |
Beta Was this translation helpful? Give feedback.
-
This is a proposal after having discussed an issue in #1193
Currently nicegui cannot be used behind gunicorn or another reverse proxy without affinity support. This may lead to confusion and also I think it's straightforward to remove that limitation.
Reverse Proxies are quite common with FastAPI/Python since otherwise the Python GIL limits you quite a bit and a single long running request can block others (if not using async/await, sometimes you can't)
I think it would be possible for nicegui to implement support for running behind a reverse proxy without too much effort, but maybe I'm wrong. This is because once the websocket connection is established, only a single worker is involved anyway.
One would need persist the client(id/data) to disk on initial page render and then read it from there if needed. After the websocket handshake, everything works with the websocket which implies staying on the same worker. So only one hand-over between workers/processes is required.
Do you think that's something to consider? Or do I simply things too much?
Beta Was this translation helpful? Give feedback.
All reactions