Reputation: 59
I have a Django application with two celery tasks set up. Both the tasks need to run only once at one minute after midnight (12:01 AM). This is just to update some statuses which change from "ACTIVE" to "INACTIVE" at 12:01 AM.
My goal is to reduce the number of times Celery polls Redis. Currently, it polls every second which is problematic.
I took three steps
I tried to change the settings in Django for Celery inlcuding using paramters such as CELERY_IGNORE_RESULT
, CELERY_WORKER_CONCURRENCY
, CELERY_BROKER_HEARTBEAT
and lastly CELERY_BEAT_MAX_LOOP_INTERVAL
CELERY_RESULT_BACKEND = None
CELERY_IGNORE_RESULT = True # Ignore task results to reduce Redis usage
CELERY_ACCEPT_CONTENT = ["json"]
CELERY_TASK_SERIALIZER = "json"
CELERYD_PREFETCH_MULTIPLIER = 1 # Fetch only 1 task at a time
CELERY_ACKS_LATE = True # Acknowledge tasks after completion to avoid re-execution on failure
# Celery transport options
CELERY_BROKER_TRANSPORT_OPTIONS = {
'ssl': {
'ssl_cert_reqs': ssl.CERT_NONE # Suggestion: CERT_REQUIRED for stronger security
},
'visibility_timeout': 3600, # Timeout for long-running tasks
'polling_interval': 30 # Poll every 30 seconds
}
CELERY_RESULT_BACKEND_TRANSPORT_OPTIONS = {
'ssl': {
'ssl_cert_reqs': ssl.CERT_NONE # Same as broker for consistency
}
}
# Reduce the number of threads/processes
CELERY_WORKER_CONCURRENCY = 1
# Disable sending task events
CELERY_WORKER_SEND_TASK_EVENTS = False
# Disable remote control commands
CELERY_WORKER_ENABLE_REMOTE_CONTROL = False
# Disable broker heartbeat messages
CELERY_BROKER_HEARTBEAT = None
CELERY_BEAT_MAX_LOOP_INTERVAL = 3600 # Check for scheduled tasks every hour
Secondly, I even tried to set up dynamic polling so that the polling schedule is more frequent in during night time and reduced again
def set_polling_interval():
now = datetime.now()
if now.hour == 23 and now.minute >= 59 or now.hour == 0 and now.minute <= 15:
# Between 11:59 PM and 12:15 AM, poll more frequently
app.conf.broker_transport_options = {'polling_interval': 30} # Poll every 30 seconds
logger.info("Polling every 30 seconds between 11:59 PM and 12:15 AM.")
else:
# During the rest of the day, poll less frequently (every 24 hours)
app.conf.broker_transport_options = {'polling_interval': 86400} # Poll every 24 hours
logger.info("Polling every 24 hours outside the midnight window.")
Lastly, because I have Django Celery Beat installed, I tried tweaking the settings there directly in the "Intervals" and "Crontabs" section, but that did not help either.
Despite these efforts, Celery is still polling Redis every second. I checked the documentation for optimization, but struggled to find a solution there https://docs.celeryq.dev/en/stable/userguide/optimizing.html
The following article was also referred so that maybe I can do the opposite of it but that did not work either
Can I use celery for every-second task?
Upvotes: 0
Views: 105