美文网首页大数据 爬虫Python AI Sql
DRF-访问频率配置(节流)

DRF-访问频率配置(节流)

作者: f050d162bcc1 | 来源:发表于2019-01-12 17:26 被阅读0次

访问频率控制(节流)

  • 我们可以先编写一个类
class VisitThrottle(object):
    def allow_request(self, request, view):
        return True  # False表示访问频率太高被限制
    def wait(self):
        return None    
微信截图_20190112111427
  • postman校验
微信截图_20190112111522 微信截图_20190112111555
  • 获取用户ip
class VisitThrottle(object):
    def allow_request(self, request, view):
        # 1. 获取用户ip
        remote_addr = request._request.META.get("REMOTE_ADDR")
        #print(remote_addr)

        ...
  • 添加访问记录
import time

# 存放访问记录(一般放数据库或者缓存中)
VISIT_RECORD = {}


class VisitThrottle(object):
    def allow_request(self, request, view):
        # 1. 获取用户ip
        remote_addr = request._request.META.get("REMOTE_ADDR")
        # print(remote_addr)
        # 2. 添加到访问记录中
        ctime = time.time()
        if remote_addr not in VISIT_RECORD:
            VISIT_RECORD[remote_addr] = [ctime, ]
            return True
        return False  # False表示访问频率太高被限制

    def wait(self):
        return None
微信截图_20190112112710
  • 两种情况,之前说的是第一种,当用户没有访问的时候的情况,记录用户的访问记录的列表里面没有用户访问,但是如果用户已经访问,而我们需求是1分钟内只能访问3次,我们需要改进代码
class VisitThrottle(object):
    def allow_request(self, request, view):
        # 1. 获取用户ip
        remote_addr = request._request.META.get("REMOTE_ADDR")
        # print(remote_addr)
        # 2. 添加到访问记录中
        ctime = time.time()
        # 当VISIT_RECORD中没有这个记录,可以直接访问,添加一个记录
        if remote_addr not in VISIT_RECORD:
            VISIT_RECORD[remote_addr] = [ctime, ]
            return True
        history = VISIT_RECORD.get(remote_addr)
        # 拿到最后历史记录里面的最后一个时间,如果最后一个时间小于当前时间-60
        while history and history[-1] < ctime - 60:
            history.pop()
        if len(history) < 3:
            history.insert(0,ctime)
            return True

        return False  # False表示访问频率太高被限制

    def wait(self):
        return None
微信截图_20190112113607
  • postman校验
微信截图_20190112113637
  • wait返回的值是一个提示,表示多少秒以后可以访问
    def wait(self):
        return 10 # 写死了10秒
微信截图_20190112120909
  • 在wait里面拿到访问记录
微信截图_20190112121324
    def wait(self):
        """
        还需要等多少秒可以访问
        :return:
        """
        ctime = time.time()

        return 60 - (ctime - self.history[-1])

源码流程

内置控制频率的类

from rest_framework.throttling import BaseThrottle


class VisitThrottle(BaseThrottle):

    def __init__(self):
        self.history = None

    def allow_request(self, request, view):
        # 1. 获取用户ip
        remote_addr = request._request.META.get("REMOTE_ADDR")
        # print(remote_addr)
        # 2. 添加到访问记录中
        ctime = time.time()
        # 当VISIT_RECORD中没有这个记录,可以直接访问,添加一个记录
        if remote_addr not in VISIT_RECORD:
            VISIT_RECORD[remote_addr] = [ctime, ]
            return True
        history = VISIT_RECORD.get(remote_addr)
        self.history = history
        # 拿到最后历史记录里面的最后一个时间,如果最后一个时间小于当前时间-60
        while history and history[-1] < ctime - 60:
            history.pop()
        if len(history) < 3:
            history.insert(0, ctime)
            return True

        return False  # False表示访问频率太高被限制

    def wait(self):
        """
        还需要等多少秒可以访问
        :return:
        """
        ctime = time.time()
        return 60 - (ctime - self.history[-1])
微信截图_20190112141225
  • 在SimpleRateThrottle里面
微信截图_20190112141531
  • get_rate方法
微信截图_20190112141649
  • get_rate方法返回值读取配置文件
微信截图_20190112141713
  • 在我们自己继承的类里面写scpoe
微信截图_20190112142138
  • settings配置
# 跟rest_有关的配置
REST_FRAMEWORK = {
    # "DEFAULT_AUTHENTICATION_CLASSES": ["myutils.auth.MyAuthtication"],
    "UNAUTHENTICATED_USER": lambda: "匿名用户哈哈",
    # "DEFAULT_PERMISSION_CLASSES": ["myutils.permission.MyPermission"],
    "DEFAULT_THROTTLE_RATES": {
        "myscope": '3/m'
    }

}
微信截图_20190112142416
  • 我们设置的频率在源码里面传递
微信截图_20190112142521
  • 3/m源码 m表示60
微信截图_20190112142816
  • 回到构造函数
    def __init__(self):
        # 在构造方法里面,通过反射调用rate
        if not getattr(self, 'rate', None):
            # "3/m"
            self.rate = self.get_rate()
        #   3次 self.num_requests    60秒  self.duration
        self.num_requests, self.duration = self.parse_rate(self.rate)
  • 内部的allow_request方法
微信截图_20190112143207
  • 使用ip作为我们的标识
class VisitThrottle(SimpleRateThrottle):
    scope = "myscope"

    def get_cache_key(self, request, view):
        return self.get_ident(request)
  • allow_request
    def allow_request(self, request, view):
        """
        Implement the check to see if the request should be throttled.

        On success calls `throttle_success`.
        On failure calls `throttle_failure`.
        """
        if self.rate is None:
            return True
        # 方法缓存里面
        self.key = self.get_cache_key(request, view)
        if self.key is None:
            return True
        # 去缓存里面拿到所有记录
        self.history = self.cache.get(self.key, [])
        # 获取当前时间
        self.now = self.timer()

        # Drop any requests from the history which have now passed the
        # throttle duration
        while self.history and self.history[-1] <= self.now - self.duration:
            self.history.pop()
        if len(self.history) >= self.num_requests:
            # 失败
            return self.throttle_failure()
        # 成功
        return self.throttle_success()
  • settings配置
# 跟rest_有关的配置
REST_FRAMEWORK = {
    # "DEFAULT_AUTHENTICATION_CLASSES": ["myutils.auth.MyAuthtication"],
    "UNAUTHENTICATED_USER": lambda: "匿名用户哈哈",
    # "DEFAULT_PERMISSION_CLASSES": ["myutils.permission.MyPermission"],
    "DEFAULT_THROTTLE_CLASSES": ['myutils.throttle.VisitThrottle'],
    "DEFAULT_THROTTLE_RATES": {
        "myscope": '3/m'
    }

}

对当前用户做限流操作

class UserThrottle(SimpleRateThrottle):
    scope = "user_scope"

    def get_cache_key(self, request, view):
        return request.user.username
  • settings配置
# 跟rest_有关的配置
REST_FRAMEWORK = {
    # "DEFAULT_AUTHENTICATION_CLASSES": ["myutils.auth.MyAuthtication"],
    "UNAUTHENTICATED_USER": lambda: "匿名用户哈哈",
    # "DEFAULT_PERMISSION_CLASSES": ["myutils.permission.MyPermission"],
    "DEFAULT_THROTTLE_CLASSES": ['myutils.throttle.VisitThrottle'],
    "DEFAULT_THROTTLE_RATES": {
        "myscope": '3/m',  # 匿名用户一分钟访问3次
        "user_scope": "8/m"  # 登陆用户一分钟访问8次
    }

}
微信截图_20190112163216

相关文章

  • DRF-访问频率配置(节流)

    访问频率控制(节流) 我们可以先编写一个类 postman校验 获取用户ip 添加访问记录 两种情况,之前说的是第...

  • 函数的节流与防抖

    概念 函数的节流与防抖是优化JavaScript的高频率执行的一种手段。 节流 函数的节流应用于一些函数高频率的场...

  • 函数的节流与防抖

    概念函数的节流与防抖是优化JavaScript的高频率执行的一种手段。 节流函数的节流应用于一些函数高频率的场景,...

  • 防抖和节流

    防抖是控制次数,节流是控制频率

  • 前端面试常见——节流

    节流 什么是节流?高频事件触发,但在 n 秒内只会执行一次,所以节流会稀释函数的执行频率。 代码附上

  • [性能优化]面试常考篇

    节流 节流顾名思义则是将减少一段时间内触发的频率。节流会稀释你的执行频率,比如每间隔1秒钟,只会执行一次函数,无论...

  • JS节流小知识

    一、什么是节流? 节流:当某个操作是连续性执行的时候,我们通过某种方式,降低该操作的执行频率,这就是节流。就跟水龙...

  • httpclient 访问图片

    图片传输采用字节流访问接口: 具体实现:

  • 前端知识

    防抖节流 优化高频率事件 onscroll oninput resize onkeyup keydown.......

  • 前端知识一

    防抖节流 优化高频率事件 onscroll oninput resize onkeyup keydown.......

网友评论

    本文标题:DRF-访问频率配置(节流)

    本文链接:https://www.haomeiwen.com/subject/nhucdqtx.html