欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Django開發(fā)時(shí)如何避免頻繁發(fā)送短信驗(yàn)證碼(python圖文代碼)

 更新時(shí)間:2025年08月02日 09:37:52   作者:程序員一諾python  
Django開發(fā)時(shí),為防止頻繁發(fā)送驗(yàn)證碼,后端需用Redis限制請(qǐng)求頻率,結(jié)合管道技術(shù)提升效率,通過生產(chǎn)者消費(fèi)者模式解耦業(yè)務(wù)邏輯,引入Celery實(shí)現(xiàn)異步任務(wù)處理,優(yōu)化系統(tǒng)性能與可擴(kuò)展性

避免頻繁發(fā)送 驗(yàn)證碼

存在的問題:

  • 雖然我們?cè)谇岸私缑孀隽?0秒倒計(jì)時(shí)功能。
  • 但是惡意用戶可以繞過前端界面向后端頻繁請(qǐng)求 驗(yàn)證碼。

解決辦法:

  • 在后端也要限制用戶請(qǐng)求 驗(yàn)證碼的頻率。60秒內(nèi)只允許一次請(qǐng)求 驗(yàn)證碼。
  • 在Redis數(shù)據(jù)庫中緩存一個(gè)數(shù)值,有效期設(shè)置為60秒。

1. 避免頻繁發(fā)送 驗(yàn)證碼邏輯分析

2. 避免頻繁發(fā)送 驗(yàn)證碼邏輯實(shí)現(xiàn)

1.提取、校驗(yàn)send_flag

send_flag = redis_conn.get('send_flag_%s' % mobile)
if send_flag:
    return http.JsonResponse({'code': RETCODE.THROTTLINGERR, 'errmsg': '發(fā)送 過于頻繁'})

2.重新寫入send_flag

  
# 保存 驗(yàn)證碼
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.界面渲染頻繁發(fā)送 提示信息

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數(shù)據(jù)庫

Redis的 C - S 架構(gòu):

  • 基于客戶端-服務(wù)端模型以及請(qǐng)求/響應(yīng)協(xié)議的TCP服務(wù)。
  • 客戶端向服務(wù)端發(fā)送一個(gè)查詢請(qǐng)求,并監(jiān)聽Socket返回。
  • 通常是以阻塞模式,等待服務(wù)端響應(yīng)。
  • 服務(wù)端處理命令,并將結(jié)果返回給客戶端。

存在的問題:

  • 如果Redis服務(wù)端需要同時(shí)處理多個(gè)請(qǐng)求,加上網(wǎng)絡(luò)延遲,那么服務(wù)端利用率不高,效率降低。

解決的辦法:

  • 管道pipeline

1. pipeline的介紹

管道pipeline

  • 可以一次性發(fā)送多條命令并在執(zhí)行完后一次性將結(jié)果返回。
  • pipeline通過減少客戶端與Redis的通信次數(shù)來實(shí)現(xiàn)降低往返延時(shí)時(shí)間。

實(shí)現(xiàn)的原理

  • 實(shí)現(xiàn)的原理是隊(duì)列。
  • Client可以將三個(gè)命令放到一個(gè)tcp報(bào)文一起發(fā)送。
  • Server則可以將三條命令的處理結(jié)果放到一個(gè)tcp報(bào)文返回。
  • 隊(duì)列是先進(jìn)先出,這樣就保證數(shù)據(jù)的順序性。

2. pipeline操作Redis數(shù)據(jù)庫

1.實(shí)現(xiàn)步驟

1. 創(chuàng)建Redis管道
2. 將Redis請(qǐng)求添加到隊(duì)列
3. 執(zhí)行請(qǐng)求

2.代碼實(shí)現(xiàn)

  
  
# 創(chuàng)建Redis管道
  
  
pl = redis_conn.pipeline()
  
  
# 將Redis請(qǐng)求添加到隊(duì)列
  
  
pl.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
pl.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1)
  
  
# 執(zhí)行請(qǐng)求
  
  
pl.execute()

生產(chǎn)者消費(fèi)者設(shè)計(jì)模式

思考:

  • 下面兩行代碼存在什么問題?

問題:

  • 我們的代碼是自上而下同步執(zhí)行的。
  • 發(fā)送 是耗時(shí)的操作。如果 被阻塞住,用戶響應(yīng)將會(huì)延遲。
  • 響應(yīng)延遲會(huì)造成用戶界面的倒計(jì)時(shí)延遲。

解決:

  • 異步發(fā)送
  • 發(fā)送 和響應(yīng)分開執(zhí)行,將**發(fā)送從主業(yè)務(wù)中解耦**出來。

思考:

  • 如何將**發(fā)送從主業(yè)務(wù)中解耦**出來。

生產(chǎn)者消費(fèi)者設(shè)計(jì)模式介紹

  • 為了將**發(fā)送從主業(yè)務(wù)中解耦出來,我們引入生產(chǎn)者消費(fèi)者設(shè)計(jì)模式**。
  • 它是最常用的解耦方式之一,尋找**中間人(broker)**搭橋,保證兩個(gè)業(yè)務(wù)沒有直接關(guān)聯(lián)。

總結(jié):

  • 生產(chǎn)者生成消息,緩存到消息隊(duì)列中,消費(fèi)者讀取消息隊(duì)列中的消息并執(zhí)行。
  • 由美多商城生成發(fā)送 消息,緩存到消息隊(duì)列中,消費(fèi)者讀取消息隊(duì)列中的發(fā)送 消息并執(zhí)行。

RabbitMQ介紹和使用

1. RabbitMQ介紹

  • 消息隊(duì)列是消息在傳輸?shù)倪^程中保存消息的容器。

  • 現(xiàn)在主流消息隊(duì)列有:RabbitMQActiveMQ、Kafka等等。

    • RabbitMQActiveMQ比較

      • 系統(tǒng)吞吐量:RabbitMQ好于ActiveMQ
      • 持久化消息:RabbitMQActiveMQ都支持
      • 高并發(fā)和可靠性:RabbitMQ好于ActiveMQ
    • RabbitMQKafka

      • 系統(tǒng)吞吐量:RabbitMQ弱于Kafka
      • 可靠性和穩(wěn)定性:RabbitMQ好于Kafka比較
      • 設(shè)計(jì)初衷:Kafka是處理日志的,是日志系統(tǒng),所以并沒有具備一個(gè)成熟MQ應(yīng)該具備的特性。
  • 綜合考慮,本項(xiàng)目選擇RabbitMQ作為消息隊(duì)列。

2. 安裝RabbitMQ(ubuntu 16.04)

1.安裝Erlang

  • 由于 RabbitMQ 是采用 Erlang 編寫的,所以需要安裝 Erlang 語言庫。
  
# 1. 在系統(tǒng)中加入 erlang apt 倉庫
$ wget 
$ sudo dpkg -i erlang-solutions_1.0_all.deb
# 2. 修改 Erlang 鏡像地址,默認(rèn)的下載速度特別慢
$ vim /etc/apt/sources.list.d/erlang-solutions.list
# 替換默認(rèn)值
$ deb  xenial contrib
# 3. 更新 apt 倉庫和安裝 Erlang
$ sudo apt-get update
$ sudo apt-get install erlang erlang-nox

2.安裝RabbitMQ

  • 安裝成功后,默認(rèn)就是啟動(dòng)狀態(tài)。
  
# 1. 先在系統(tǒng)中加入 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
# 啟動(dòng)
$ sudo systemctl start rabbitmq-server
# 關(guān)閉
$ sudo systemctl stop rabbitmq-server

3.Python訪問RabbitMQ

  • RabbitMQ提供默認(rèn)的administrator賬戶。
  • 用戶名和密碼:guestguest
  • 協(xié)議:amqp
  • 地址:localhost
  • 端口:5672
  • 查看隊(duì)列中的消息:sudo rabbitctl list_queues
  
# Python3虛擬環(huán)境下,安裝pika
$ pip install pika
  
# 生產(chǎn)者代碼:rabbitmq_producer.py
import pika
# 鏈接到RabbitMQ服務(wù)器
credentials = pika.PlainCredentials('guest', 'guest')
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost',5672,'/',credentials))
#創(chuàng)建頻道
channel = connection.channel()
# 聲明消息隊(duì)列
channel.queue_declare(queue='zxc')
# routing_key是隊(duì)列名 body是要插入的內(nèi)容
channel.basic_publish(exchange='', routing_key='zxc', body='Hello RabbitMQ!')
print("開始向 'zxc' 隊(duì)列中發(fā)布消息 'Hello RabbitMQ!'")
# 關(guān)閉鏈接
connection.close()
  
# 消費(fèi)者代碼:rabbitmq_customer.py 
import pika
# 鏈接到rabbitmq服務(wù)器
credentials = pika.PlainCredentials('guest', 'guest')
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost',5672,'/',credentials))
# 創(chuàng)建頻道,聲明消息隊(duì)列
channel = connection.channel()
channel.queue_declare(queue='zxc')
# 定義接受消息的回調(diào)函數(shù)
def callback(ch, method, properties, body):
    print(body)
# 告訴RabbitMQ使用callback來接收信息
channel.basic_consume(callback, queue='zxc', no_ack=True)
# 開始接收信息
channel.start_consuming()

3. 新建administrator用戶

  
# 新建用戶,并設(shè)置密碼
$ sudo rabbitmqctl add_user admin your_password 
# 設(shè)置標(biāo)簽為administrator
$ sudo rabbitmqctl set_user_tags admin administrator
# 設(shè)置所有權(quán)限
$ sudo rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"
# 查看用戶列表
sudo rabbitmqctl list_users
# 刪除用戶
$ sudo rabbitmqctl delete_user admin

4. RabbitMQ配置遠(yuǎn)程訪問

1.準(zhǔn)備配置文件

  • 安裝好 RabbitMQ 之后,在 /etc/rabbitmq 目錄下面默認(rèn)沒有配置文件,需要單獨(dú)下載。
$ cd /etc/rabbitmq/
$ wget 
$ sudo cp rabbitmq.config.example rabbitmq.config

2.設(shè)置配置文件

$ sudo vim rabbitmq.config
# 設(shè)置配置文件結(jié)束后,重啟RabbitMQ服務(wù)端
$ sudo systemctl restart rabbitmq-server

配置完成后,使用rabbitmq_producer.py、rabbitmq_customer.py測試。

Celery介紹和使用

思考:

  • 消費(fèi)者取到消息之后,要消費(fèi)掉(執(zhí)行任務(wù)),需要我們?nèi)?shí)現(xiàn)。
  • 任務(wù)可能出現(xiàn)高并發(fā)的情況,需要補(bǔ)充多任務(wù)的方式執(zhí)行。
  • 耗時(shí)任務(wù)很多種,每種耗時(shí)任務(wù)編寫的生產(chǎn)者和消費(fèi)者代碼有重復(fù)。
  • 取到的消息什么時(shí)候執(zhí)行,以什么樣的方式執(zhí)行。

結(jié)論:

  • 實(shí)際開發(fā)中,我們可以借助成熟的工具Celery來完成。
  • 有了Celery,我們?cè)谑褂蒙a(chǎn)者消費(fèi)者模式時(shí),只需要關(guān)注任務(wù)本身,極大的簡化了程序員的開發(fā)流程。

1. Celery介紹

  • Celery介紹:

    • 一個(gè)簡單、靈活且可靠、處理大量消息的分布式系統(tǒng),可以在一臺(tái)或者多臺(tái)機(jī)器上運(yùn)行。
    • 單個(gè) Celery 進(jìn)程每分鐘可處理數(shù)以百萬計(jì)的任務(wù)。
    • 通過消息進(jìn)行通信,使用消息隊(duì)列(broker)客戶端消費(fèi)者之間進(jìn)行協(xié)調(diào)。
  • 安裝Celery:

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

2. 創(chuàng)建Celery實(shí)例并加載配置

1.定義Celery包

2.創(chuàng)建Celery實(shí)例

celery_tasks.main.py

  
# celery啟動(dòng)文件
from celery import Celery
# 創(chuàng)建celery實(shí)例
celery_app = Celery('meiduo')

3.加載Celery配置

celery_tasks.config.py

  
# 指定消息隊(duì)列的位置
broker_url= 'amqp://guest:guest@192.168.103.158:5672'

celery_tasks.main.py

  
# celery啟動(dòng)文件
from celery import Celery
# 創(chuàng)建celery實(shí)例
celery_app = Celery('meiduo')
# 加載celery配置
celery_app.config_from_object('celery_tasks.config')

3. 定義發(fā)送 任務(wù)

1.注冊(cè)任務(wù):celery_tasks.main.py

  
# celery啟動(dòng)文件
from celery import Celery
# 創(chuàng)建celery實(shí)例
celery_app = Celery('meiduo')
# 加載celery配置
celery_app.config_from_object('celery_tasks.config')
# 自動(dòng)注冊(cè)celery任務(wù)
celery_app.autodiscover_tasks(['celery_tasks.sms'])

2.定義任務(wù):celery_tasks.sms.tasks.py

  
# bind:保證task對(duì)象會(huì)作為第一個(gè)參數(shù)自動(dòng)傳入
# name:異步任務(wù)別名
# retry_backoff:異常自動(dòng)重試的時(shí)間間隔 第n次(retry_backoff×2^(n-1))s
# max_retries:異常自動(dòng)重試次數(shù)的上限
@celery_app.task(bind=True, name='ccp_send_sms_code', retry_backoff=3)
def ccp_send_sms_code(self, mobile, sms_code):
    """
    發(fā)送 異步任務(wù)
    :param mobile: 手機(jī)號(hào)
    :param sms_code:  驗(yàn)證碼
    :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)
        # 有異常自動(dòng)重試三次
        raise self.retry(exc=e, max_retries=3)
    if send_ret != 0:
        # 有異常自動(dòng)重試三次
        raise self.retry(exc=Exception('發(fā)送 失敗'), max_retries=3)
    return send_ret

4. 啟動(dòng)Celery服務(wù)

$ cd ~/projects/meiduo_project/meiduo_mall
$ celery -A celery_tasks.main worker -l info
  • -A指對(duì)應(yīng)的應(yīng)用程序, 其參數(shù)是項(xiàng)目中 Celery實(shí)例的位置。
  • worker指這里要啟動(dòng)的worker。
  • -l指日志等級(jí),比如info等級(jí)。

5. 調(diào)用發(fā)送 任務(wù)

  
# 發(fā)送 驗(yàn)證碼
# CCP().send_template_sms(mobile,[sms_code, constants.SMS_CODE_REDIS_EXPIRES // 60], constants.SEND_SMS_TEMPLATE_ID)
# Celery異步發(fā)送 驗(yàn)證碼
ccp_send_sms_code.delay(mobile, sms_code)

6. 補(bǔ)充celery worker的工作模式

  • 默認(rèn)是進(jìn)程池方式,進(jìn)程數(shù)以當(dāng)前機(jī)器的CPU核數(shù)為參考,每個(gè)CPU開四個(gè)進(jìn)程。
  • 如何自己指定進(jìn)程數(shù):celery worker -A proj --concurrency=4
  • 如何改變進(jìn)程池方式為協(xié)程方式: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

總結(jié)

到此這篇關(guān)于Django開發(fā)時(shí)如何避免頻繁發(fā)送短信驗(yàn)證碼(python圖文代碼)的文章就介紹到這了,更多相關(guān)Django避免頻繁發(fā)送短信驗(yàn)證碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • python 將列表里的字典元素合并為一個(gè)字典實(shí)例

    python 將列表里的字典元素合并為一個(gè)字典實(shí)例

    這篇文章主要介紹了python 將列表里的字典元素合并為一個(gè)字典實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • python之如何查找多層嵌套字典的值

    python之如何查找多層嵌套字典的值

    這篇文章主要介紹了python之如何查找多層嵌套字典的值問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • Python高級(jí)特性切片(Slice)操作詳解

    Python高級(jí)特性切片(Slice)操作詳解

    在Python中對(duì)于具有序列結(jié)構(gòu)的數(shù)據(jù)來說都可以使用切片操作,需注意的是序列對(duì)象某個(gè)索引位置返回的是一個(gè)元素,而切片操作返回是和被切片對(duì)象相同類型對(duì)象的副本。
    2018-09-09
  • Python實(shí)現(xiàn)3行代碼解簡單的一元一次方程

    Python實(shí)現(xiàn)3行代碼解簡單的一元一次方程

    這篇文章主要介紹了Python實(shí)現(xiàn)3行代碼解簡單的一元一次方程,很適合Python初學(xué)者學(xué)習(xí)借鑒,需要的朋友可以參考下
    2014-08-08
  • Python合并多個(gè)Excel數(shù)據(jù)的方法

    Python合并多個(gè)Excel數(shù)據(jù)的方法

    這篇文章主要介紹了Python合并多個(gè)Excel數(shù)據(jù)的方法也就是說將多個(gè)excel中的數(shù)據(jù)合并到另一個(gè)表中,本文通過實(shí)例代碼相結(jié)合的形式給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2018-07-07
  • 三步解決python PermissionError: [WinError 5]拒絕訪問的情況

    三步解決python PermissionError: [WinError 5]拒絕訪問的情況

    這篇文章主要介紹了三步解決python PermissionError: [WinError 5]拒絕訪問的情況,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-04-04
  • Python爬取哆啦A夢(mèng)-伴我同行2豆瓣影評(píng)并生成詞云圖

    Python爬取哆啦A夢(mèng)-伴我同行2豆瓣影評(píng)并生成詞云圖

    哆啦A夢(mèng)系列是陪伴我,乃至陪伴了幾代人成長的故事.50年來,藤子·F·不二雄先生創(chuàng)造了竹蜻蜓,任意門,時(shí)光機(jī)器等等無數(shù)的新奇道具,讓大雄和他的小伙伴們經(jīng)歷了各種冒險(xiǎn),也經(jīng)歷了許多充滿戲劇性的啼笑皆非的日常.特意寫了這篇文章,教大家怎么繪制詞云圖,需要的朋友可以參考下
    2021-06-06
  • 使用pytorch提取卷積神經(jīng)網(wǎng)絡(luò)的特征圖可視化

    使用pytorch提取卷積神經(jīng)網(wǎng)絡(luò)的特征圖可視化

    這篇文章主要給大家介紹了關(guān)于使用pytorch提取卷積神經(jīng)網(wǎng)絡(luò)的特征圖可視化的相關(guān)資料,文中給出了詳細(xì)的思路以及示例代碼,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-03-03
  • LyScript實(shí)現(xiàn)計(jì)算片段Hash并寫出Excel的示例代碼

    LyScript實(shí)現(xiàn)計(jì)算片段Hash并寫出Excel的示例代碼

    本案例將學(xué)習(xí)運(yùn)用LyScript計(jì)算特定程序中特定某些片段的Hash特征值,并通過xlsxwriter這個(gè)第三方模塊將計(jì)算到的hash值存儲(chǔ)成一個(gè)excel表格,感興趣的可以跟隨小編一起學(xué)習(xí)一下
    2022-09-09
  • python對(duì)execl 處理操作代碼

    python對(duì)execl 處理操作代碼

    這篇文章主要介紹了python對(duì)execl 處理操作,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06

最新評(píng)論