Fix autoscale when prefetch_multiplier is 1#6069
Merged
Merged
Conversation
6 tasks
This was referenced May 4, 2020
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This PR is to address issue: #4003
I came across this issue because celery autoscaling wasn't working while running it with airflow. Other people running airflow have had the same issue:
apache/airflow#3989 (comment)
I looked into this and I think the issue surfaces when the prefetch_multiplier=1 and task_acks_late=True. Under those circumstances the prefetch_count is set to the lower bound of the autoscale range:
https://github.com/celery/celery/blob/4.4.2/celery/worker/components.py#L226
In this situation we are caught in a catch-22 with respect to auto-scaling. In order to bump the processes we need autoscale.qty (i.e. reserved requests) to be greater than the number of processes:
https://github.com/celery/celery/blob/4.4.2/celery/worker/autoscale.py#L89
but to increase the prefetch count which would increase the reserved requests, we need to increase the number of processes:
https://github.com/celery/celery/blob/4.4.2/celery/worker/autoscale.py#L140
So we're stuck.
Things work Ok if you have a prefetch_multiplier > 1 because you essentially jump start the prefetch_count. Same goes if you have task_acks_late=False even with prefetch_multiplier=1 because the reserved_requests exceeds the number of processes because we ack before completing each task.
In this PR, I've set the prefetch_count to the upper_bound of the autoscale range on start up rather than the lower bound. Now if work is available reserved_requests will be able to bump up and then the process count will follow suit.
If the user has set an upper bound they should be Ok with pulling that much work (and consequently scaling up workers) if that work is available. With the prefetch count set at the upper bound then there is no need to update in the _grow and _shrink methods.
Below example program to demonstrate failure to scale with prefetch_multiplier=1 and task_acks_late=True.
tasks.py:
Run:
celery worker -A tasks --autoscale=6,3 --prefetch-multiplier=1and you'll see that we dont' budge off of 3 processes.