rest_framework throttling 限流

rest_framework throttling 限流


1. 限流

限流设置也是List。

在执行view前,限流列表中的每个限流器都会执行,任意一次检查未通过,抛出fexceptions.Throttled exception,后续操作终止。

1.1. 配置

  
# 全局配置  
REST_FRAMEWORK = {  
    'DEFAULT_THROTTLE_CLASSES': [  
        'rest_framework.throttling.AnonRateThrottle',  
        'rest_framework.throttling.UserRateThrottle'  
    ],  
    'DEFAULT_THROTTLE_RATES': {  
        'anon': '100/day',  
        'user': '1000/day'  
    }  
}  

自定义限流类配置

  
from rest_framework.response import Response  
from rest_framework.throttling import UserRateThrottle  
from rest_framework.views import APIView  

class ExampleView(APIView):  
    throttle_classes = [UserRateThrottle]  

    def get(self, request, format=None):  
        content = {  
            'status': 'request was permitted'  
        }  
        return Response(content)  


Or, if you're using the @api_view decorator with function based views.  

@api_view(['GET'])  
@throttle_classes([UserRateThrottle])  
def example_view(request, format=None):  
    content = {  
        'status': 'request was permitted'  
    }  
    return Response(content)  

1.2. 客户端识别 How clients are identified

客户端识别基于 X-Forwarded-For HTTP header and REMOTE_ADDR WSGI
优先使用前者,如果前者不存在,使用后者。
NUM_PROXIES用于指定使用哪一个ip,非0使用X-Forwarded-For最后一项,否则使用REMOTE_ADDR

1.3. 内置限流类

AnonRateThrottle
限制未认证的用户。识别是基于请求的IP。

UserRateThrottle
基于用户限制全局请求频率。用户标识用于生成一个唯一的密钥来加以限制。未登录用户基于ip进行限制。

ScopedRateThrottle
用于限制对API特定部分的访问。只有当正在访问的视图包含 .throttle_scope 属性时才会应用此限制。

2. 案例

自定义限流类实现30秒内限制访问3次

  
# throttle.py  
from rest_framework.throttling import BaseThrottle  
import time  

VISIT_RECORD = {}  
# 限流类  
class VisitThrottle(BaseThrottle):  
    def __init__(self):  
        super().__init__()  
        self.history = None  

    def allow_request(self, request, view):  
        remote_addr = request.META.get("REMOTE_ADDR")  

        ctime = time.time()  

        history = VISIT_RECORD.get(remote_addr)  
        if history is None:  
            VISIT_RECORD[remote_addr] = [ctime,]  
            return True  

        self.history = history  
        while history and history[-1] < ctime -30:  
            history.pop()  

        if len(history) < 3:  
            history.insert(0, ctime)  
            return True  
        return False  

    def wait(self):  
        ctime = time.time()  
        return 30 - (ctime - self.history[-1])  

# APIview  
from .throtlle import VisitThrottle  
class TestModelObjectView(generics.RetrieveAPIView):  
    queryset = TestModels.objects.all()  
    serializer_class = TestModelsSerializer  
    permission_classes = [permissions.AllowAny]  
    throttle_classes = [VisitThrottle,]  
posted @ 2020-11-19 00:09  木林森__𣛧  阅读(180)  评论(0)    收藏  举报