07 drf源码剖析之节流

1. 节流简述

  • 节流类似于权限,它确定是否应授权请求。节流指示临时状态,并用于控制客户端可以向API发出的请求的速率。

  • 还有情况可能是 ,由于某些服务特别耗费资源,因此您需要在API的不同部分施加不同的约束。

  • 频率限制在认证、权限之后

2. 节流使用

  • 在settings配置文件中设置规定时间段内可以访问的次数

    REST_FRAMEWORK = {
    "DEFAULT_THROTTLE_RATES": {"anon": '10/m'},
    }
  • 在需要节流的类中加throttle_classes

    from rest_framework.views import APIView
    from rest_framework.response import Response from rest_framework.throttling import AnonRateThrottle,BaseThrottle class ArticleView(APIView):
    throttle_classes = [AnonRateThrottle,]
    def get(self,request,*args,**kwargs):
    return Response('文章列表') class ArticleDetailView(APIView):
    def get(self,request,*args,**kwargs):
    return Response('文章列表')

3. 源码剖析

  • 请求过来先执行dispatch方法

    class APIView(View):
    permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES def dispatch(self, request, *args, **kwargs):
    # 封装request对象...
    self.initial(request, *args, **kwargs)
    # 通过反射执行视图中的方法...
  • initial方法过渡

    def initial(self, request, *args, **kwargs):
    # 版本的处理...
    # 认证...
    # 权限判断 self.check_throttles(request) # 节流
  • 将所有的节流类实例化成对象列表

    def get_throttles(self):
    return [throttle() for throttle in self.throttle_classes]
  • 循环执行每个对象的allow_request方法

    def check_throttles(self, request):
    throttle_durations = []
    for throttle in self.get_throttles():
    if not throttle.allow_request(request, self):
    throttle_durations.append(throttle.wait())
  • 执行allow_request方法,AnonRateThrottle没有allow_request,去父类找

    class AnonRateThrottle(SimpleRateThrottle):
    scope = 'anon' def get_cache_key(self, request, view):
    if request.user.is_authenticated:
    return None # Only throttle unauthenticated requests. return self.cache_format % {
    'scope': self.scope,
    'ident': self.get_ident(request)
    }
  • 执行SimpleRateThrottle类中allow_request方法

    • 获取请求用户的IP
    • 根据IP获取他的所有访问记录
    • 获取当前时间
    • 将不在规定时间的记录删除掉
    • 判断规定时间段时间内访问了多少次
    • 和设定次数对比,判断用户是否可以继续访问
    class SimpleRateThrottle(BaseThrottle):
    cache = default_cache
    timer = time.time
    cache_format = 'throttle_%(scope)s_%(ident)s'
    scope = None
    THROTTLE_RATES = api_settings.DEFAULT_THROTTLE_RATES def __init__(self):
    if not getattr(self, 'rate', None):
    self.rate = self.get_rate()
    self.num_requests, self.duration = self.parse_rate(self.rate) def parse_rate(self, rate):
    if rate is None:
    return (None, None)
    num, period = rate.split('/')
    num_requests = int(num)
    duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[0]]
    return (num_requests, duration) def allow_request(self, request, view):
    if self.rate is None:
    return True # 获取请求用户的IP
    self.key = self.get_cache_key(request, view)
    if self.key is None:
    return True # 根据IP获取他的所有访问记录,[]
    self.history = self.cache.get(self.key, []) self.now = self.timer() 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() def throttle_success(self):
    self.history.insert(0, self.now)
    self.cache.set(self.key, self.history, self.duration)
    return True def throttle_failure(self):
    return False def wait(self):
    if self.history:
    remaining_duration = self.duration - (self.now - self.history[-1])
    else:
    remaining_duration = self.duration available_requests = self.num_requests - len(self.history) + 1
    if available_requests <= 0:
    return None return remaining_duration / float(available_requests)

总结:

  • 实现原理

    来访问时:

    1.获取当前时间 100121280

    2.100121280-60 = 100121220,小于100121220所有记录删除

    3.判断1分钟以内已经访问多少次了? 4

    4.无法访问

    停一会

    来访问时:

    1.获取当前时间 100121340

    2.100121340-60 = 100121280,小于100121280所有记录删除

    3.判断1分钟以内已经访问多少次了? 0

    4.可以访问
  • 具体流程
    1. 请求来时会执行allow_follow方法,
    2. 会用self.key获取请求用户的ip,再用self.history根据用户的ip获取其访问的记录,
    3. 获取当前的时间,用当前的时间减去设定的时间段,
    4. 循环该用户访问的记录,将不在该时间段的记录pop掉,
    5. 通过len判定该时间段已经访问了多少次,超过限定次数会返回false
    6. 匿名用户是通过ip进行访问限制,登录用户通过用户的id进行访问限制

07 drf源码剖析之节流的更多相关文章

  1. drf源码剖析系列(系列目录)

    drf源码剖析系列(系列目录) 01 drf源码剖析之restful规范 02 drf源码剖析之快速了解drf 03 drf源码剖析之视图 04 drf源码剖析之版本 05 drf源码剖析之认证 06 ...

  2. 06 drf源码剖析之权限

    06 drf源码剖析之权限 目录 06 drf源码剖析之权限 1. 权限简述 2. 权限使用 3.源码剖析 4. 总结 1. 权限简述 权限与身份验证和限制一起,决定了是否应授予请求访问权限. 权限检 ...

  3. 05 drf源码剖析之认证

    05 drf源码剖析之认证 目录 05 drf源码剖析之认证 1. 认证简述 2. 认证的使用 3. 源码剖析 4. 总结 1. 认证简述 当我们通过Web浏览器与API进行交互时,我们可以登录,然后 ...

  4. 04 drf源码剖析之版本

    04 drf源码剖析之版本 目录 04 drf源码剖析之版本 1. 版本简述 2. 版本使用 3.源码剖析 4. 总结 1. 版本简述 API版本控制使您可以更改不同客户端之间的行为.REST框架提供 ...

  5. 02 drf源码剖析之快速了解drf

    02 drf源码剖析之快速了解drf 目录 02 drf源码剖析之快速了解drf 1. 什么是drf 2. 安装 3. 使用 3. DRF的应用场景 1. 什么是drf drf是一个基于django开 ...

  6. 07 flask源码剖析之用户请求过来流程

    07 Flask源码之:用户请求过来流程 目录 07 Flask源码之:用户请求过来流程 1.创建ctx = RequestContext对象 2. 创建app_ctx = AppContext对象 ...

  7. drf源码分析系列---节流(访问频率限制)

    使用 from rest_framework.throttling import AnonRateThrottle from rest_framework.generics import ListAP ...

  8. 01 drf源码剖析之restful规范

    01 restful规范 目录 01 restful规范 1. 什么是restful规范 2.restful规范详细 1. 什么是restful规范 restful是一套规则,是程序间进行数据传输的一 ...

  9. DRF源码系列分析

    DRF源码系列分析 DRF源码系列分析--版本 DRF源码系列分析--认证 DRF源码系列分析--权限 DRF源码系列分析--节流

随机推荐

  1. Docker中使用RabbitMQ

    安装Docker yum install docker //安装完成以后,可以查看一下docker的版本 docker -v //Docker version 1.13.1, build 64e998 ...

  2. CVE-2018-12613 phpmyadmin文件包含getshell连载(三)

    这是phpmyadmin系列渗透思路的第三篇文章,前面一篇文章阐述了通过慢查询日志getshell,本文将通过文件包含漏洞展开讨论 #001 影响版本 Phpmyadmin 4.8.0/4.8.0.1 ...

  3. Java学习笔记6(集合类)

    集合类 集合按照其存储结构可以分为两大类,即单列集合Collection和双列集合Map. Collection:单列集合类的根接口,用于存储一系列符合某种规则的元素,有List和Set两个重要子接口 ...

  4. WeChair项目Beta冲刺(9/10)

    团队项目进行情况 1.昨日进展    Beta冲刺第九天 昨日进展: 项目开始扫尾 2.今日安排 前端:前端工作已经完成 后端:扫码占座后端测试,实现对超时预约座位下座的功能 数据库:和后端组织协商扫 ...

  5. mongodb 数据库 增删改查

    mongodb    数据库      增删改查 增: // 引入express 模块 var express = require('express'); // 路由var router = expr ...

  6. 北京开发票/v电13543443967

    关于事项:Iㄋ5一★4З44一★ㄋ9.б7开发票的准备资料必须要公司名称个人的话就用个人名字和身份证去税务柜台申请办理!公司的话要提供公司全称就是营业执照上的名称,纳税人税号,如果是开普通增值税发票的 ...

  7. 黎活明8天快速掌握android视频教程--15_采用Pull解析器解析和生成XML内容

    1.该项目主要有下面的两个作用 (1)将xml文件解析成对象的List对象,xml文件可以来自手机本地,也可以来自服务器返回的xml数据 (2)强list对象保存成xml文件,xml保存到手机的内存卡 ...

  8. python 2 与python 3区别汇总

    python 2 与python 3区别汇总 一.核心类差异1. Python3 对 Unicode 字符的原生支持.Python2 中使用 ASCII 码作为默认编码方式导致 string 有两种类 ...

  9. laravel --- composer install之后,项目没有vender目录

    composer install之后,项目没有vender目录 1. 原因一:PHP版本过低 PHP版本需要7.1以上,目前使用的是7.0.23

  10. Java | 顶层类(Top-Level Class)

    前言 本文内容根据 Java 官方教程中的<课程:类和对象>编写而成. 本文提供的是 JDK 14 的示例代码. 定义 顶层类(Top-Level Class),是 Java 中对类的一种 ...