-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Description
Currently all workers are accepting in // with no dialog which make them sometimes accepting the same connection triggering EAGAIN and increasing the CPU usage for nothing.
While modern OSes have mostly fixed that it still can happen in Gunicorn since we can listen on multiple interface.
Solution
The solution I see for that is to introduce some communication between the arbiter and the workers. The accept will still be executed directly in the callers workers if the socket accept returns ok. Otherwise the listen socket is "selected" in the arbiter using an eventloop and an input ready callback will run socket accept from a worker when the event is triggered.
Implementation details:
While it can change in the future by adding more methods like sharing memory between the arbiter and the worker, we will took the simple path for now:
- 1 pipe will be maintained between the arbiter and the worker. This pipe will be used for the signaling.
- The arbiter will put all listener sockets in an eventloop. Once the read event is triggered it will notify one of the available workers to accept.
- For the eventloop it will use the selectors in python 3. It will backported for python 2.x
Usual garbage collection will take care about closing the pipe when needed.
* note* Possibly, the pipe will also let the workers notify the arbiter they are alive.
Problems to solve
Each async worker are accepting using their own method without much consideration to gunicorn right now. For example the gevent worker is using the gevent Server object, tornado and eventlet use similar system. We should find a way to adapt them to use the new socket signaling system.
Thoughts? Any other suggestions?