当前位置: 首页 > news >正文

Celery使用:优秀的python异步任务框架

目录

  • Celery 简介
    • 介绍
    • 安装
    • 基本使用
  • Flask使用Celery
    • 异步任务
    • 定时任务
  • Celery使用Flask上下文
  • 进阶使用参考
    • 停止Worker
    • 后台运行

Celery 简介

介绍

Celery 是一个简单、灵活且可靠的,处理大量消息的分布式系统,并且提供维护这样一个系统的必需工具。

它是一个专注于实时处理的任务队列,同时也支持任务调度。

Celery 通过消息机制进行通信,通常需要中间人(Broker)和工作者(Worker)来进行调节。其中Broker就是消息中间件(常用的rabbitmq和redis),主要用来进行发送和接收消息;Worker就是任务的执行单元,通常是开发者来自己定义任务的内容。

Celery 特点:

  • 简单:Celery 上手比较简单,不需要配置文件就可以直接运行;
  • 高可用:如果出现丢失连接或连接失败,职程(Worker)和客户端会自动重试,并且中间人通过 主/主 主/从 的方式来进行提高可用性;
  • 快速:单个 Celery 进行每分钟可以处理数以百万的任务,而且延迟仅为亚毫秒(使用 RabbitMQ、 librabbitmq 在优化过后);
  • 灵活:Celery 的每个部分几乎都可以自定义扩展和单独使用,例如自定义连接池、序列化方式、压缩方式、日志记录方式、任务调度、生产者、消费者、中间人(Broker)等。

Celery 主要用途:

  • 异步执行:解决耗时任务,将耗时操作任务提交给Celery去异步执行,比如发送短信/邮件、消息推送、音视频处理等等;
  • 延迟执行:解决延迟任务,比如有些跑批接口的任务,需要耗时比较长;
  • 调度:可以通过调度功能在一段时间内指定任务的执行时间 datetime,也可以根据简单每隔一段时间进行执行重复的任务,支持分钟、小时、星期几,也支持某一天或某一年的Crontab表达式。

Celery 主要架构:

celery 的5个主要角色:

  1. Task:就是任务,有异步任务和定时任务;
  2. Broker:中间人,接收生产者发来的消息即Task,将任务存入队列。任务的消费者是Worker。Celery本身不提供队列服务,推荐用Redis或RabbitMQ实现队列服务;
  3. Worker:执行任务的单元,它实时监控消息队列,如果有任务就获取任务并执行它;
  4. Beat:定时任务调度器,根据配置定时将任务发送给Broker;
  5. Backend:用于存储任务的执行结果(例如:SQLAlchemy/Django] ORM、Memcached、Redis、 RPC RabbitMQ/AMQP)以及自定义的后端结果存储中间件)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vuSOPV5s-1679397896074)(./imgs/1.png)]

安装

安装比较简单,命令如下:

pip install Celery

另外Celery 自定义了一组用于安装 Celery 和特定功能的依赖。可以在中括号加入您需要依赖,并可以通过逗号分割需要安装的多个依赖包,例如安装rabbitmq和redis依赖,如下:

pip install "celery[librabbitmq,redis]"

注意:RabbitMQ 是默认的中间人(Broker),只需要配置连接的URL即可,不需要安装额外的的配置以及初始化配置信息。但是使用redis作为中间件时(或作为结果存储),必须要安装 Celery 的依赖库,按照上面的命令即可。

基本使用

选用rabbitmq作为Broker。

创建一个工程,保存为一个 app 文件中。针对大型的项目,可能需要创建 独立的模块。

首先创建 tasks.py:

from celery import Celeryapp = Celery('tasks',broker='amqp://guest:guest@localhost:5672',backend='redis://localhost')@app.task
def add(x, y):return x + y

Celery参数:

第一个参数为当前模块的名称,只有在 __main__模块中定义任务时才会生产名称。

第二个参数为中间人(Broker)的链接 URL ,实例中使用的 RabbitMQ(Celery默认使用的也是RabbitMQ)。

第三个参数为后端结果链接,实例中使用的redis。

这里创建了一个名称为 add 的任务,返回的俩个数字的和。

然后启动celery服务:

celery -A tasks worker --loglevel=info

成功运行后,打印如下信息:

 -------------- celery@testdeMacBook-Pro.local v5.2.7 (dawn-chorus)
--- ***** ----- 
-- ******* ---- macOS-10.16-x86_64-i386-64bit 2023-01-03 21:39:48
- *** --- * --- 
- ** ---------- [config]
- ** ---------- .> app:         tasks:0x7fcbf8ce4e20
- ** ---------- .> transport:   amqp://guest:**@localhost:5672//
- ** ---------- .> results:     redis://localhost/
- *** --- * --- .> concurrency: 8 (prefork)
-- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker)
--- ***** ----- -------------- [queues].> celery           exchange=celery(direct) key=celery[tasks]. tasks.add[2023-01-03 21:39:48,906: INFO/MainProcess] Connected to amqp://guest:**@127.0.0.1:5672//
[2023-01-03 21:39:48,916: INFO/MainProcess] mingle: searching for neighbors
[2023-01-03 21:39:49,957: INFO/MainProcess] mingle: all alone
[2023-01-03 21:39:50,007: INFO/MainProcess] celery@testdeMacBook-Pro.local ready.

其中可以看到配置信息和任务信息。

最后调用任务:

需要调用我们创建的实例任务,可以通过 delay() 进行调用。

delay()apply_async() 的快捷方法,可以更好的控制任务的执行

>>> from tasks import add
>>> add.delay(4, 4)
<AsyncResult: e4722dc5-1ccd-45b5-ba89-75ff3edf4255>

调用任务会返回一个 AsyncResult 的实例,用于检测任务的状态,等待任务完成获取返回值(如果任务执行失败,会抛出异常)。默认这个功能是不开启的,到那时我们配置了backend,所以可以查看任务的状态,如下:

>>> result.ready() # ready() 可以检测是否已经处理完毕:
True
>>> result.get(timeout=1)  # get获取任务执行结果
8

如果任务出现异常,可以通过以下命令进行回溯:

>>> result.traceback

同时该任务已经有被celery Worker开始处理,可以在启动celery的控制台输出的日志进行查看执行情况,如下可以看到任务被成功执行:

[2023-01-03 21:48:08,374: INFO/MainProcess] Task tasks.add[1b5f11de-c113-4f07-b2de-52c7f7594959] received
[2023-01-03 21:48:08,390: INFO/ForkPoolWorker-8] Task tasks.add[1b5f11de-c113-4f07-b2de-52c7f7594959] succeeded in 0.013839624999999245s: 8

Flask使用Celery

异步任务

下面来看下在实际flask项目中,如何使用Celery。

1.创建flask项目

使用pycharm创建一个flask项目,名称为flask_celery。

同时创建一个文件夹,名称为celery_tasks,专门用于管理celery相关的文件。

2.celery配置

针对较大型的项目,建议使用专用配置模块,进行针对 Celery 配置。不建议使用硬编码,建议将所有的配置项集中化配置。

需要在celery_tasks文件夹下创建一个名为 config.py 的文件,添加以下配置内容:

broker_url = 'amqp://guest:guest@localhost:5672'
result_backend = 'redis://:123456@localhost:6379/8'

更多配置后面会讲解。

创建完后可以通过 app.config_from_object() 进行加载配置模块。

3.创建Celery app实例

在celery_tasks文件夹下创建main.py文件,代码如下:

from celery import Celery
from celery_tasks import configcelery_app = Celery(__name__)# 加载配置文件
celery_app.config_from_object(config)# 自动搜寻异步任务
celery_app.autodiscover_tasks(['celery_tasks.sms'])

注意:autodiscover_tasks用来自动搜寻我们指定文件夹下创建的任务,但是任务所在的文件必须叫tasks.py。

当然也可以在创建celery对象时使用参数include直接指定搜寻任务文件夹,如下:

celery_app = Celery('tasks',broker='redis://127.0.0.1:6379/1',backend='redis://127.0.0.1:6379/2',include=['celery_tasks.sms',])

4.创建任务

创建一个发送短信验证码的任务:先在celery_tasks文件夹下创建sms文件夹,然后创建一个tasks.py(为了能被自动搜寻到)文件,编辑代码如下:

import timefrom celery_tasks.celery_service import celery_app@celery_app.task
def send_sms(phone, data):"""模拟发送短信"""time.sleep(3)print("发送短信成功")return True

5.创建业务接口

一般真实业务中,我们的任务都是由flask项目中的业务去调用。这里创建一个名称为sms的接口,来调用发送短信验证码的任务,代码如下:

from flask import Flaskfrom celery_tasks.sms_task import send_smsapp = Flask(__name__)@app.route('/')
def hello_world():return 'Hello World!'@app.route('/sms')
def sms():# 做一些业务操作# delay函数会把任务交给celery去执行,然后立即返回,所以是异步send_sms.delay()return 'send sms success!'if __name__ == '__main__':app.run()

6.启动flask项目

启动flask项目即可

7.启动celery

注意,启动时,不要切换到celery_app所在文件夹下,而是在项目根目录即可(后面会说明为什么)。

执行命令:

celery -A celery_tasks.main worker -l info-------------- celery@testdembp v5.2.7 (dawn-chorus)
--- ***** ----- 
-- ******* ---- macOS-10.16-x86_64-i386-64bit 2023-01-05 00:14:03
- *** --- * --- 
- ** ---------- [config]
- ** ---------- .> app:         celery_tasks.celery_service:0x7f95f8a69f70
- ** ---------- .> transport:   amqp://guest:**@localhost:5672//
- ** ---------- .> results:     redis://:**@localhost:6379/8
- *** --- * --- .> concurrency: 8 (prefork)
-- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker)
--- ***** ----- -------------- [queues].> celery           exchange=celery(direct) key=celery[tasks]. celery_tasks.sms.tasks.send_sms[2023-01-05 00:14:04,226: INFO/MainProcess] Connected to amqp://guest:**@127.0.0.1:5672//
[2023-01-05 00:14:04,235: INFO/MainProcess] mingle: searching for neighbors
[2023-01-05 00:14:05,273: INFO/MainProcess] mingle: all alone
[2023-01-05 00:14:05,298: INFO/MainProcess] celery@testdembp ready.

可以看到tasks里已经有我们的celery_tasks.sms.tasks.send_sms任务了,注意这里的任务名就是这个包含路径的全名,而不只是send_sms这个函数名。

注意:正式环境启动时,可以使用如下命令启动celer worker

nohup celery -A proj worker - P gevent -c 1000 > celery.log 2>&1 &# 1.nohup 和末尾的&:后台执行,忽略所有挂断
# 2.- P gevent -c 1000 :开1000个协程执行,可根据业务调整

8.测试

访问我们的sms接口:http://127.0.0.1:5000/sms。然后可以看到接口是立即返回的,没有延迟3秒。然后再celery任务控制台看到如下信息:

[2023-01-05 00:16:54,391: INFO/MainProcess] Task celery_tasks.sms.tasks.send_sms[23b58998-ab44-4bc6-8aff-bc6cc12aa664] received
[2023-01-05 00:16:57,394: WARNING/ForkPoolWorker-8] 发送短信成功
[2023-01-05 00:16:57,402: INFO/ForkPoolWorker-8] Task celery_tasks.sms.tasks.send_sms[23b58998-ab44-4bc6-8aff-bc6cc12aa664] succeeded in 3.0086944159999973s: True

任务被成功执行,且看到最后耗时3.0086944159999973s,返回True。

看一下整个项目的结构如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nBe8gVGn-1679397896075)(./imgs/2.png)]

最后特别说明:

整个项目其实由三部分组成:客户端(flask应用)、Celery服务端、中间件(broker)。这三部分在实际成产中都可以分开单独去部署,Celery本身也是一个单独的服务,只不过为了方便,写在了flask项目中,实际也可以把celery_tasks文件夹单独拿出来,单独去部署启动服务。但是文件分开后注意一点,flask客户端去调用celery里的异步任务的时候,是通过任务名(就是上面我们看到的文件路径加函数名组成的)放到Broker中,celery服务从Broker获取任务名去执行。flask可以没有具体的异步任务逻辑代码,只要一个任务名就行,但是为了flask能顺利调用异步任务,flask项目使用celery的相关文件的目录结构要与celery本身服务的目录结构相同,这样保证了flask客户端和celery服务两边的任务名相同。

当celery异步任务中需要flask上下文时,就不宜把flask项目和celery项目分开了。

还有一点是,除非有特殊要求,否则任务最好不要返回值,能省去后端结果存储、提高性能。

定时任务

创建定时任务时,使用celery的celery beat,它是一个调度程序,定期启动任务,然后由集群中的可用节点执行任务。

默认情况下会从配置中的 beat_schedule 项中获取条目(entries,也就是要执行的具体的定时任务),但是也可以使用自定义存储,例如将entries存储在SQL数据库中。

时区设置:默认情况下,定期任务计划使用UTC时区,但是可以使用时区设置更改使用的时区。

例如配置 Asia/Shanghai:

broker_url = 'amqp://guest:guest@localhost:5672'
result_backend = 'redis://:123456@localhost:6379/8'
# 时区设置
timezone = 'Asia/Shanghai'

也可以你直接使用app.conf.timezone ='Asia/Shanghai'来直接配置。

首先创建我们的任务,在celery_tasks文件夹创建一个新文件夹scheduled,然后创建tasks.py文件,编辑 celery_tasks/scheduled/tasks.py,代码如下:

from celery_tasks.main import celery_app@celery_app.task
def scheduled_task(name):"""模拟定时任务"""print(f"{name}执行定时任务")return True

然后在周期调度列表中添加条目(entry),建议使用如下方式添加,编辑celery_tasks/main.py:

from datetime import timedeltafrom celery import Celery# from app import app
from celery_tasks import configcelery_app = Celery(__name__)# 加载配置文件
celery_app.config_from_object(config)# 自动搜寻异步任务
celery_app.autodiscover_tasks(['celery_tasks.sms', 'celery_tasks.scheduled'])# 设置定时任务
celery_app.conf.beat_schedule = {# 名字,最好做到见名知意'add-every-10-seconds': {# 执行scheduled.tasks下的scheduled_task函数'task': 'celery_tasks.scheduled.tasks.scheduled_task',# 每隔3秒执行一次'schedule': 3.0,# 'schedule': timedelta(seconds=3),# 传递参数'args': ('张三',)},
}

设置时间间隔时,也可以使用timedelta(不仅可以设置秒,也可以设置天,年等间隔),这样更加灵活。

下面启动我们的celery worker服务

 celery -A celery_tasks.main worker -l info# 显示如下启动成功-------------- celery@testdembp v5.2.7 (dawn-chorus)
--- ***** ----- 
-- ******* ---- macOS-10.16-x86_64-i386-64bit 2023-01-07 12:14:20
- *** --- * --- 
- ** ---------- [config]
- ** ---------- .> app:         celery_tasks.main:0x7fbb2066c3d0
- ** ---------- .> transport:   amqp://guest:**@localhost:5672//
- ** ---------- .> results:     redis://:**@localhost:6379/8
- *** --- * --- .> concurrency: 8 (prefork)
-- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker)
--- ***** ----- -------------- [queues].> celery           exchange=celery(direct) key=celery[tasks]. celery_tasks.scheduled.tasks.scheduled_task. celery_tasks.sms.tasks.send_sms[2023-01-07 12:14:21,070: INFO/MainProcess] Connected to amqp://guest:**@127.0.0.1:5672//
[2023-01-07 12:14:21,083: INFO/MainProcess] mingle: searching for neighbors
[2023-01-07 12:14:22,119: INFO/MainProcess] mingle: all alone
[2023-01-07 12:14:22,145: INFO/MainProcess] celery@testdembp ready.

这时候是不会执行任何任务的。与一般的异步任务不同的是,定时任务是依赖celery beat服务的,需要单独再启动celery beat服务,如下:

celery -A celery_tasks.main beat
# 显示如下则启动成功
celery beat v5.2.7 (dawn-chorus) is starting.
__    -    ... __   -        _
LocalTime -> 2023-01-07 12:07:10
Configuration ->. broker -> amqp://guest:**@localhost:5672//. loader -> celery.loaders.app.AppLoader. scheduler -> celery.beat.PersistentScheduler. db -> celerybeat-schedule. logfile -> [stderr]@%WARNING. maxinterval -> 5.00 minutes (300s)

beat进程会读取配置文件的内容,周期性的将配置中到期需要执行的任务发送给任务队列,然后worker进程从队列读取执行。

启动后,在worker服务的终端马山可以看到任务已经执行了,如下:

[2023-01-07 12:14:28,999: INFO/MainProcess] Task celery_tasks.scheduled.tasks.scheduled_task[64510402-3a67-43f4-b1f3-60477f873e7b] received
[2023-01-07 12:14:29,001: WARNING/ForkPoolWorker-8] 张三执行定时任务
[2023-01-07 12:14:29,008: INFO/ForkPoolWorker-8] Task celery_tasks.scheduled.tasks.scheduled_task[64510402-3a67-43f4-b1f3-60477f873e7b] succeeded in 0.007088375000000369s: True
[2023-01-07 12:14:31,973: INFO/MainProcess] Task celery_tasks.scheduled.tasks.scheduled_task[d81cf939-c24d-4cdd-b111-03bfa4a315b8] received
[2023-01-07 12:14:31,974: WARNING/ForkPoolWorker-8] 张三执行定时任务
[2023-01-07 12:14:31,976: INFO/ForkPoolWorker-8] Task celery_tasks.scheduled.tasks.scheduled_task[d81cf939-c24d-4cdd-b111-03bfa4a315b8] succeeded in 0.0017581670000001992s: True
[2023-01-07 12:14:34,970: INFO/MainProcess] Task celery_tasks.scheduled.tasks.scheduled_task[385e75e0-e9c6-4510-993d-12a82799e5dc] received
[2023-01-07 12:14:34,971: WARNING/ForkPoolWorker-8] 张三执行定时任务
[2023-01-07 12:14:34,972: INFO/ForkPoolWorker-8] Task celery_tasks.scheduled.tasks.scheduled_task[385e75e0-e9c6-4510-993d-12a82799e5dc] succeeded in 0.0008522909999992834s: True

可以看到,确实任务每3秒执行一次。

设置任务时,还可以更加灵活的使用Crontab 调度器,例如一天中的特定时间或一周中的某天执行任务。

如下,设置任务每周一的上午7:30分执行:

from celery.schedules import crontabapp.conf.beat_schedule = {# Executes every Monday morning at 7:30 a.m.'add-every-monday-morning': {'task': 'celery_tasks.scheduled.tasks.scheduled_task','schedule': crontab(hour=7, minute=30, day_of_week=1),'args': ('张三',),},
}

Celery使用Flask上下文

参考:https://flask.palletsprojects.com/en/2.2.x/patterns/celery/

关于Flask的上下文原理参考文章:https://blog.csdn.net/qq_43745578/article/details/129574039?spm=1001.2014.3001.5501

根据Flask上下文原理介绍,我们知道:

在一个非请求的线程中,想要使用应用上下文,必须要 手动把上下文push到栈中,文章中介绍了两种方法。

在Celery执行任务时,也一样,由于Celery是异步的,和请求并不是一个线程,所以Celery要想使用上下文,也需要同样把上下文手动push到栈中。这里我们使用with app.app_context()

同时我们需要使用工厂函数模式来创建appcelery_app

修改我们的项目结构如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FbaNV79Z-1679397896075)(./imgs/3..png)]

主要变化如下:

1.增加一个app文件夹,用于创建Flaskapp和Celery app

2.celery_tasks文件夹下的__init__.py文件增加创建Celery app的工厂方法。

3.增加run.py取代之前的app.py,用于启动flask应用。

具体代码如下:

(1)celery_tasks/__init__.py

这个文件增加用来创建Celery app的工厂方法:

from celery import Celery, Task
from flask import Flaskdef celery_init_app(app: Flask) -> Celery:# 重写celery的task类,主要把任务放在上下文中执行class FlaskTask(Task):def __call__(self, *args: object, **kwargs: object) -> object:with app.app_context():return self.run(*args, **kwargs)celery_app = Celery(app.name, task_cls=FlaskTask)# 把celery赋值到app的属性中,便于后面取app.extensions["celery"] = celery_appreturn celery_app

(2)app_factory/__init__.py

这个文件增加flask app的工厂方法,用于创建flask app 和 celery app:

from flask import Flask
from celery_tasks import  celery_init_appdef create_app() -> Flask:app = Flask(__name__)celery_init_app(app)return appflask_app = create_app()
celery_app = flask_app.extensions["celery"]

(3)celery_tasks/main.py

修改次文件,不再创建celery app,而是使用app_factory/__init__.py文件创建的 celery app。

from celery import Celeryfrom celery_tasks import config
from app_factory import celery_app# celery_app = Celery(__name__)# 加载配置文件
celery_app.config_from_object(config)# 自动搜寻异步任务
celery_app.autodiscover_tasks(['celery_tasks.sms', 'celery_tasks.scheduled', 'celery_tasks.context_tasks'])# 设置定时任务
celery_app.conf.beat_schedule = {# 名字,最好做到见名知意'add-every-10-seconds': {# 执行scheduled.tasks下的scheduled_task函数'task': 'celery_tasks.scheduled.tasks.scheduled_task',# 每隔3秒执行一次'schedule': 3.0,# 'schedule': timedelta(seconds=3),# 传递参数'args': ('张三',)},
}

配置文件还和以前一样。

(4)创建celery任务

新建文件夹celery_tasks/context_tasks,在里面创建文件tasks.py

from app_factory import celery_app
from flask import current_app@celery_app.task
def context_task():"""celery中使用flask上下文"""print("context_task")with current_app.app_context():print(f"current_app mysql:{current_app.mysql}")return str(current_app.config)

这里主要创建一个task,并且使用了flask中的应用上下文,打印出来应用的name。

(5)run.py

创建视图函数,启动app:

from app_factory import flask_app as app
from celery_tasks.context_tasks.tasks import context_task
from celery_tasks.sms.tasks import send_sms@app.route('/sms', methods=['GET'])
def sms():send_sms.delay()return 'send sms success!'@app.route('/app_context', methods=["GET"])
def test_flask_app_context():result = context_task.delay()print(result)return "success!"if __name__ == '__main__':app.run()

这里的app使用我们工厂函数创建的app。

(6)启动celery

 celery -A celery_tasks.main worker -l info

(7)测试

访问路由http://127.0.0.1:5000/app_context,看到celery任务后台打印如下:

[2023-03-21 19:04:37,353: INFO/MainProcess] Task celery_tasks.context_tasks.tasks.context_task[70891026-47f7-48b1-bb9c-41aa08be51c3] received
[2023-03-21 19:04:37,356: WARNING/ForkPoolWorker-8] context_task
[2023-03-21 19:04:37,359: WARNING/ForkPoolWorker-8] current_app mysql:mysql1
[2023-03-21 19:04:37,367: INFO/ForkPoolWorker-8] Task celery_tasks.context_tasks.tasks.context_task[70891026-47f7-48b1-bb9c-41aa08be51c3] succeeded in 0.011942791999999702s: '<Config {\'ENV\': \'production\', \'DEBUG\': False, \'TESTING\': False, \'PROPAGATE_EXCEPTIONS\': None, \'PRESERVE_CONTEXT_ON_EXCEPTION\': None, \'SECRET_KEY\': None, \'PERMANENT_SESSION_LIFETIME\': datetime.timedelta(days=31), \'USE_X_SENDFILE\': False, \'SERVER_NAME\': None, \'APPLICATION_ROOT\': \'/\', \'SESSION_COOKIE_NAME\': \'session\', \'SESSION_COOKIE_DOMAIN\': None, \'SESSION_COOKIE_PATH\': None, \'SESSION_COOKIE_HTTPONLY\': True, \'SESSION_COOKIE_SECURE\': False, \'SESSION_COOKIE_SAMESITE\': None, \'SESSION_REFRESH_EACH_REQUEST\': True, \'MAX_CONTENT_LENGTH\': None, \'SEND_FILE_MAX_AGE_DEFAULT\': None, \'TRAP_BAD_REQUEST_ERRORS\': None, \'TRAP_HTTP_EXCEPTIONS\': False, \'EXPLAIN_TEMPLATE_LOADING\': False, \'PREFERRED_URL_SCHEME\': \'http\', \'JSON_AS_ASCII\': True, \'JSON_SORT_KEYS\': True, \'JSONIFY_PRETTYPRINT_REGULAR\': False, \'JSONIFY_MIMETYPE\': \'application/json\', \'TEMPLATES_AUTO_RELOAD\': None, \'MAX_COOKIE_SIZE\': 4093}>'

进阶使用参考

停止Worker

使用 Control + c 就可以停止职程(Worker)

后台运行

正式环境后台启动celery命令:

nohup celery -A proj worker - P gevent -c 1000 > celery.log 2>&1 &# 1.nohup 和末尾的&:后台执行,忽略所有挂断
# 2.- P gevent -c 1000 :开1000个协程执行,可根据业务调整

参考:

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

https://blog.csdn.net/u010339879/article/details/97691231

相关文章:

Celery使用:优秀的python异步任务框架

目录Celery 简介介绍安装基本使用Flask使用Celery异步任务定时任务Celery使用Flask上下文进阶使用参考停止Worker后台运行Celery 简介 介绍 Celery 是一个简单、灵活且可靠的&#xff0c;处理大量消息的分布式系统&#xff0c;并且提供维护这样一个系统的必需工具。 它是一个…...

第十四届蓝桥杯三月真题刷题训练——第 19 天

第 1 题&#xff1a;灌溉_BFS板子题 题目描述 小蓝负责花园的灌溉工作。 花园可以看成一个 n 行 m 列的方格图形。中间有一部分位置上安装有出水管。 小蓝可以控制一个按钮同时打开所有的出水管&#xff0c;打开时&#xff0c;有出水管的位置可以被认为已经灌溉好。 每经过一分…...

类和对象 - 下

本文已收录至《C语言》专栏&#xff01; 作者&#xff1a;ARMCSKGT 目录 前言 正文 初始化列表 成员变量的定义与初始化 初始化列表的使用 变量定义顺序 explicit关键字 隐式类型转换 自定义类型隐式转换 explicit 限制转换 关于static static声明类成员 友元 友…...

【云原生】Linux基础IO(文件理解与操作)

✨个人主页&#xff1a; Yohifo &#x1f389;所属专栏&#xff1a; Linux学习之旅 &#x1f38a;每篇一句&#xff1a; 图片来源 &#x1f383;操作环境&#xff1a; CentOS 7.6 阿里云远程服务器 Great minds discuss ideas. Average minds discuss events. Small minds disc…...

CentOS 7 安装 mysql 8.0 客户端

只想安装 mysql-client 8.0 &#xff0c; 结果发现直接 yum install mysql mysql-client 安装的版本是 mysql Ver 15.1 Distrib 5.5.68-MariaDB &#xff0c;这个版本太低&#xff0c;连接其他服务器上的 mysql 8.0 时总是失败&#xff0c;因为 mysql 8.0 加密方式改变了&#…...

Ubuntu下载、配置、安装和编译opencv

1 安装相关依赖安装opencv前&#xff0c;需要先准备好编译器、相关依赖sudo apt-get install gcc g cmake vim sudo apt-get install build-essential libgtk2.0-dev libavcodec-dev libavformat-dev libjpeg-dev libswscale-dev libtiff5-dev sudo apt-get install libgtk2.0-…...

第七讲 贪心

文章目录股票买卖 II货仓选址&#xff08;贪心:排序中位数&#xff09;糖果传递&#xff08;❗贪心&#xff1a;中位数&#xff09;雷达设备&#xff08;贪心排序&#xff09;付账问题&#xff08;平均值排序❓&#xff09;乘积最大&#xff08;排序/双指针&#xff09;后缀表达…...

数字藏品的未来及发展趋势

随着互联网的普及以及数字文化的日益发展&#xff0c;数字藏品作为一种全新的收藏方式正在逐步兴起。数字藏品可以是数字版权、数字艺术品、数字音乐以及数字视频等形式&#xff0c;这些藏品通过数字化技术保存下来&#xff0c;并在互联网上进行传播和交易。数字藏品的发展趋势…...

值得记忆的STL常用算法,分分钟摆脱容器调用的困境,以vector为例,其余容器写法类似

STL常用算法 概述&#xff1a; 算法主要是由头文件<algorithm> <functional> <numeric>组成 <algorithm>是所有STL头文件中最大的一个&#xff0c;范围涉及到比较、交换、查找、遍历操作、复制、修改等等 <nuneric>体积很小&#xff0c;只包括…...

java如何手动导jar包

今天用IDEA&#xff0c;需要导入一个Jar包&#xff0c;因为以前都是用eclipse的&#xff0c;所以对这个idea还不怎么上手&#xff0c;连打个Jar包都是谷歌了一下。 但是发现网上谷歌到的做法一般都是去File –> Project Structure中去设置&#xff0c;有没有如同eclipse一样…...

怎么防止SQL注入?

首先SQL注入是一种常见的安全漏洞&#xff0c;黑客可以通过注入恶意代码来攻击数据库和应用程序。以下是一些防止SQL注入的基本措施&#xff1a; 数据库操作层面 使用参数化查询&#xff1a;参数化查询可以防止SQL注入&#xff0c;因为参数化查询会对用户输入的数据进行过滤和…...

【千题案例】TypeScript获取两点之间的距离 | 中点 | 补点 | 向量 | 角度

我们在编写一些瞄准、绘制、擦除等功能函数时&#xff0c;经常会遇到计算两点之间的一些参数&#xff0c;那本篇文章就来讲一下两点之间的一系列参数计算。 目录 1️⃣ 两点之间的距离 ①实现原理 ②代码实现及结果 2️⃣两点之间的中点 ①实现原理 ②代码实现及结果 3…...

堆叠注入--攻防世界CTF赛题学习

在一次联系CTF赛题中才了解到堆叠注入&#xff0c;在这里简单介绍一下。 堆叠注入的原理什么的一搜一大堆&#xff0c;我就不引用百度了&#xff0c;直接进入正题。 这个是攻防世界的一道CTF赛题。 采用寻常思路来寻找sql注入漏洞。 payload:1 and 11-- 利用payload: and 12…...

STM32 ADC+定时器+DMA+FFT

本次实现的功能为单片机DAC输出一个正弦波&#xff0c;然后ADC定时采样用DMA输出&#xff0c;最后对DAC输出的波形进行FFT。单片机STM32F103ZET6内部时钟一、配置ADCADC端口为PA1&#xff0c;采用DMA输出&#xff0c;定时器3触发定时器时钟64M&#xff0c;分频后为102.4KHzADC采…...

用Node.js实现一个HTTP服务器程序(文件服务器)

http Node.js开发的目的就是为了用JavaScript编写Web服务器程序。因为JavaScript实际上已经统治了浏览器端的脚本,其优势就是有世界上数量最多的前端开发人员。如果已经掌握了JavaScript前端开发,再学习一下如何将JavaScript应用在后端开发,就是名副其实的全栈了。 HTTP协…...

Python实现人脸识别检测, 对美女主播照片进行评分排名

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 素材、视频、代码、插件安装教程我都准备好了&#xff0c;直接在文末名片自取就可点击此处跳转 开发环境: Python 3.8 Pycharm 2021.2 模块使用&#xff1a; requests >>> pip install requests tqdm >…...

【数据结构与算法】什么是双向链表?并用代码手动实现一个双向链表

文章目录一、什么是双向链表二、双向链表的简单实现一、什么是双向链表 我们来看一下这个例子&#xff1a; 在一个教室里&#xff0c;所有的课桌排成一列&#xff0c;如图 相信在你们的读书生涯中&#xff0c;老师肯定有要求你们记住自己的前后桌是谁。所以该例子中&#x…...

23种设计模式

参考链接&#xff1a; 【狂神说Java】通俗易懂的23种设计模式教学&#xff08;停更&#xff09;_哔哩哔哩_bilibili 23种设计模式【狂神说】_狂神说设计模式_miss_you1213的博客-CSDN博客 1. 单例模式 参考链接&#xff1a; 【狂神说Java】单例模式-23种设计模式系列_哔哩哔哩…...

20美刀一个月的ChatGPT架构师,性价比逆天了

文章目录20美刀一个月的ChatGPT架构师&#xff0c;性价比逆天了1.角色设定2.基本描述3.解决方案4.物理网络蓝图5.系统集成接口5.1 系统集成接口设计5.1.1 前端服务器与后端服务器接口&#xff1a;5.1.2 后端服务器与去背景处理服务接口&#xff1a;5.2 系统集成接口展示6.部署环…...

海门区教育科学规划课题2020年度成果鉴定书

海门区教育科学规划课题2020年度成果鉴定书 课题编号&#xff1a;HMGZ2020007 课题名称 中学历史核心素养校本化实施的培育研究 主持人 徐彬 工作单位 南通市海门证大中学 核心组成员 &#xff08;包括主持人&#xff09; 姓名 研究任务完成情况 &#xff08;获得的主要成果、…...

大数据专业应该怎么学习

大数据学习不能停留在理论的层面上&#xff0c;大数据方向切入应是全方位的&#xff0c;基础语言的学习只是很小的一个方面&#xff0c;编程落实到最后到编程思想。学习前一定要对大数据有一个整体的认识。 大数据是数据量多吗&#xff1f;其实并不是&#xff0c;通过Hadoop其…...

学习黑客十余年,如何成为一名高级的安全工程师?

1. 前言 说实话&#xff0c;一直到现在&#xff0c;我都认为绝大多数看我这篇文章的读者最后终究会放弃&#xff0c;原因很简单&#xff0c;自学终究是一种适合于极少数人的学习方法&#xff0c;而且非常非常慢&#xff0c;在这个过程中的变数过大&#xff0c;稍有不慎&#…...

【算法】手把手学会二分查找

目录 简介 基本步骤 第一种二分 第二种二分 例题 搜索插入位置 数的范围 总结 简介 &#x1f965;二分查找&#xff0c;又叫折半查找&#xff0c;通过找到数据二段性每次都能将原来的数据筛选掉一半&#xff0c;通过这个算法我们能够将一个一个查找的 O(n) 的时间复杂…...

SVO、vinsmono、 OKVIS系统比较

几个经典视觉slam系统的比较 SVO 高翔链接&#xff1a;https://www.zhihu.com/question/39904950/answer/138644975处理的各个线程: tracking部分-frame to frame 、frame to map 金字塔的处理。这一步估计是从金字塔的顶层开始&#xff0c;把上一层的结果作为下一层估计的初…...

前端开发规范

一、开发工具 开发工具统一使用 VSCode代码格式化插件使用 Prettier代码格式校验使用 ESLintVSCode 需安装的插件有&#xff1a;ESLint、Prettier、Vetur 二、命名规范 项目命名使用小写字母&#xff0c;以连字符分隔 正确&#xff1a;fe-project 错误&#xff1a;FE PROJECT…...

不用科学上网,免费的GPT-4 IDE工具Cursor保姆级使用教程

大家好&#xff0c;我是可乐。 过去的一周&#xff0c;真是疯狂的一周。 GPT-4 震撼发布&#xff0c;拥有了多模态能力&#xff0c;不仅能和GPT3一样进行文字对话&#xff0c;还能读懂图片&#xff1b; 然后斯坦福大学发布 Alpaca 7 B&#xff0c;性能匹敌 GPT-3.5&#xff…...

【艾特淘】抖音小店物流体验分提升的6个维度,新手做店必看

抖音小店体验分&#xff0c;考核的内容包括商品、物流以及服务。大部分人会把重心放在商品评价和服务上&#xff0c;忽略了物流体验。但其实&#xff0c;抖音小店物流体验占比有20%&#xff0c;比服务分的占比还高一点。如果你的订单物流出了问题&#xff0c;很有可能会导致用户…...

数据结构——二叉树与堆

作者&#xff1a;几冬雪来 时间&#xff1a; 内容&#xff1a;二叉树与堆内容讲解 目录 前言&#xff1a; 1.完全二叉树的存储&#xff1a; 2.堆的实现&#xff1a; 1.创建文件&#xff1a; 2.定义结构体&#xff1a; 3.初始化结构体&#xff1a; 4.扩容空间与扩容…...

Three.js——learn02

Three.js——learn02Three.js——learn02通过轨道控制器查看物体OrbitControls核心代码index2.htmlindex.cssindex2.jsresult添加辅助器1.坐标轴辅助器AxesHelper核心代码完整代码2.箭头辅助器ArrowHelper核心代码完整代码3.相机视锥体辅助器CameraHelper核心代码完整代码Three…...

零基础小白如何入门网络安全?

我经常会看到这一类的问题&#xff1a; 学习XXX知识没效果&#xff1b; 学习XXX技能没方向&#xff1b; 学习XXX没办法入门&#xff1b; 给大家一个忠告&#xff0c;如果你完全没有基础的话&#xff0c;前期最好不要盲目去找资料学习&#xff0c;因为大部分人把资料收集好之…...

电脑制作网站总么做/模板建站和开发网站区别

&#xff08;一&#xff09;架构师技能树 大数据基础巩固&#xff08;录播&#xff09; HDFS分布式文件系统 1.HDFS架构设计 2.HDFS设计思想 3.数据块 4.机架感知 5.容错策略 6.数据本地性策略 7.读写流程分析 8.HDFS高可用原理 MapReduce分布式计算模型 1.基本原理 2.作业执…...

上海高端品牌网站建设/如何弄一个自己的网站

这是我之前项目同学遇到的一个问题&#xff0c;现实代码比较复杂&#xff0c;现在我将尽可能简单的描述这个问题&#xff0c;并且内容重心会放在探索为什么会出现这样的情况以及后续监控。一、问题的起源先看一个非常简单的model类Boy:publicclass Boy {publicString boyName;p…...

锦州网站建设更好/百度推广注册

<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />美国思科公司&#xff08;Cisco System Inc.&#xff09;可谓无人不知&#xff0c;无人不晓。凭借它的IOS&#xff08;Internet Operating System&#xff09;&#xff0c;Cisco公…...

ps制作网站首页面教程/如何优化网站推广

之前谈到免货运&#xff0c;真的很难&#xff0c;你想如果是你在网上购买食品&#xff0c;你一般会购买多少&#xff1f;有的人会说&#xff0c;我会很多&#xff0c;但是你在看看食品的价格是多少&#xff0c;也许你购买了一大袋食品价格也许不会超过100块&#xff0c;但是从重…...

网站推广专家/百度 seo排名查询

2003年4月7日&#xff0c;马云&#xff0c;在杭州&#xff0c;成立了一个神秘的组织。他叫来十位员工&#xff0c;要他们签了一份协议&#xff0c;这份协议要求他们立刻离开阿里巴巴&#xff0c;去做一个神秘的项目。这个项目要求绝对保密&#xff0c;老马戏称“连说梦话被老婆…...

东昌府区建设局网站/公司软文推广

各个参数可参照最后的友链;下面是个异常&#xff1a;2014-09-16 12:45:00.012 [PoolCleaner[326380248:1409911461938]] WARN o.a.tomcat.jdbc.pool.ConnectionPool - Connection has been abandoned PooledConnection[com. mysql.jdbc.JDBC4Connection433b6bee]:java.lang.Ex…...