基本思路(原生Django而言):

  在django2.x中,若出现节流(访问频率控制)的需求,我们首先想到的是使用一个字典(dict类型)来存储所有IP地址的访问时间记录,这是针对于匿名用户(IP)而言的

  1. {
  2. "111.222.3.44": [, , , , ....],
  3. "1.333.44.555": [, , , .....]
  4. }

  原生request的消息体中,在environ下的REMOTE_ADDR保存了客户端的IP地址

  

  由于请求经过WSGIRequest封装后,必经中间件层,所以考虑通过中间件来实现节流功能

  1. from django.utils.deprecation import MiddlewareMixin
  2. from django.http.response import HttpResponse
  3. import time
  4.  
  5. MAX_PER_VISITED_NUMS = 3
  6. VISITED_IP_THROTTLE = dict()
  7.  
  8. class ThrottleMiddleware(MiddlewareMixin):
  9. """
  10. 节流中间件
  11. VISITED_IP_THROTTLE每分钟最大访问次数
  12. """
  13. def request_allowed(self, request):
  14. """自定义访问频率限制器, 用于限制匿名用户的访问频率限制"""
  15. ip = request.META['REMOTE_ADDR']
  16. cur_time = time.time()
  17. # 如果ip在限制器中有记录
  18. if ip in VISITED_IP_THROTTLE:
  19. visiting_record = VISITED_IP_THROTTLE[ip]
  20.  
  21. while visiting_record:
  22. # 与列表中最后一次访问记录的时间差大于60秒, 移除最后一次记录并继续循环
  23. if cur_time - 60 >= visiting_record[-1]:
  24. visiting_record.pop(-1)
  25. continue
  26. # 访问记录列表超过最大访问次数
  27. if len(visiting_record) >= MAX_PER_VISITED_NUMS:
  28. return False
  29. # 与列表中最后一次访问记录的时间差小于60秒
  30. visiting_record.insert(0, cur_time)
  31. return True
  32.  
  33. # 无记录则新建该IP访问记录
  34. VISITED_IP_THROTTLE[ip] = list()
  35. VISITED_IP_THROTTLE[ip].insert(0, cur_time)
  36. return True
  37.  
  38. def process_request(self, request):
  39. if self.request_allowed(request):
  40. print(True)
  41. return HttpResponse("True")
  42. else:
  43. print(False)
  44. return HttpResponse("False")

  运行结果:

  

  这是针对在访问用户较少的情况下才采用的全局变量来存储访问记录, 实际情况中,最好使用redis作为缓存来存储记录。

restframework版:

  自定义节流控制器

  使用redis缓存访问记录(hash类型)

  redispool.py(作连接池, 参数设置为你自己的redis连接信息)

  1. import redis
  2. from vue_shop import settings
  3.  
  4. REDIS_POOL = redis.ConnectionPool(**settings.REDIS_KWARGS)

  throttle.py

  1. import time
  2. import redis
  3. from utils.redispool import REDIS_POOL
  4. import json
  5. from rest_framework.throttling import SimpleRateThrottle
  6.  
  7. class AnonymityUserThrottle(object):
  8. """
  9. 自定义匿名用户节流器, 采用redis缓存访问记录
  10. MAX_PER_VISITED_NUMS: 每分钟最高访问次数
  11. name: 缓存(redis)中,hash类型的name
  12. """
  13. MAX_PER_VISITED_NUMS = 3
  14. name = "AnonymityVisitedRecord"
  15.  
  16. def allow_request(self, request, view):
  17. """
  18. 进行是否可访问的逻辑判断
  19. :param request: drf's request
  20. :param view:
  21. :return: bool
  22. """
  23. IP_ADDR = request.META.get("REMOTE_ADDR", None)
  24. cur_visit_time = time.time()
  25. redis_conn = redis.Redis(connection_pool=REDIS_POOL)
  26. ips_record = redis_conn.hget(self.name, IP_ADDR)
  27. print(ips_record)
  28. if ips_record:
  29. history_visit_list = json.loads(ips_record.decode())
  30. while history_visit_list:
  31. # [120, 99, 40]
  32. # 最远一次访问时间B与当前时间A的时间差大于60秒,则删除B,如此循环
  33. if cur_visit_time - history_visit_list[-1] >= 60:
  34. history_visit_list.pop(-1)
  35. redis_conn.hset(self.name, IP_ADDR, json.dumps(history_visit_list))
  36. continue
  37. if len(history_visit_list) > self.MAX_PER_VISITED_NUMS:
  38. return False
  39. history_visit_list.insert(0, cur_visit_time)
  40. redis_conn.hset(self.name, IP_ADDR, json.dumps(history_visit_list))
  41. return True
  42.  
  43. new_ip_record = list()
  44. new_ip_record.insert(0, cur_visit_time)
  45. redis_conn.hset(self.name, IP_ADDR, json.dumps(new_ip_record))
  46. return True
  47.  
  48. def wait(self):
  49. """
  50. Optionally, return a recommended number of seconds to wait before
  51. the next request.
  52. """
  53. return None

  运行结果:

  

  内置的节流控制器

  1. class SimpleAnonymityUsertThrottle(SimpleRateThrottle):
  2. """
  3. 使用restframework内置的节流类,针对于的匿名用户的访问控制
  4. """
  5. scope = "Anonymity"
  6.  
  7. def get_cache_key(self, request, view):
  8. """
  9. 返回用户的唯一标识
  10. """
  11. # return request.META.get("REMOTE_ADDR")
  12. return self.get_ident(request)
  13.  
  14. class CertifiedUserThrottle(SimpleRateThrottle):
  15. """
  16. 对认证通过的用户进行节流控制
  17. """
  18. scope = "CertifiedUser"
  19.  
  20. def get_cache_key(self, request, view):
  21. """返回唯一用户标识"""
  22. return request.user.username

   scope参数依赖配置:

  1. REST_FRAMEWORK =
  2. {
  3. 'DEFAULT_THROTTLE_RATES': {
  4. 'Anonymity': '3/m',
  5. 'realUser': '6/m',
  6. },
  7. }

  

restframework之节流的更多相关文章

  1. Restframework的认证,权限,节流

    1.认证 流程:请求到达REST framework的时候,会对request进行二次封装,在封装的过程中会对客户端发送过来的request封装进认证,选择,解析等功能.request方法封装完成之后 ...

  2. django restframework

    一.django restframework 请求流程源码剖析 上面的认证一个流程是rest_framework的关于APIauth的认证流程,,这个流程试用权限.频率.版本.认证.这个四个组件都是通 ...

  3. RestFramework——API基本实现及dispatch基本源码剖析

    基于Django实现 在使用RestFramework之前我们先用Django自己实现以下API. API完全可以有我们基于Django自己开发,原理是给出一个接口(URL),前端向URL发送请求以获 ...

  4. Django rest framework(3)----节流

    目录 Django组件库之(一) APIView源码 Django restframework (1) ----认证 Django rest framework(2)----权限 Django res ...

  5. rest-framework源码解析和自定义组件----版本

    版本 url中通过GET传参自定义的版本 12345678910111213141516171819202122 from django.http import HttpResponsefrom dj ...

  6. 谈谈JS中的函数节流

    好吧,一直在秋招中,都没怎么写博客了...今天赶紧来补一补才行...我发现,在面试中,讲到函数节流好像可以加分,尽管这并不是特别高深的技术,下面就聊聊吧! ^_^ 备注:以下内容部分来自<Jav ...

  7. JavaScript 函数节流和函数去抖应用场景辨析

    概述 也是好久没更新 源码解读,看着房价蹭蹭暴涨,心里也是五味杂陈,对未来充满恐惧和迷茫 ...(敢问一句你们上岸了吗) 言归正传,今天要介绍的是 underscore 中两个重要的方法,函数节流和函 ...

  8. JS函数节流

    背景:在前端开发中,有时会为页面绑定resize事件,或为一个页面元素拖拽事件(其核心就是绑定mousemove)在一个正常操作中也有可能在一个短时间内触发非常多次事件绑定程序,而DOM操作是很消耗性 ...

  9. 你不知道的函数节流,提高你的JS性能!

    浏览器的DOM计算处理非常耗费CPU时间,霸占内存,这对我们的开发来说是非常不友好的,,比如IE浏览器的onresize事件就可能在用户稍微拖动一下窗口时计算上千次,甚至更高频率直接让浏览器崩溃... ...

随机推荐

  1. python中字符串的常用(部分)处理方法

    myStr = "hello world itcast and hahaitcastcpp" 方法的查询方法: help(myStr.replace) myStr.find(&qu ...

  2. K8S使用问题汇总

    1,报错如下 Warning: kubectl apply should be used on resource created by either kubectl create --save-con ...

  3. 面试总结之Data Science

    数据科学家面试如何准备? https://mp.weixin.qq.com/s/uFJ58az8WRyaXT2nibK02g 2020 年算法 / 数据分析面试数学考点梳理 https://mp.we ...

  4. 【vue】vue生命周期---精简易懂-----【XUEBIG】

    主要的生命周期函数分类:    - 创建期间的生命周期函数:(只会调用一次)       + beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属 ...

  5. SOFABoot&SOFATracer

    SOFABoot快速开始 SOFABoot介绍 SOFABoot 是蚂蚁金服开源的基于 Spring Boot 的研发框架,它在 Spring Boot 的基础上,提供了诸如 Readiness Ch ...

  6. 140款Android开源优秀项目源码

    BeautifulRefreshLayout-漂亮的美食下拉刷新 https://github.com/android-cjj/BeautifulRefreshLayout/tree/Beautifu ...

  7. 文件的内存读取 ,以及image图片(二进制)的读取

    #在python2.x中导入模块方法: from StringIO import String #在python2.x中它还有个孪生兄弟,运行速度比它快,用c实现的 from cStringIO im ...

  8. 在Ubuntu系统下连接远程服务器并传输文件

      原文链接:https://blog.csdn.net/u013250416/article/details/78075590 一. 连接远程Ubuntu服务器. 1. 打开命令行,输入 : sud ...

  9. Python入门篇-数据结构堆排序Heap Sort

    Python入门篇-数据结构堆排序Heap Sort 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.堆Heap 堆是一个完全二叉树 每个非叶子结点都要大于或者等于其左右孩子结点 ...

  10. .NET 使用 VLC 播放视频

    使用 VLC 播放监控有几个月了,现在是多个项目中都有用到.在使用的过程中也有一些细节供大家参考. 一.对 VLC 的了解 VLC 是一个开源的跨平台多媒体播放器及框架. VLC 官方出的有播放器.编 ...