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. filebeat v6.3 多行合并的步骤 多个表达式同时匹配

    配置文件位于/etc/filebeat/filebeat.yml,就是filebeat的主配置文件打开文件filebeat.yml,搜索multiline:,默认是注释的,常用的有如下三个配置: mu ...

  2. IOS 发布 程序截图问题

    特别要注意那个有无状态栏时的像素要求 **注意:在截屏模拟器的时候,请把模拟器的Scale设置成100%(Window->Scale->100%) 开模拟器截图,运行每一个iOS型号,然后 ...

  3. 如何解析json格式的字符串

    package com.json; import java.util.ArrayList; import java.util.HashMap; import java.util.List; impor ...

  4. jmeter录制app测试脚本

    1.jmeter 下载地址 https://jmeter.apache.org 2.选择下载包 3.下载完成后解压即可使用(也可以配置环境变量,但我一般不配置,可以使用) 4.打开jmeter 创建线 ...

  5. 使用matplotlib进行可视化

    转自:https://blog.csdn.net/qq_30614345/article/details/99049790 https://blog.csdn.net/qq_30614345/arti ...

  6. 龙芯团队完成CoreCLR MIPS64移植,在github开源

    国产龙芯的软件生态之中.NET不会缺席,毕竟 C# 与 .NetCore/Mono 也是全球几大主流的编程语言和运行平台之一,最近一段时间听到太多的鼓吹政务领域不支持.NET, 大家都明白这是某些人为 ...

  7. linux kernel update

    linux内核升级 最近HW行动,报出来的linux系统内核漏洞,环境中全部是2.6.32-431.el6.x86_64的主机,需要全部升级到754版本,这也是第一次进行内核升级操作. 先找了一台和生 ...

  8. pick靶场-sql注入

    甲.数字型注入 数字型注入一般提交值没有引号,所以直接在后面构造语句就可以了. 抓包查看 构造语句 提交后 该数据库表内容被爆出来了. 乙.字符型注入 首先我们要知道一点,字符串在数据库中提交是需要用 ...

  9. SDL软件安全读书笔记(一)

    # 如何应对当前的全球网络安全威胁? 开发安全漏洞尽可能少的软件,应该着眼于源头安全. 边界安全盒深度防御是重要的安全手段,但软件自身的安全是安全防护的第一关. 即使软件源头存在较少的漏洞,这些漏洞也 ...

  10. vue中使用element2

    阻止谷歌下记住密码 当我们将input框的类型设置为密码框的时候,就会出现下面这种效果,不仅样式不统一,有的时候,密码框的上面并不是用户名,而是其他的内容,也会被强制显示为用户名: 首先需要解决样式问 ...