celery介绍

发布时间 2023-11-21 09:42:08作者: Way*yy

celery介绍

# celery是什么?
    分布式异步任务框架:第三方框架,celery翻译过来是芹菜,吉祥物就是芹菜
    项目中使用异步任务的场景,可以使用它
    之前做异步,如何做? 异步发送短信--->开启多线程--->不便于管理

# celery有什么作用?
	-执行异步任务
    -执行延迟任务
    -执行定时任务
# celery原理
1)可以不依赖任何服务器,通过自身命令,启动服务
2)celery服务为为其他项目服务提供异步解决任务需求的
注:会有两个服务同时运行,一个是项目服务,一个是celery服务,项目服务将需要异步处理的任务交给celery服务,celery就会在需要时异步完成项目的需求

人是一个独立运行的服务 | 医院也是一个独立运行的服务
	正常情况下,人可以完成所有健康情况的动作,不需要医院的参与;但当人生病时,就会被医院接收,解决人生病问题
	人生病的处理方案交给医院来解决,所有人不生病时,医院独立运行,人生病时,医院就来解决人生病的需求
    
    
    django如果不用异步,正常运行即可,如果想做异步,就借助于 celery来完成
    
    
    
    
# celery架构
	-broker:消息中间件,任务中间件(消息队列:redis,rabbitmq)
    	django要做异步,提交任务到 任务中间件中(redis),存储起来
        Celery本身不提供消息服务,但是可以方便的和第三方提供的消息中间件集成。包括,RabbitMQ, Redis等等
    -worker:任务执行者,任务执行单元
    	不停的从任务中间件中取任务,执行
        Worker是Celery提供的任务执行的单元,worker并发的运行在分布式的系统节点中
    -banckend:结果存储,任务结果存储
    	把任务执行结果(函数返回值),存放到结果存储中(redis)
        用来存储Worker执行的任务的结果,Celery支持以不同方式存储任务的结果,包括AMQP, redis等
     


###  任务中间件:redis
###  结果存储:redis

celery的快速使用

注意:celery本身是不支持win的,在win上面使用需要借助于第三方

# 安装
	pip install celery
# main.py
	import time
    from celery import Celery

    broker = 'redis://127.0.0.1:6379/1'  # 消息中间件 redis
    backend = 'redis://127.0.0.1:6379/2'  # 结果存,用redis
    #1 实例化得到一个对象
    app = Celery("app", broker=broker, backend=backend)

	#2 编写任务,必须用app.task 装饰,才变成了celery的任务
    @app.task
    def send_sms():
        time.sleep(2)
        print("短信发送成功")
        return "手机号发送成功"
    
    #3 提交任务使用别进程
    from main import send_sms
    res = send_sms.delay()
    print(res)
    
    ### 4 启动worker--->可以在3之前
    # windows:
    pip3 install eventlet
    # 切换到含有app的的文件夹下
    celery  -A main worker -l info -P eventlet
    # mac  linux
    # celery -A main worker -l info


    ### 5 worker就会执行任务,把执行的结果,放到结果存储中
    
    ### 6 查看结果 
    from celery.result import AsyncResult
    from main import app
    id = '92987636-ae9e-4be9-828b-8c2d10fe066a'
    if __name__ == '__main__':
        a = AsyncResult(id=id, app=app)
        if a.successful():
            result = a.get()
            print(result)
        elif a.failed():
            print('任务失败')
        elif a.status == 'PENDING':
            print('任务等待中被执行')
        elif a.status == 'RETRY':
            print('任务异常后正在重试')
        elif a.status == 'STARTED':
            print('任务已经开始被执行')

补充单例

什么是单例模式?单例模式是指:保证一个类仅有一个实例,并提供一个访问它的全局访问点
# 线程1 执行:
cursor.excute('select * from user')

# 线程2执行 
cursor.excute('select * from books')

# 线程1 执行
cursor.fetchAll() # 拿出查询到的数据

# django ,每个线程,一个连接对象--->连接池

1.使用模块

其实,Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。如果我们真的想要一个单例类,可以考虑这样做:

mysingleton.py

class Singleton(object):
    def foo(self):
        pass
singleton = Singleton()

将上面的代码保存在文件 mysingleton.py 中,要使用时,直接在其他文件中导入此文件中的对象,这个对象即是单例模式的对象

from a import singleton

2.使用装饰器

def Singleton(cls):
    instance = None

    def _singleton(*args, **kargs):
        nonlocal instance
        if not instance:
            instance = cls(*args, **kargs)
        return instance

    return _singleton


@Singleton
class A(object):
    def __init__(self, x=0):
        self.x = x


a1 = A(2)
a2 = A(3)
print(a1.x)
print(a2.x)

print(a1 is a2)

3.使用类方法

class Singleton(object):
    _instance=None
    def __init__(self):
        pass
    @classmethod
    def instance(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance=cls(*args, **kwargs)
        return cls._instance

a1=Singleton.instance()
a2=Singleton().instance()

print(a1 is a2)

4.基于new方法实现

class Singleton(object):
    _instance=None
    def __init__(self):
        pass


    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = object.__new__(cls)
        return cls._instance

obj1 = Singleton()
obj2 = Singleton()
print(obj1 is obj2)

5.基于metaclass方式实现

class SingletonType(type):
    _instance=None
    def __call__(cls, *args, **kwargs):
        if not cls._instance:
            # cls._instance = super().__call__(*args, **kwargs)
            cls._instance = object.__new__(cls)
            cls._instance.__init__(*args, **kwargs)
        return cls._instance

class Foo(metaclass=SingletonType):
    def __init__(self,name):
        self.name = name


obj1 = Foo('name')
obj2 = Foo('name')
print(obj1.name)
print(obj1 is obj2)