前言

作为 Django 应用程序开发人员,您经常遇到这样的情况:您希望能够执行周期性的异步后台任务。如果您想创建一些背景检查、发送通知或构建缓存,它会派上用场

我的第一选择是安装django-celery-beats。我对结果很满意。我能够根据用户配置动态配置我的周期性任务,因为 Celery 从数据库读取执行配置。

另一方面,我的应用程序现在依赖于celery(必须作为单独的服务运行)和Redis服务器(芹菜用作消息代理)。

应用程序的容器化变得很奇怪。我不确定,我是否应该将celery服务包含在容器内或作为使用docker-compose的依赖项。我还认为我只需要Redis实例来执行定期任务是荒谬的。我还想减小hypervisord配置的大小。

我想保持灵活性,但减少依赖项和配置样板的数量。

解决方案

我celery在不需要的应用程序中去掉了(我没有使用其他伟大的 celery 功能)。我只想从django.conf.settings或数据库加载周期性。

我使用Alpine Linux作为我的应用程序的基本映像。基本操作系统已经可以处理周期性任务的执行。这是好老crond。该配置在Alpine Linux docs 中有描述。

我创建了一个简单的Django管理命令叫setup我的应用程序。我们还假设我有另一个 Django 管理命令popularity,它应该每五分钟运行一次。在这个例子中,我将从 Django 设置变量中读取一个配置,CRON_JOBS它可能如下所示:

CRON_JOBS = {
    'popularity': '*/5 * * * *'
}

变量由Django management command名称和 periodicity对组成。该命令将crond使用python-crontab库根据它创建一个配置。该命令应该在第一次运行之前和每次配置更改时运行(请记住,因为您已经从管理命令创建 CRON 作业规则,您可以使用 ORM 从数据库读取配置)。

# management/commands/setup.py
from crontab import CronTab
from django.core.management import BaseCommand

class Command(BaseCommand):
    cron = CronTab(tabfile='/etc/crontabs/root', user=True)
    cron.remove_all()

    for command, schedule in settings.CRON_JOBS.items():
        job = cron.new(command='cd /usr/src/app && python3 manage.py {}'.format(command), comment=command)
        job.setall(schedule)
        job.enable()

    cron.write()

请记住,如果您从数据库加载数据,则必须使用setup管理命令再次执行此更改。您可以使用call_command方法实现此目的。

from Django.core import management

def save_config():
    # do whatever you want
    management.call_method('setup')

创建容器

正如我之前所说,我的 Django 应用程序基于 Alpine Linux 容器,并从entrypoint.sh负责(按上述顺序)执行:

1.执行migrations,
2.执行setup创建初始 CRON 作业配置的管理命令,
3.并初始化supervisord服务(将管理gunicorn和crond服务)。

supervisord 配置

我supervisord用来管理gunicorn应用服务器和crond服务的执行。

如果应用程序位于/usr/src/app目录中并gunicorn安装在目录中,则/root/.local/bin/gunicorn 可能supervisor.conf如下所示:

[supervisord]
nodaemon=true

[program:gunicorn]
directory=/usr/src/app
command=/root/.local/bin/gunicorn -b 0.0.0.0:8000 -w 4 my_app.wsgi --log-level=debug --log-file=/var/log/gunicorn.log
autostart=true
autorestart=true
priority=900

[program:cron]
directory=/usr/src/app
command=crond -f
autostart=true
autorestart=true
priority=500
stdout_logfile=/var/log/cron.std.log
stderr_logfile=/var/log/cron.err.log

Dockerfile

最小Dockerfile必须至少包含:

  • 复制应用程序源代码,
  • 安装依赖项,
  • 复制配置,
  • 入口点的执行。
FROM alpine:3.15

WORKDIR /usr/src/app

# Copy source
COPY . .

# Dependencies
RUN apk add --no-cache python3 supervisor 
RUN pip3 install --user gunicorn
RUN pip3 install --user -r requirements.txt

# Configuration
COPY conf/supervisor.conf /etc/supervisord.conf

# Execution
RUN chmod +x conf/entrypoint.sh
CMD ["conf/entrypoint.sh"]
点赞(0)

评论列表 共有 0 评论

暂无评论

微信服务号

微信客服

淘宝店铺

support@elephdev.com

发表
评论
Go
顶部