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

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

{
"111.222.3.44": [, , , , ....],
"1.333.44.555": [, , , .....]
}

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

  

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

from django.utils.deprecation import MiddlewareMixin
from django.http.response import HttpResponse
import time MAX_PER_VISITED_NUMS = 3
VISITED_IP_THROTTLE = dict() class ThrottleMiddleware(MiddlewareMixin):
"""
节流中间件
VISITED_IP_THROTTLE每分钟最大访问次数
"""
def request_allowed(self, request):
"""自定义访问频率限制器, 用于限制匿名用户的访问频率限制"""
ip = request.META['REMOTE_ADDR']
cur_time = time.time()
# 如果ip在限制器中有记录
if ip in VISITED_IP_THROTTLE:
visiting_record = VISITED_IP_THROTTLE[ip] while visiting_record:
# 与列表中最后一次访问记录的时间差大于60秒, 移除最后一次记录并继续循环
if cur_time - 60 >= visiting_record[-1]:
visiting_record.pop(-1)
continue
# 访问记录列表超过最大访问次数
if len(visiting_record) >= MAX_PER_VISITED_NUMS:
return False
# 与列表中最后一次访问记录的时间差小于60秒
visiting_record.insert(0, cur_time)
return True # 无记录则新建该IP访问记录
VISITED_IP_THROTTLE[ip] = list()
VISITED_IP_THROTTLE[ip].insert(0, cur_time)
return True def process_request(self, request):
if self.request_allowed(request):
print(True)
return HttpResponse("True")
else:
print(False)
return HttpResponse("False")

  运行结果:

  

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

restframework版:

  自定义节流控制器

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

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

import redis
from vue_shop import settings REDIS_POOL = redis.ConnectionPool(**settings.REDIS_KWARGS)

  throttle.py

import time
import redis
from utils.redispool import REDIS_POOL
import json
from rest_framework.throttling import SimpleRateThrottle class AnonymityUserThrottle(object):
"""
自定义匿名用户节流器, 采用redis缓存访问记录
MAX_PER_VISITED_NUMS: 每分钟最高访问次数
name: 缓存(redis)中,hash类型的name
"""
MAX_PER_VISITED_NUMS = 3
name = "AnonymityVisitedRecord" def allow_request(self, request, view):
"""
进行是否可访问的逻辑判断
:param request: drf's request
:param view:
:return: bool
"""
IP_ADDR = request.META.get("REMOTE_ADDR", None)
cur_visit_time = time.time()
redis_conn = redis.Redis(connection_pool=REDIS_POOL)
ips_record = redis_conn.hget(self.name, IP_ADDR)
print(ips_record)
if ips_record:
history_visit_list = json.loads(ips_record.decode())
while history_visit_list:
# [120, 99, 40]
# 最远一次访问时间B与当前时间A的时间差大于60秒,则删除B,如此循环
if cur_visit_time - history_visit_list[-1] >= 60:
history_visit_list.pop(-1)
redis_conn.hset(self.name, IP_ADDR, json.dumps(history_visit_list))
continue
if len(history_visit_list) > self.MAX_PER_VISITED_NUMS:
return False
history_visit_list.insert(0, cur_visit_time)
redis_conn.hset(self.name, IP_ADDR, json.dumps(history_visit_list))
return True new_ip_record = list()
new_ip_record.insert(0, cur_visit_time)
redis_conn.hset(self.name, IP_ADDR, json.dumps(new_ip_record))
return True def wait(self):
"""
Optionally, return a recommended number of seconds to wait before
the next request.
"""
return None

  运行结果:

  

  内置的节流控制器

class SimpleAnonymityUsertThrottle(SimpleRateThrottle):
"""
使用restframework内置的节流类,针对于的匿名用户的访问控制
"""
scope = "Anonymity" def get_cache_key(self, request, view):
"""
返回用户的唯一标识
"""
# return request.META.get("REMOTE_ADDR")
return self.get_ident(request) class CertifiedUserThrottle(SimpleRateThrottle):
"""
对认证通过的用户进行节流控制
"""
scope = "CertifiedUser" def get_cache_key(self, request, view):
"""返回唯一用户标识"""
return request.user.username

   scope参数依赖配置:

REST_FRAMEWORK =
{
'DEFAULT_THROTTLE_RATES': {
'Anonymity': '3/m',
'realUser': '6/m',
},
}

  

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. 2019 快乐阳光java面试笔试题 (含面试题解析)

    本人3年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.快乐阳光等公司offer,岗位是Java后端开发,最终选择去了快乐阳光. 面试了很多家公司,感觉大部分公司考察的点 ...

  2. python pip安装解决方法

    一招解决python pip install 安装库失败   PIP是python强大的安装利器,但是我们经常遇到安装库失败的问题,以下本人觉得最有效的解决方法: 1.打开 https://www.l ...

  3. div中的“内容”水平垂直居中

    1. div高度自适应的情况 div在不设置高度的时候,会被里面的内容撑开,内容自动填充在div中,无论是一行内容还是多行内容,此时不需要设置垂直居中,内容自动在中间的, 想要看的更直观些,只需要加上 ...

  4. 82.使用vue后怎么针对搜索引擎做SEO优化?

    什么是SEO 搜索引擎优化(Search engine optimization,简称SEO),指为了提升网页在搜索引擎自然搜索结果中(非商业性推广结果)的收录数量以及排序位置而做的优化行为,是为了从 ...

  5. Mybatis 中的转义字符及常用查询

    转译符 1.特殊字符转译 < < 小于 > > 大于 & & 与 ' ’ 单引号 " " 双引号 需要注意的是分号是必不可少的. 比如 a ...

  6. curl请求https资源的时候出现400

    在nginx上配置了一个新的域名, 习惯性地用curl请求看看有没有配置错误 因为是https的, 所以 $curl 'https://test.test.com/' -x 127.0.0.1:443 ...

  7. Gerrit代码审计系统实战-Gerrit 2.15.14版本快速搭建

    Gerrit代码审计系统实战-Gerrit 2.15.14版本快速搭建  作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Gerrit版本选择 1>.查看Gerrit官网 ...

  8. ExecutorService java多线程分割list运行

    调用方法 int threadNum = 7; while(true) { List<FaceAnalyseImage> list = faceAnalyseImageMapper.sel ...

  9. storm整合kafka storm-kafka-client

    pom.xml-注意jar-log4j---------------------<dependencies> <dependency> <groupId>org.a ...

  10. Please, another Queries on Array?(Codeforces Round #538 (Div. 2)F+线段树+欧拉函数+bitset)

    题目链接 传送门 题面 思路 设\(x=\prod\limits_{i=l}^{r}a_i\)=\(\prod\limits_{i=1}^{n}p_i^{c_i}\) 由欧拉函数是积性函数得: \[ ...