【Django】文件上传以及celery的使用

上传文件、异步、初始化脚本

 面试题:
项目中的静态文件处理(JS/CSS/image)	自己在机房内优化的方法:
   1. Nginx/lighttpd(lighty-douban):Nginx 处理静态资源速度非常快,并且自身还带有缓存。
   2. 80: Nginx -> {server config} -> django:8080  -> Static : folders	 -> 云存储
 
你了解CDN吗?能讲讲原理么?

扩展:如何更换CDN上的图片?改名大法

   1. 请求加参数:
      
      1. abc.jpg
      2. abc.jpg?20191011111042asdflj2
      3. abc.jpg?20191011111043
      
   2. 改名
      1. abc_201910111042.jpg
      2. abc_md5.jpg

七牛云接入

  1. 注册七牛云账号
  2. 创建存储空间:Bucket -> 有独立的域名,可以访问
  3. 获取相关配置
    • AccessKey:从个人中心-密钥管理里获得
    • SecretKey:从个人中心-密钥管理里获得
    • Bucket_name:我们自己新建的存储空间的名字
    • Bucket_URL:建好的新存储空间的访问url
  4. 安装 qiniu SDK:pip install qiniu
  5. 根据接口文档进行接口封装
  6. 按照需要将上传、下载接口封装成异步任务
  7. 程序处理流程
    1. 服务端上传方式
      1. 用户图片先上传到我们的服务器上
      2. 然后,我们的程序再调用七牛云的api,将图片上传到七牛云
      3. 上传成功后,拼接 avatar 的图片 url 地址:
        1. 七牛云的Bucket_URL/filename,将 avatar 的图片 url 存入数据库
    2. 客户端直传
      1. 客户端图片直接上传到云服务
      2. 客户端将图片地址告诉服务端,服务端更新数据库
      3. 其实存在一个安全隐患
        1. 客户端先从服务端获取token,再上传

代码示例 使用了celery

#上传图片
def user_avatar(request):
    #1.存下来
    # 定义上传后保存的文件名
    file_name =f'avatar-{request.user.id}.jpg'
    # 上传后保存的路径
    file_path = f'{settings.BASE_DIR}/static/{file_name}'
    #接收上传文件内容
    f = request.FILES['avatar']

    with open(file_path,'wb+') as destination:
        for chunk in f.chunks():
            destination.write(chunk)
    print('save local ok.')
    user_id = request.user.id
    #delay很重要!!!
    upload_qiniu.delay(file_name, file_path, user_id)
    return  render_json('已经放入celery-redis队列中')

#这一步用异步celery
@celery_app.task
def upload_qiniu(file_name, file_path, user_id):
    # 2.调用七牛云sdk上传
    # 需要填写你的 Access Key 和 Secret Key 需要修改 
    access_key = 'KXfx2ZiBP311HkZZ8l8JHCmqlqPTJCK2sraihexx'
    secret_key = 'pe5svTTUAJQoUPhppsf0Gg9wbEJiYahnRMAy1rxx'
    # 要上传的空间
    bucket_name = 'liu'
    # 要上传的域名
    bucket_domain = ' liu.s3-cn-south-1.qiniucs.com'
    # 构建鉴权对象
    q = Auth(access_key, secret_key, )
    token = q.upload_token(bucket_name, file_name, 3600)
    ret, info = put_file(token, file_name, file_path)
    print(info)
    #断言
    assert ret['key'] == file_name
    assert ret['hash'] == etag(file_path)
    print('save qiniu ok.')
    avatar_url = f'{bucket_domain}/{file_name}'
    # 3.更新用户的avatar
    user = User.objects.get(id=user_id)
    # user = request.user # request 无法传 所以改为user_id
    user.avatar = avatar_url
    user.save()

    return  True

异步任务

Celery 及异步任务的处理

  1. 通用的异步框架的原理

    1. 核心队列:消息队列

    2. 客户端:异步端

    3. 生产者:消费者

    4. 发布者:订阅者

    5. 发送者:接收者

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YFOxnBJs-1577967577874)(/Users/zebin/Pictures/markdown_assets/image-20200102152154116.png)]

    • 任务模块 Task:包含异步任务和定时任务. 其中, 异步任务通常在业务逻辑中被触发并发往任务队列, 而定时任务由 Celery Beat 进程周期性地将任务发往任务队列.

    • 消息中间件 Broker:代理Broker, 即为任务调度队列, 接收任务生产者发来的消息(即任务)更重要的智能是把海量的的消息缓冲住, 将任务存入队列。Celery 本身不提供队列服务, 官方推荐使用 RabbitMQ 和 Redis 等,或者干脆用云服务的消息队列服务:SQS

    • 任务执行单元 Worker:Worker 是执行任务的处理单元, 它实时监控消息队列, 获取队列中调度的任务, 并执行它.

    • 任务结果存储 Backend:Backend 用于存储任务的执行结果, 以供查询. 同消息中间件一样, 存储也可使用 RabbitMQ, Redis 和 MongoDB 等.

  2. 消息队列:

    1. MQ:Message Queue,(与服务器、存储、缓存、数据库同等重要,是现代互联网后台架构的基础组件)
    2. 作用:
      1. 异步:把没必要同步执行的程序,用消息队列暂存,然后用其他程序去异步执行,做到跨机器分散任务
      2. 解耦:有依赖关系的应用之间,用消息队列解除耦合
        1. A 和 B 两个业务有强耦合
        2. A B
      3. 削峰:把互联网的高峰请求,先缓冲下来,然后再慢慢的逐个处理
        1. 秒杀、团购的场景,用这种方式降低峰值请求
      4. 限流:
        1. 1000,每进来一个人 -1,每离开一个人 +1,
        2. 减到 0 ,就告诉后来者:人满了。
    3. 常见的消息队列:
      1. Redis,最简单
      2. Kafka,最适合做日志处理,单机几十万并发(每秒钟的请求)
      3. RabbitMQ,符合 MQ 标准的消息队列(每秒钟几万)
      4. RocketMQ,符合 MQ 标准的消息队列(每秒钟十几万)
  3. 安装 注意win10不支持celery4.3!!!!!!!!!!
    所以需要额外安装在这里插入图片描述

    pip install  celery[redis] 
    
  4. 创建实例

    import os
    from celery import Celery
    
    from social import settings
    from worker import config
    
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "social.settings")
    
    celery_app = Celery('social')
    celery_app.config_from_object(config)
    celery_app.autodiscover_tasks()
    
    
    
    
    
    
    
    
  5. 常规配置

    broker_url = 'redis://127.0.0.1:6379/0'
    broker_pool_limit = 1000  # Borker 连接池, 默认是10
    
    timezone = 'Asia/Shanghai'
    accept_content = ['pickle', 'json']
    
    task_serializer = 'pickle'
    result_expires = 3600  # 任务过期时间
    
    result_backend = 'redis://127.0.0.1:6379/1'
    result_serializer = 'pickle'
    result_cache_max = 10000  # 任务结果最大缓存数量
    
    worker_redirect_stdouts_level = 'INFO'
    
  6. 启动 Worker

Linux / mac下:
celery worker -A worker --loglevel=info

win:
celery worker -A worker --loglevel=info -P eventlet

发布了354 篇原创文章 · 获赞 163 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/qq_41856814/article/details/103810537
今日推荐