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. iOS/swift 单选框和复选框

    /** 复选框 */ import UIKit class LYBmutipleSelectView: UIView { var selectindexs:[Int]=[]//选中的 //标题数组 v ...

  2. sublime Text3 实现2:1:1三分屏效果

    小trick, 水一篇博客 先上效果图 由于写题啥的时候需要重定向输入输出改数据对拍, 设置成这样的效果就非常直观的看数据 直接切题, 首选项--快捷键--default里搜索alt+shift+1( ...

  3. Web api配置填坑攻略

    最近开始使用web api,开发调试过程还算顺利,现在项目已经发布,网站已经部署,结果浏览过程出现问题(不出问题好像不正常吧……),做个note开始填坑. 1.1号坑 咋一开始就爆出另一个程序正在使用 ...

  4. ca33a_demo_c++_新旧代码的兼容char数组与vector_string相互转换

    /*ca33a_demo_c++33_CppPrimer_新旧代码的兼容_txwtech旧代码:数组和c风格字符串新代码:vector和string相互转换:c风格字符串<- ->stri ...

  5. GoAccess分析Web日志

    简介 为什么要用GoAccess? GoAccess 被设计成快速的并基于终端的日志分析工具.其核心理念是不需要通过 Web 浏览器就能快速分析并实时查看 Web 服务器的统计数据(这对于需要使用 S ...

  6. Apache Hudi:云数据湖解决方案

    1. 引入 开源Apache Hudi项目为Uber等大型组织提供流处理能力,每天可处理数据湖上的数十亿条记录. 随着世界各地的组织采用该技术,Apache开源数据湖项目已经日渐成熟. Apache ...

  7. sharding-jdbc源码解析

    参考博客:https://cloud.tencent.com/developer/article/1529692 看sharding-jdbc支持XA协议重点看下面的代码 sharding-trans ...

  8. 1、struct2第一个项目登陆流程

    这些jar包的作用:第一个日志记录 第二个 使用freemarker制作页面,freemarker和jsp一样都是页面操作的 ognl是struct2提供的向el标签设置的包 struct2-core ...

  9. python 2 与python 3区别汇总

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

  10. mysqldump: Got error: 1044: Access denied for user 'root'@'%' to database 'hhh' when using LOCK TABLES

    错误原因:mysqldump 命令执行时,需要四种权限,分别是:select,show view,trigger,lock table.但是因为没有lock table的权限,导致上述错误发生. 修改 ...