Transformación asincrónica del proyecto Django - Apio

Celery es un sistema distribuido simple, flexible y confiable que puede manejar grandes volúmenes de mensajes y al mismo tiempo proporciona a las operaciones las herramientas que necesitan para mantener el sistema. Esta es una cola de tareas que se centra en el procesamiento en tiempo real y también admite la programación de tareas.

Celery se comunica a través de mensajes, normalmente utilizando un intermediario para mediar entre clientes y trabajadores. Para iniciar una tarea, el cliente pone un mensaje en la cola y el intermediario entrega el mensaje al trabajador.

Un sistema Celery puede estar compuesto por varios trabajadores y corredores para lograr alta disponibilidad y escalabilidad horizontal.

En proyectos web, generalmente debido a la limitación del tiempo de espera del servidor http, la tarea no se puede completar dentro del tiempo especificado, lo que requiere el uso de una implementación asincrónica. A continuación se explica cómo utilizar el apio para transformar un proyecto Django existente.

1. Instalar dependencias

pip install celery redis

El redis instalado por pip no se puede utilizar en el proyecto porque necesita instalarse en el entorno, el método es el siguiente:

wget http://download.redis.io/releases/redis-3.2.8.tar.gz -o /home/admin/package/
cd /home/admin/package/ 
tar -zxvf redis-3.2.8.tar.gz 
mv ./redis-3.2.8 /usr/local/redis/ 
cd /usr/local/redis/ 
make 
make install 
cd utils 
echo | /bin/bash install_server.sh  

2. Configurar el apio

2.1、configuración.py

Agregue la siguiente configuración en el archivo settings.py del proyecto Django:

# 配置 Celery
CELERY_BROKER_URL = 'redis://localhost:6379/0'
CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'

# 配置 redis
REDIS_HOST = [("127.0.0.1", 6379)]
REDIS_PASSWORD = ""

2.2 Configuración en el directorio de inicio del proyecto

2.2.1、__init__.py

#coding=utf-8
from __future__ import absolute_import, unicode_literals

from django.conf import settings
from .celery import app as celery_app
from ._redis import TaskRedis

redis_client = TaskRedis(
    settings.REDIS_HOST,
    settings.REDIS_PASSWORD,
    db=1
)

__all__ = ['celery_app']

2.2.2 Crear un nuevo archivo de configuración de apiocelery.py

#!/usr/bin/env python
# coding=utf-8
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery, platforms

from django.conf import settings

from celery.schedules import crontab
from datetime import timedelta

os.environ.setdefault('DJANGO_SETTINGS_MODULE', '项目名称.settings')
platforms.C_FORCE_ROOT = True
app = Celery('项目名称', backend='redis://localhost:6379/1', broker='redis://localhost:6379/0')

# 将settings对象作为参数传入
app.config_from_object('django.conf:settings', )

# celery 自动发现任务: APP/tasks.py
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

# 设置定时参数
app.conf.update(

    # 并发数
    CELERYD_CONCURRENCY=4,
    # 每个worker 执行多少任务就kill
    CELERYD_MAX_TASKS_PER_CHILD=50,

    # celery 路径
    CELERY_ROUTES={
    
    
        "项目名称.tasks.add": {
    
    "queue": "q1"},  # 把add任务放入q1队列
    },
    # celery beat 调度
    CELERYBEAT_SCHEDULE={
    
    
        "asy-update-info": {
    
    
            "task": "get_info",
            "schedule": crontab(minute=0,hour=1),                       # 定时同步aone信息
        },
    # 定时执行    
    #    "schedule": crontab(minute=0, hour=3),  # 每日早上3点
    #    "schedule": crontab(minute=0, hour=1),
    #    "schedule": crontab(minute=0, hour=1), 
    #    "schedule": crontab(minute=0, hour="*/1") # 每隔1小时执行一次
    #    "schedule": crontab(minute=0, hour="*/12") # 每隔十小时执行一次
    #    "schedule": crontab(minute=0, hour=3) # 每日凌晨3点
    #    "schedule": crontab(minute=0, hour=3, day_of_week=2) # 每周二凌晨3点
    #    "schedule": crontab(minute=0, hour=3, day_of_week=1)  # 每周一凌晨3点
    #    "schedule": crontab(minute=0, hour=3, day_of_week=2) # 每周二凌晨3点
    #    "schedule": crontab(minute=0, hour=3, day_of_week=2) # 每周二凌晨3点
    #    "schedule": crontab(minute=0, hour=4, day_of_week='1,4')  # 每周一、四凌晨4点
    #     
)


@app.task(bind=True)
def debug_task(self):
    print('Request: {0!r}'.format(self.request))

2.2.3 Crear el archivo del método de información de la cola almacenado por redis en el directorio del proyecto_redis.py

#coding:utf-8

import datetime
import json

from redis import Redis, ConnectionPool


class RedisInit(object):

    def __init__(self, redis_config, password, master=None, connect_type='direct', db=0):
        """
        :param redis_config:
        :param password:
        :param master:
        :param connect_type: 连接方式 direct: 直连 sentinel: 哨兵
        """
        self.redis_config = redis_config
        self.password = password
        self.master = master
        self.connect_type = connect_type
        self.redis = None
        self.host, self.port = self.redis_config[0]
        self.db = db
        self._connect()

    def _connect(self):
        # 直接
        if self.connect_type == 'direct':
            self.pool = ConnectionPool(host=self.host, port=self.port, password=self.password, db=self.db,
                                       max_connections=200, socket_keepalive=True, decode_responses=True)
            self.redis = Redis(connection_pool=self.pool)
        # 哨兵
        else:
            # 哨兵连接池
            self.sentinel = Sentinel(self.redis_config, password=self.password, db=self.db,
                                     socket_keepalive=True, decode_responses=True)
            self.redis = self.sentinel.master_for(self.master, max_connections=200)


class TaskRedis(RedisInit):
        
    def __init__(self, *args, **kwargs):
        super(TaskRedis, self).__init__(*args, **kwargs)

    def _set_task(self, key, task_id):
        """
        缓存 task 的celery对象
        :param key 键
        :param task_id celery task id
        :return
        """
        self.redis.set(key, task_id)
        self.redis.expire(key, 7200)

    def _get_task_id(self, key):
        """
        获取celery的task id
        """
        return self.redis.get(key)

3. Transformación asincrónica de tareas

3.1 Modificar la función de la tarea

Django mediotask.py

from celery import task
from celery import shared_task

@shared_task
def add(x, y):
    sleep(5)
    return x + y

3.2 Tareas desencadenantes

En Django view.py, solo necesitas agregar delay()métodos a la función:

from .tasks import add

result = add.delay(4, 4)

4. Inicia el proyecto del apio.

Al iniciar el proyecto, use el siguiente comando para iniciar el apio

# 在Django项目主目录下
celery -A '项目名称' worker -l info 

Please specify a different user using the -u option.

User information: uid=0 euid=0 gid=0 egid=0

  uid=uid, euid=euid, gid=gid, egid=egid,
 
 -------------- celery@x.x.x.x v3.1.25 (Cipater)
---- **** ----- 
--- * ***  * -- Linux-5.10.84-004x86_64-x86_64-with-redhat-7.2
-- * - **** --- 
- ** ---------- [config]
- ** ---------- .> app:         '项目名称':0x7feac79c3390
- ** ---------- .> transport:   redis://localhost:6379/0
- ** ---------- .> results:     redis://localhost:6379/1
- *** --- * --- .> concurrency: 4 (prefork)
-- ******* ---- 
--- ***** ----- [queues]
 -------------- .> celery           exchange=celery(direct) key=celery
                
[tasks]
  . add
  
[2023-04-24 06:47:56,647: INFO/MainProcess] Connected to redis://localhost:6379/0
[2023-04-24 06:47:56,652: INFO/MainProcess] mingle: searching for neighbors
[2023-04-24 06:47:57,656: INFO/MainProcess] mingle: all alone
[2023-04-24 06:47:57,662: WARNING/MainProcess] /usr/lib/python2.7/site-packages/celery/fixups/django.py:265: UserWarning: Using settings.DEBUG leads to a memory leak, never use this setting in production environments!
  warnings.warn('Using settings.DEBUG leads to a memory leak, never '
[2023-04-24 06:47:57,663: WARNING/MainProcess] celery@x.x.x.x ready.

Mantenga los comandos ejecutándose en segundo plano

celery -A '项目名称' worker -l info --detach

Registro de salida al archivo de registro

celery -A '项目名称' worker -l info --loglevel=debug --logfile=tasks.log

Documentación de referencia

1. https://www.celerycn.io/ru-men/celery-jian-jie

2, https://www.cnblogs.com/fisherbook/p/11089243.html

Supongo que te gusta

Origin blog.csdn.net/yuelai_217/article/details/130363557
Recomendado
Clasificación