Django开发时如何避免频繁发送短信验证码(python图文代码)

本文主要是介绍Django开发时如何避免频繁发送短信验证码(python图文代码),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《Django开发时如何避免频繁发送短信验证码(python图文代码)》Django开发时,为防止频繁发送验证码,后端需用Redis限制请求频率,结合管道技术提升效率,通过生产者消费者模式解耦业务逻辑...

避免频繁发送 验证码

存在的问题:

  • 虽然我们在前端界面做了60秒倒计时功能。
  • 但是恶意用户可以绕过前端界面向后端频繁请求 验证码。

解决办法:

  • 在后端也要限制用户请求 验证码的频率。60秒内只允许一次请求 验证码。
  • 在Redis数据库中缓存一个数值,有效期设置为60秒。

1. 避免频繁发送 验证码逻辑分析

Django开发时如何避免频繁发送短信验证码(python图文代码)

2. 避免频繁发送 验证码逻辑实现

1.提取、校验send_flag

send_flag = redis_conn.get('send_flag_%s' % mobile)
if send_flag:
    return http.jsonResponse({'code': RETCODE.THROTTLINGERR, 'errmsg': '发送 过于频繁'})

2.重新写入send_flag

  
# 保存 验证码
redis_conn.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
# 重新写入send_flag
redis_conn.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1)

3.界面渲染频繁发送 提示信息

if (response.data.code == '4001') {
    this.error_image_code_message = response.data.errmsg;
    this.error_image_code = true;
} else { // 4002
    this.error_sms_code_message = response.data.errmsg;
    this.error_sms_code = true;
}

pipeline操作Redis数据库

Redis的 C - S 架构:

  • 基于客户端-服务端模型以及请求/响应协议的TCP服务。
  • 客户端向服务端发送一个查询请求,并监听Socket返回。
  • 通常是以阻塞模式,等待服务端响应。
  • 服务端处理命令,并将结果返回给客户端。

存在的问题:

  • 如果Redis服务端需要同时处理多个请求,加上网络延迟,那么服务端利用率不高,效率降低。

解决的办法:

  • 管道pipeline

Django开发时如何避免频繁发送短信验证码(python图文代码)

1. pipeline的介绍

管道pipeline

  • 可以一次性发送多条命令并在执行完后一次性将结果返回。
  • pipeline通过减少客户端与Redis的通信次数来实现降低往返延时时间。

实现的原理

  • 实现的原理是队列。
  • Client可以将三个命令放到一个tcp报文一起发送。
  • Server则可以将三条命令的处理结果放到一个tcp报文返回。
  • 队列是先进先出,这样就保证数据的顺序性。

Django开发时如何避免频繁发送短信验证码(python图文代码)

2. pipeline操作Redis数据库

1.实现步骤

1. 创建Redis管道
2. 将Redis请求添加到队列
3. 执行请求

2.代码实现

  
  
# 创建Redis管道
  
  
pl = redis_conn.pipeline()
  
  
# 将Redis请求添加到队列
  
  
pl.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, smpythons_code)
pl.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1)
  
  
# 执行请求
  
  
pl.execute()

生产者消费者设计模式

思考:

  • 下面两行代码存在什么问题?

Django开发时如何避免频繁发送短信验证码(python图文代码)

问题:

  • 我们的代码是自上而下同步执行的。
  • 发送 是耗时的操作。如果 被阻塞住,用户响应将会延迟。
  • 响应延迟会造成用户界面的倒计时延迟。

Django开发时如何避免频繁发送短信验证码(python图文代码)

解决:

  • 异步发送
  • 发送 和响应分开执行,将**发送从主业务中解耦**出来。

Django开发时如何避免频繁发送短信验证码(python图文代码)

思考:

  • 如何将**发送从主业务中解耦**出来。

生产者消费者设计模式介绍

  • 为了将**发送从主业务中解耦出来,我们引入生产者消费者设计模式**。
  • 它是最常用的解耦方式之一,寻找**中间人(broker)**搭桥,保证两个业务没有直接关联

Django开发时如何避免频繁发送短信验证码(python图文代码)

总结:

  • 生产者生成消息,缓存到消息队列中,消费者读取消息队列中的消息并执行。
  • 由美多商城生成发送 消息,缓存到消息队列中,消费者读取消息队列中的发送 消息并执行。

RabbitMQ介绍和使用

1. RabbitMQ介绍

  • 消息队列是消息在传输的过程中保存消息的容器

  • 现在主流消息队列有:RabbitMQActiveMQKafka等等。

    • RabbitMQActiveMQ比较

      • 系统吞吐量:RabbitMQ好于ActiveMQ
      • 持久化消息:RabbitMQActiveMQ都支持
      • 高并发和可靠性:RabbitMQ好于ActiveMQ
    • RabbitMQKafka

      • 系统吞吐量:RabbitMQ弱于Kafka
      • 可靠性和稳定性:RabbitMQ好于Kafka比较
      • 设计初衷:Kafka是处理日志的,是日志系统,所以并没有具备一个成熟MQ应该具备的特性。
  • 综合考虑,本项目选择RabbitMQ作为消息队列。

2. 安装RabbitMQ(ubuntu 16.04)

1.安装Erlang

  • 由于 RabbitMQ 是采用 Erlang 编写的,所以需要安装 Erlang 语言库。
  
# 1. 在系统中加入 erlang apt 仓库
$ wget 
$ sudo dpkg -i erlang-solutions_1.0_all.deb
# 2. 修改 Erlang 镜像地址,默认的下载速度特别慢
$ vim /etc/apt/sources.list.d/erlang-solutions.list
# 替换默认值
$ deb  xenial contrib
# 3. 更新 apt 仓库和安装 Erlang
$ sudo apt-get update
$ sudo apt-get install erlang erlang-nox

2.安装RabbitMQ

  • 安装成功后,默认就是启动状态。
  
# 1. 先在系统中加入 rabbitmq apt 仓库,再加入 rabbitmq signing key
$ echo 'deb  testing main' | sudo tee /etc/apt/sources.list.d/rabbitmq.list
$ wget -O-  | sudo apt-key add -
# 2. 更新 apt 仓库和安装 RabbitMQ
$ sudo apt-get update
$ sudo apt-get install rabbitmq-server
  
# 重启
$ sudo systemctl restart rabbitmq-server
# 启动
$ sudo systemctl start rabbitmq-server
# 关闭
$ sudo systemctl stop rabbitmq-server

3.python访问RabbitMQ

  • RabbitMQ提供默认的administrator账户。
  • 用户名和密码:guestguest
  • 协议:amqp
  • 地址:localhost
  • 端口:5672
  • 查看队列中的消息:sudo rabbitctl list_queues
  
# Python3虚拟环境下,安装pika
$ pip install pika
  
# 生产者代码:rabbitmq_producer.py
import pika
# 链接到RabbitMQ服务器
credentials = pika.PlainCredentials('guest', 'guest')
connection = pika.blockingConnection(pika.ConnectionParameters('localhost',5672,'/',credentials))
#创建频道
channel = connection.channel()
# 声明消息队列
channel.queue_declare(queue='zxc')
# routing_key是队列名 body是要插入的内容
channel.basic_publish(exchange='', routing_key='zxc', body='Hello RabbitMQ!')
print("开始向 'zxc' 队列中发布消息 'Hello RabbitMQ!'")
# 关闭链接
connection.close()
  
# 消费者代码:rabbitmq_customer.py 
import pika
# 链接到rabbitmq服务器
credentials = pika.PlainCredentials('guest', 'guest')
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost',5672,'/',credentials))
# 创建频道,声明消息队列
channel = connectiandroidon.channel()
channel.queue_declare(queue='zxc')
# 定义接受消息的回调函数
def callback(ch, method, properties, body):
    print(body)
# 告诉RabbitMQ使用callback来接收信息
channel.basic_consume(callback, queue='zxc', no_ack=True)
# 开始接收信息
channel.start_consuming()

Django开发时如何避免频繁发送短信验证码(python图文代码)

3. 新建administrator用户

  
# 新建用户,并设置密码
$ sudo rabbitmqctl add_user admin your_password 
# 设置标签为administrator
$ sudo rabbitmqctl set_user_tags admin administrator
# 设置所有权限
$ sudo rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"
# 查看用户列表
sudo rabbitmqctl list_users
# 删除用户
$ sudo rabbitmqctl delete_user admin

Django开发时如何避免频繁发送短信验证码(python图文代码)

4. RabbitMQ配置远程访问

1.准备配置文件

  • 安装好 RabbitMQ 之后,在 /etc/rabbitmq 目录下面默认没有配置文件,需要单独下载。
$ cd /etc/rabbitmq/
$ wget 
$ sudo cp rabbitmq.config.example rabbitmq.config

Django开发时如何避免频繁发送短信验证码(python图文代码)

2.设置配置文件

$ sudo vim rabbitmq.config
# 设置配置文件结束后,重启RabbitMQ服务端
$ sudo systemctl restart rabbitmq-server

Django开发时如何避免频繁发送短信验证码(python图文代码)

配置完成后,使用rabbitmq_producer.pyrabbitmq_customer.py测试。

Celery介绍和使用

思考:

  • 消费者取到消息之后,要消费掉(执行任务),需要我们去实现。
  • 任务可能出现高并发的情况,需要补充多任务的方式执行。
  • 耗时任务很多种,每种耗时任务编写的生产者和消费者代码有重复。
  • 取到的消息什么时候执行,以什么样的方式执行。

结论:

  • 实际开发中,我们可以借助成熟的工具Celery来完成。
  • 有了Celery,我们在使用生产者消费者模式时,只需要关注任务本身,极大的简化了程序员的开发流程。

1. Celery介绍

  • Celery介绍:

    • 一个简单、灵活且可靠、处理大量消息的分布式系统,可以在一台或者多台机器上运行。
    • 单个 Celery 进程每分钟可处理数以百万计的任务。
    • 通过消息进行通信,使用消息队列(broker)客户端消费者之间进行协调。
  • 安装Celery:

$ pip install -U Celery
  • [Celery官方js文档]

2. 创建Celery实例并加载配置

1.定义Celery包

Django开发时如何避免频繁发送短信验证码(python图文代码)

2.创建Celery实例

Django开发时如何避免频繁发送短信验证码(python图文代码)

celery_tasks.main.py

  
# celery启动文件
from celery import Celery
# 创建celery实例
celery_app = Celery('meiduo')

3.加载Celery配置

Django开发时如何避免频繁发送短信验证码(python图文代码)

celery_tasks.config.py

  
# 指定消息队列的位置
broker_url= 'amqp://guest:guest@192.168.103.158:5672'

celery_tasks.main.py

  
# celery启动文件
from celery import Celery
# 创建celery实例
celery_app = Celery('meiduo')
# 加载celery配置
celery_app.config_from_object('celery_tasks.config')

3. 定义发送 任务

Django开发时如何避免频繁发送短信验证码(python图文代码)

1.注册任务:celery_tasks.main.py

  
# celery启动文件
from celery import Celery
# 创建celery实例
celery_app = Celery('meiduo')
# 加载celery配置
celery_app.config_from_object('celery_tasks.config')
# 自动注册celery任务
celery_app.autodiscover_tasks(['celery_tasks.sms'])

2.定义任务:celery_tasks.sms.tasks.py

  
# bind:保证task对象会作为第一个参数自动传入
# name:异步任务别名
# retry_backoff:异常自动重试的时间间隔 第n次(retry_backoff2^(n-1))s
# max_retries:异常自动重试次数的上限
@celery_app.task(bind=True, name='ccp_send_sms_code', retry_backoff=3)
def ccp_send_sms_code(self, mobile, sms_code):
    """
    发送 异步任务
    :param mobile: 手机号
    :param sms_code:  验证码
    :return: 成功0 或 失败-1
    """
    try:
        send_ret = CCP().send_template_sms(mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES // 60], constants.SEND_SMS_TEMPLATE_ID)
    except Exception as e:
        logger.error(e)
        # 有异常自动重试三次
        raise self.retry(exc=e, max_retries=3)
    if send_ret != 0:
        # 有异常自动重试三次
        raise self.retry(exc=Exception('发送 失败'), max_retries=3)
    return send_ret

4. 启动Celery服务

$ cd ~/projects/meiduo_project/meiduo_mall
$ celery -A celery_tasks.main worker -l info
  • -A指对应的应用程序, 其参数是项目中 Celery实例的位置。
  • worker指这里要启动的worker。
  • -l指日志等级,比如info等级。

Django开发时如何避免频繁发送短信验证码(python图文代码)

5. 调用发送 任务

  
# 发送 验证码
# CCP().send_template_sms(mobile,[sms_code, constants.SMS_CODE_REDIS_EXPIRES // 60], constants.SEND_SMS_TEMPLATE_ID)
# Celery异步发送 验证码
ccp_send_sms_code.delay(mobile, sms_code)

Django开发时如何避免频繁发送短信验证码(python图文代码)

6. 补充celery worker的工作模式

  • 默认是进程池方式,进程数以当前机器的CPU核数为参考,每个CPU开四个进程。
  • 如何自己指定进程数:celery worker -A proj --concurrency=4
  • 如何改变进程池方式为协程方式:celery worker -A proj --concurrency=1000 -P eventlet -c 1000
  
# 安装eventlet模块
$ pip install eventlet
# 启用 Eventlet 池
$ celery -A celery_tasks.main worker -l info -P eventlet -c 1000

Django开发时如何避免频繁发送短信验证码(python图文代码)

总结

到此这篇关于Django开发时如何避免频繁发送短信验证码(python图文代码)的文章就介绍到这了,更多相关Django避免频繁发送短信验证码内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程phpChina编程(www.chinasem.cn)!

这篇关于Django开发时如何避免频繁发送短信验证码(python图文代码)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1155564

相关文章

Python的Darts库实现时间序列预测

《Python的Darts库实现时间序列预测》Darts一个集统计、机器学习与深度学习模型于一体的Python时间序列预测库,本文主要介绍了Python的Darts库实现时间序列预测,感兴趣的可以了解... 目录目录一、什么是 Darts?二、安装与基本配置安装 Darts导入基础模块三、时间序列数据结构与

Python正则表达式匹配和替换的操作指南

《Python正则表达式匹配和替换的操作指南》正则表达式是处理文本的强大工具,Python通过re模块提供了完整的正则表达式功能,本文将通过代码示例详细介绍Python中的正则匹配和替换操作,需要的朋... 目录基础语法导入re模块基本元字符常用匹配方法1. re.match() - 从字符串开头匹配2.

基于 Cursor 开发 Spring Boot 项目详细攻略

《基于Cursor开发SpringBoot项目详细攻略》Cursor是集成GPT4、Claude3.5等LLM的VSCode类AI编程工具,支持SpringBoot项目开发全流程,涵盖环境配... 目录cursor是什么?基于 Cursor 开发 Spring Boot 项目完整指南1. 环境准备2. 创建

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

C#实现千万数据秒级导入的代码

《C#实现千万数据秒级导入的代码》在实际开发中excel导入很常见,现代社会中很容易遇到大数据处理业务,所以本文我就给大家分享一下千万数据秒级导入怎么实现,文中有详细的代码示例供大家参考,需要的朋友可... 目录前言一、数据存储二、处理逻辑优化前代码处理逻辑优化后的代码总结前言在实际开发中excel导入很

通过Docker容器部署Python环境的全流程

《通过Docker容器部署Python环境的全流程》在现代化开发流程中,Docker因其轻量化、环境隔离和跨平台一致性的特性,已成为部署Python应用的标准工具,本文将详细演示如何通过Docker容... 目录引言一、docker与python的协同优势二、核心步骤详解三、进阶配置技巧四、生产环境最佳实践

Python一次性将指定版本所有包上传PyPI镜像解决方案

《Python一次性将指定版本所有包上传PyPI镜像解决方案》本文主要介绍了一个安全、完整、可离线部署的解决方案,用于一次性准备指定Python版本的所有包,然后导出到内网环境,感兴趣的小伙伴可以跟随... 目录为什么需要这个方案完整解决方案1. 项目目录结构2. 创建智能下载脚本3. 创建包清单生成脚本4

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

Python实现Excel批量样式修改器(附完整代码)

《Python实现Excel批量样式修改器(附完整代码)》这篇文章主要为大家详细介绍了如何使用Python实现一个Excel批量样式修改器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录前言功能特性核心功能界面特性系统要求安装说明使用指南基本操作流程高级功能技术实现核心技术栈关键函

python获取指定名字的程序的文件路径的两种方法

《python获取指定名字的程序的文件路径的两种方法》本文主要介绍了python获取指定名字的程序的文件路径的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 最近在做项目,需要用到给定一个程序名字就可以自动获取到这个程序在Windows系统下的绝对路径,以下