我使用的框架是flask2.2.0 ,以下操作是基于flask 进行
我们先认识一下celery Celery中文手册 Celery 是一个 基于python的分布式异步任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery, 举几个实例场景:
异步任务:将耗时的操作任务提交给Celery异步执行,比如发送短信/邮件、消息推送、音频处理等等 做一个定时任务,比如每天定时执行爬虫爬取指定内容 还可以使用celery实现简单的分布式爬虫系统等等 Celery 在执行任务时需要通过一个消息中间件(Broker)来接收和发送任务消息,以及存储任务结果
Celery有以下优点:
简单:Celery 易于使用和维护,并且它 不需要配置文件 ,并且配置和使用还是比较简单的 高可用:当任务执行失败或执行过程中发生连接中断,celery 会自动尝试重新执行任务 快速:单个 Celery 进程每分钟可处理数以百万计的任务,而保持往返延迟在亚毫秒级 灵活: Celery 几乎所有部分都可以扩展或单独使用,各个部分可以自定义。
celery核心
1、Task
任务(Task)就是你要做的事情,例如一个注册流程里面有很多任务,给用户发验证邮件就是一个任务,这种耗时任务可以交给Celery去处理,还有一种任务是定时任务,比如每天定时统计网站的注册人数,这个也可以交给Celery周期性的处理。
2、Broker
Broker 的中文意思是经纪人,指为市场上买卖双方提供中介服务的人。在Celery中它介于生产者和消费者之间经纪人,这个角色相当于数据结构中的队列。例如一个Web系统中,生产者是处理核心业务的Web程序,业务中可能会产生一些耗时的任务,比如短信,生产者会将任务发送给 Broker,就是把这个任务暂时放到队列中,等待消费者来处理。消费者是 Worker,是专门用于执行任务的后台服务。Worker 将实时监控队列中是否有新的任务,如果有就拿出来进行处理。Celery 本身不提供队列服务,一般用 Redis 或者 RabbitMQ 来扮演 Broker 的角色
3、Worker
Worker 就是那个一直在后台执行任务的人,也称为任务的消费者,它会实时地监控队列中有没有任务,如果有就立即取出来执行。
4、Beat
Beat 是一个定时任务调度器,它会根据配置定时将任务发送给 Broker,等待 Worker 来消费。
5、Backend
Backend 用于保存任务的执行结果,每个任务都有返回值,比如发送邮件的服务会告诉我们有没有发送成功,这个结果就是存在Backend中,当然我们并不总是要关心任务的执行结果。
邮箱的设置 第一步 先进入邮箱设置(我这里使用的是qq邮箱)
第二步 选择设置里的账户 找到SMTP选项
1 2 3 什么是POP3和SMTP POP3 用来将邮件下载到本地的一个协议 用于接收邮件 SMTP 是用户来和服务器连接的一个协议 用于发送邮件
这里选择开启 开启后会让用户发送验证码确认用户信息, 之后或返回一个密钥这个密钥复制下来 等会发送邮件的时候要用
需要用到的工具
下载celery
安装redis redis下载连接地址
初始化Celery 在我们的入口文件里设置celery 与flask 交互
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 def make_celery (app ): celery = Celery(app.import_name, broker='redis://localhost:6379/1' , backend='redis://localhost:6379/2' ) celery.config_from_object(config) class ContextTask (celery.Task): def __call__ (self, *args, **kwargs ): with app.app_context(): return self.run(*args, **kwargs) celery.Task = ContextTask return celery celery = make_celery(app)
编写发送邮件任务 编写邮箱任务类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 from manage.py import celeryimport smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart@celery.task() class SendEmail : def __init__ (self ): self._user = '*****' self._pwd = '*****' def send_mail (self,_touser,_title,_content ): print ('发送邮件' ) msg = MIMEMultipart() msg['Subject' ] = _title msg['From' ] = self._user msg['To' ] = _touser part = MIMEText(_content,'html' ,'utf-8' ) msg.attach(part) s = smtplib.SMTP_SSL('smtp.qq.com' ,465 ) s.login(self._user,self._pwd) s.sendmail(self._user,_touser,msg.as_string()) s.close()
使用异步任务 在我们的视图中使用异步任务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 from task import SendEmailr = redis.Redis(decode_responses=True ) import randomimport stringimport reclass SendCodeApi (MethodView ): def get (self ): email = request.args.get('email' ,None ) code = r.exists(‘black_’+email) if code: times = r.ttl(email) return jsonify({ 'code' :204 , 'msg' :'请在%s秒后重试' %times, 'time' :times }) if not email: return jsonify({ 'code' :203 , 'msg' :'请输入邮箱' }) if not re.fendall(r'^[1-9a-z][0-9a-z]{4,15}@qq\.com$' ,emial): return jsonify({ 'code' :204 , 'msg' :'请输入合法的邮箱' }) sendcode = r.get(email+'_count' ) if sendcode and int (sendcode)>3 : return jsonify({ 'code' :204 , 'msg' :'已达到邮箱发送次数的最大上限' }) code = course ='' .join(random.sample(string.digits + string.ascii_lowercase,4 )) try : taskss.SendEmail.delay(email, '社交平台验证码' , code) except Exception as e: return jsonify({ 'code' :205 , 'msg' :'邮件发送失败' }) r.set (email,code,ex=500 ) if not r.get(email+'_count' ): r.set (email+'_count' ,1 ) else : r.incr(email+'_count' ) return jsonify({ 'code' : 200 , 'msg' : '邮箱验证码发送成功' })
如何启动异步 第一步先启动redis
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 redis-server.exe redis.windows.conf C:\renaissace\redis\Redis-x64-3.2 .100 >redis-server.exe redis.windows.conf _._ _.-``__ '' -._ _.-`` `. `_. '' -._ Redis 3.2 .100 (00000000 /0 ) 64 bit .-`` .-```. ```\/ _.,_ '' -._ ( ' , .-` | `, ) Running in standalone mode |`-._`-...-` __...-.``-._|' ` _.-'| Port: 6379 | `-._ `._ / _.-' | PID: 2804 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-' _.-'| | `-._`-._ _.-' _.-' | https://redis.io `-._ `-._`-.__.-' _.-' _.-' |`-._`-._ `-.__.-' _.-' _.-'| | `-._`-._ _.-' _.-' | `-._ `-._`-.__.-' _.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' [2804 ] 13 Sep 11 :59 :02.735 [2804 ] 13 Sep 11 :59 :02.736 * DB loaded from disk: 0.000 seconds [2804 ] 13 Sep 11 :59 :02.739 * The server is now ready to accept connections on po rt 6379 显示以上内容既代表redis启动成功
第二步启动celery
1 2 celery -A taskss.celery worker --loglevel=info
以上就是异步发送验证码的全部过程