Move Celery check task to the high priority queue - #23731
Conversation
|
Thanks for the pull request, @kaizoku! I've created OSPR-4388 to keep track of it in JIRA, where we prioritize reviews. Please note that it may take us up to several weeks or months to complete a review and merge your PR. Feel free to add as much of the following information to the ticket:
All technical communication about the code itself will be done via the GitHub pull request interface. As a reminder, our process documentation is here. Please let us know once your PR is ready for our review and all tests are green. |
|
@kaizoku Thank you for your contribution. Please let me know once it is ready for our review. |
|
Thanks @natabene, this is ready for review. |
|
@kaizoku Thanks for letting me know, I will queue it for our review. |
There was a problem hiding this comment.
👍
- I tested this:
- Checked that the task is registered in the high priority queue:
-> celery@edx.lms.core.high.edxapp-pr23731sandbo-appserver-1: OK
* openedx.core.djangoapps.heartbeat.tasks.sample_task [routing_key=edx.lms.core.high]
- I read through the code
-
I checked for accessibility issuesNA -
Includes documentationNA
@kaizoku Good to go!
@natabene I'll add this to the prioritization list.
|
@natabene has this PR come up for review yet? |
|
@kaizoku No, not yet. |
cf https://github.com/edx/edx-platform/pull/23731 Move Celery check task to the high priority queue Currently, LMS uses 3 Celery workers: lms_default_1, lms_high_1 and lms_high_mem_1. Each Celery worker sends messages to a single queue: edx.core.default, edx.core.high and edx.core.high_mem, respectively. The number of child processes per Celery worker is set to 1. Due to this configuration, any task in a queue blocks all other tasks. Currently, the Celery check task submitted by the /heartbeat?extended LMS HTTP API endpoint runs in the default queue. When some slow task (eg course grades creation) is sent to the default queue, it will block the Celery check task, which will expire and the heartbeat endpoint will fail. This patch moves the task to another queue which has only shorter tasks and in which this problem will not occur. Use a Django setting for the Celery check task routing key so that it can be overriden by individual OpenEDX instances via JSON env files. (cherry picked from commit eaf229556365889d66ac7c9baeb866df0d659e11)
|
jenkins run all |
|
@kaizoku Can you rebase this one? It's been already approved. |
|
@giovannicimolin Just FYI we will need one more approver, someone with edx-platform code ownership. |
|
@natabene I though that @fredsmith had ownership here. Since he approved I assumed this was good to go. |
|
@giovannicimolin Yeah, it was my bad. He confirmed he would like someone with edx-platform ownership to review, too. |
cf https://github.com/edx/edx-platform/pull/23731 Move Celery check task to the high priority queue Currently, LMS uses 3 Celery workers: lms_default_1, lms_high_1 and lms_high_mem_1. Each Celery worker sends messages to a single queue: edx.core.default, edx.core.high and edx.core.high_mem, respectively. The number of child processes per Celery worker is set to 1. Due to this configuration, any task in a queue blocks all other tasks. Currently, the Celery check task submitted by the /heartbeat?extended LMS HTTP API endpoint runs in the default queue. When some slow task (eg course grades creation) is sent to the default queue, it will block the Celery check task, which will expire and the heartbeat endpoint will fail. This patch moves the task to another queue which has only shorter tasks and in which this problem will not occur. Use a Django setting for the Celery check task routing key so that it can be overriden by individual OpenEDX instances via JSON env files. (cherry picked from commit eaf229556365889d66ac7c9baeb866df0d659e11)
nasthagiri
left a comment
There was a problem hiding this comment.
Once the rename is complete and merge conflicts are corrected, we can go ahead and merge.
There was a problem hiding this comment.
Can you rename this setting to be consistent with the other related settings?
Suggestion: CELERY_CHECK_ROUTING_KEY -> HEARTBEAT_CELERY_ROUTING_KEY
There was a problem hiding this comment.
Yes, I've updated this variable name to be more consistent with the others.
eaf2295 to
831da76
Compare
831da76 to
6b9cba5
Compare
Currently, LMS uses 3 Celery workers: lms_default_1, lms_high_1 and lms_high_mem_1. Each Celery worker sends messages to a single queue: edx.core.default, edx.core.high and edx.core.high_mem, respectively. The number of child processes per Celery worker is set to 1. Due to this configuration, any task in a queue blocks all other tasks. Currently, the Celery check task submitted by the /heartbeat?extended LMS HTTP API endpoint runs in the default queue. When some slow task (eg course grades creation) is sent to the default queue, it will block the Celery check task, which will expire and the heartbeat endpoint will fail. This patch moves the task to another queue which has only shorter tasks and in which this problem will not occur. Use a Django setting for the Celery check task routing key so that it can be overriden by individual OpenEDX instances via JSON env files.
6b9cba5 to
b9559fc
Compare
kaizoku
left a comment
There was a problem hiding this comment.
Thanks @nasthagiri, I've rebased against master and updated the variable name.
Is this otherwise good for merge now?
There was a problem hiding this comment.
Yes, I've updated this variable name to be more consistent with the others.
| TRACKING_SEGMENTIO_SOURCE_MAP = ENV_TOKENS.get("TRACKING_SEGMENTIO_SOURCE_MAP", TRACKING_SEGMENTIO_SOURCE_MAP) | ||
|
|
||
| # Heartbeat | ||
| HEARTBEAT_CELERY_ROUTING_KEY = ENV_TOKENS.get('HEARTBEAT_CELERY_ROUTING_KEY', HIGH_PRIORITY_QUEUE) |
There was a problem hiding this comment.
Can you update the default value here to be HEARTBEAT_CELERY_ROUTING_KEY? This way, (1) the value of HIGH_PRIORITY_QUEUE can be set only in a single place in common.py and (2) it supports other overrides along the way, like in private.py.
This will hopefully be the last change before merge.
There was a problem hiding this comment.
Sure @nasthagiri, that's a good application of DRY and I've updated this for the lms and cms production.py.
|
Your PR has finished running tests. There were no failures. |
| ) | ||
|
|
||
| HEARTBEAT_CELERY_TIMEOUT = 5 | ||
| HEARTBEAT_CELERY_ROUTING_KEY = HIGH_PRIORITY_QUEUE |
There was a problem hiding this comment.
One more last thing (sorry), is there a reason you change the pre-existing default value? By default, the code had been using CELERY_DEFAULT_ROUTING_KEY for this (which defaults to the CELERY_DEFAULT_QUEUE). To be on the safe side (unless it was intentional), let's change the value of this to CELERY_DEFAULT_ROUTING_KEY.
There was a problem hiding this comment.
No worries @nasthagiri, this change was intentional. The original intent behind this PR was to change the heartbeat queue to the high priority. We ran into problems when running grade reports or other long running tasks since all default priority workers were busy, so the celery heartbeat check would time out and trigger false positives in our monitoring infrastructure. Moving this heartbeat check to the high priority queue prevents that since there's generally a high priority worker available.
|
@kaizoku 🎉 Your pull request was merged! Please take a moment to answer a two question survey so we can improve your experience in the future. |
|
EdX Release Notice: This PR has been deployed to the staging environment in preparation for a release to production. |
|
EdX Release Notice: This PR has been deployed to the production environment. |
|
@kaizoku this PR introduced a bug because the default queue naming in |
common.py has queue names that always get overridden by production.py and lead to confusion. Set a default SERVICE_VANIANT in common.py and then set the queue names based on that in common.py so that production.py doesn't make it more complicated. This should prevent the issue where if you copy a queue name in common.py it ends up being incorrect in the production system. This is what happened with the sample_task change. https://github.com/edx/edx-platform/pull/23731 made it so that the queue name for that queue is independently configurable but the default was set to the value of HIGH_PRIORITY_QUEUE in common.py which is not the same as the value set in production.py leading to stale tasks that never get picked up in production. BREAKING_CHANGE: If anyone was building a different settings file on top of common, the default names in common.py are now change to be service variant specific. eg 'edx.cms.core.high' instead of 'edx.core.high'
Currently, LMS uses 3 Celery workers:
lms_default_1,lms_high_1, andlms_high_mem_1. Each Celery worker sends messages to a single queue:edx.core.default,edx.core.highandedx.core.high_mem, respectively.The number of child processes per Celery worker is set to 1. Due to this configuration, any task in a queue blocks all other tasks.
Currently, the Celery check task submitted by the /heartbeat?extended LMS HTTP API endpoint runs in the default queue. When some slow task (eg course grades creation) is sent to the default queue, it will block the Celery check task, which will expire and the heartbeat endpointwill fail. This patch moves the task to another queue which has only shorter tasks and in which this problem will not occur.
Use a Django setting for the Celery check task routing key so that it can be overriden by individual OpenEDX instances via JSON env files.
JIRA tickets: Implements OSPR-4325
Sandbox URL: TBD - sandbox is being provisioned.
Testing instructions:
Reviewers