Repository navigation
Replies: 1 comment 3 replies
No. Absolutely not. |
3 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Current status
Granian does not provide a mechanism for load balancing between workers. Since a thread separate from the application thread performs accept in the worker, there is a possibility that a busy worker will accept instead of an idle worker until it reaches backpressure, resulting in an uneven load.
#544
This PR enables SO_REUSEPORT and allows each worker to have its own backlog. Linux distributes connections based on the hash value of the socket pair, which achieves a distribution close to random.
In addition, this also avoids the thundering herd problem where multiple workers wake up simultaneously for new connections.
On the other hand, because the backlog is distributed, there was a problem that the contents of the backlog held by the worker that terminates during a graceful restart are discarded.
#567
#579
In this PR, to fix graceful restart, workers share the listening socket again. SO_REUSEPORT remains enabled, but it no longer has any effect.
Idea
Each worker listens on its own independent port. This allows a reverse proxy like nginx to distribute connections using algorithms such as least conn or round robin.
When performing a graceful restart, the old worker and the new worker share the same listening socket, so requests remaining in the backlog are not discarded.
This idea is not my original. It is described in the uWSGI documentation, and we are currently using it in our production environment.
https://uwsgi-docs.readthedocs.io/en/latest/articles/SerializingAccept.html#bonus-chapter-using-the-zeeg-approach-in-a-uwsgi-friendly-way
Before considering whether this idea will be accepted and how to support it in the CLI, I first verified whether this idea is valid for granian.
Prooof of concept
application
This sample application is about 50% CPU bound and 50% I/O bound.
If the load is well balanced, using 2 threads should yield performance close to double.
nginx configuration
8 workers, 1 thread, backpressure=1
server:
load test:
This result is a reference value when the load balance is close to ideal.
4 workers, 4 threads, backpressure=4
load test:
You can see that the values of Avg, Stdev, Max have deteriorated significantly.
4 workers, 4 threads, backpressure=4, dedicated port for each worker
poc patch for multiport support: https://gist.github.com/methane/205485901684a66f4e77a399a49c4cb1
load test:
You can see that the values of Avg, Stdev, and Max have come quite close to those of 8process/1thread.
All reactions