-
Notifications
You must be signed in to change notification settings - Fork 444
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for running multiple Celery queues #1130
Comments
Hey @Ian2012! I'm glad you are opening this issue today as there are multiple conversations going on right now about Celery: As usual, I'd like to resolve these issues by:
Let's address these two items in reverse order: CustomizationLet's assume that we provide a mechanism in Tutor core that makes it possible to customize the celery command exactly as you need. You are then also able to run any celery worker by adding containers to the docker-compose/k8s override files. I don't have a perfect solution to this problem just yet, but I'm working on it. Assuming this solution exists, it should enable you to customize the celery workers as you see fit, right? There would be one remaining problem, which is the unavailability of gevent in the openedx Docker image. You propose to address this issue in your edx-platform PR. An alternative would be to add gevent to the additional packages installed by Tutor. Which solution do you like best? Good defaultsMy second concern is having good defaults for users who don't know how to tune celery workers. In your opinion, what changes should we make to the default celery command or settings to improve those defaults? For instance, in your tutor-contrib-celery plugin, I see that you set |
CustomizationI've seen some comments around having a For 'gevent', both options are available, but if it's okay to have it on the tutor, then let's proceed with that. Good defaultsBesides the
I can open a PR with the following changes to be considered:
|
Yes, I suggested that. But after investigating I found no way to configure a celery worker using such a settings file. As far as I know the Do you know a way to achieve that? |
We need to use the celery app default_config = 'myproj.celeryconfig'
app.config_from_object(default_config) |
It may require changes to edx-platform celery's app but I don't think we need it. We also have the option to use environment variables but python files provides more prefxility |
You are referring to this? https://docs.celeryq.dev/en/stable/reference/celery.html#celery.Celery.config_from_object As far as I know, this method is used to configure the Celery application, which is not the same thing as the Celery worker. For instance, were you able to configure the worker concurrency using this method? If yes, how? |
Yes, here is the code snippet with some other settings: CELERYD_CONCURRENCY = 2 # worker_concurrency
CELERYD_MAX_TASKS_PER_CHILD = 100 # worker_max_tasks_per_child
CELERYD_POOL = 'threads' # worker_pool See https://celery-safwan.readthedocs.io/en/latest/userguide/configuration.html#new-lowercase-settings for more information on the available settings, users can also use the We are still missing having separate settings for each lms-worker queue but that can be solved by injecting an environment variable and dynamically resolve the settings on a dictionary: CELERY_WORKER_TYPE = os.environ.get("CELERY_WORKER_TYPE", "default")
worker_settings = {
"lms": {
"default": {
"parameters": {
"worker_concurrency": 4,
"worker_pool": "threads"
}
},
"high": {},
"high_mem": {},
},
"cms": {
"default": {},
"low": {},
},
}
from openedx.core.lib.celery import APP
worker_variants = worker_settings.get(SERVICE_VARIANT)
for variant, config in worker_variants.items():
if CELERY_WORKER_TYPE == variant:
for parameter, value in config.get("parameters", {}).items():
conf = APP.conf
setattr(conf, parameter, value) This is working locally |
Some parameters cannot be added this way, like the queues but can be added to the command line args. But if we are going to add command line arguments and everything is configurable using the pattern above then we don't need this script, just inject every setting via the filter and allow operators to override it |
This is the POC: #1131 |
CustomizationI saw your PoC ##1131. I'm not in favor of a filter that would be used to create extra containers. There is already another mechanisms to do that, which is patching the docker-compose/deployments.yml files. Let's avoid creating another one. Let's focus on the best mechanism to override/customise the existing celery command. Controlling celery via environment variables or a celeryconfig.py file will give us limited control, because not all CLI options can be configured using this mechanism. In particular, I suggest to use two filters: Good defaultspool
We should stick to just one worker for the LMS and the CMS. Any extra worker will use extra server resources. In that context, I think we should stick to processes and the autoscaleIs it really a good idea to default to acks_late
|
CustomizationI don't think we would need two filters, I think the lms and cms queues are already very similar, so we can just use one filter for it: Good defaultspoolAre we just going to use add one queue? Operators should be able to add workers for the different queues to improve the performance of those tasks. Also, the current implementation can cause problems because it only excludes the default queue from the other service, but other queues such as lms autoscaleNo, it causes problems with CPU/memory HPA and doesn't provide any advantages over scaling the deployments. This would only benefit local installations, not k8s installations. I wouldn't default this one but leave a warning or recommendation in the docs for it. acks_lateNo, it will not retry failed tasks. Failed tasks will be acknowledged as failed, but will not be retried. Late acknowledge prevents forceful killed workers from removing tasks from the queue. Multique queuesThen, will If it is a resource problem, can we default to only one worker but allow to have multiple workers with different settings? This is what we already do on the Celery plugin. |
I also imagine having multiple queues only on Kubernetes deployment, not in local installations |
Hi! Joining late to the conversation, but I would like to leave my 50 cents:
|
@regisb I've updated the POC to use the two new filters to define the celery command: #1134 btw, one issue with the |
Is your feature request related to a problem? Please describe.
Open edX already has implemented solutions for running multiple celery queues such as the old known
high
andhigh_mem
default queues however, tutor operates by using a single worker deployment with a default pool (prefork
) and this is not always as performant as desired as that pool is designed for CPU intensive tasks such as the ones related to grading, while I/O bound tasks such as the ones used in Aspects would benefit from having agevent
pool which used green threads aka virtual threads to accomplish high levels of concurrency. This has already been tested and implemented in tutor-contrib-celery and the benefits have been notorious as the resources are better handled and I/O bound tasks are resolved pretty fast.Describe the solution you'd like
Allow tutor users to configure multiple Celery deployments with specialized settings for each queue's tasks. With defaults matching what's currently expected to run on each queue.
Describe alternatives you've considered
Developing a separate plugin for Celery: tutor-contrib-celery however we think the community would benefit from having a standard way to set Celery and also don't need to build a custom openedx images with those requirements: openedx/edx-platform#35591
Additional context
https://celery.school/celery-worker-pools
The text was updated successfully, but these errors were encountered: