一. 什么是限流
限流(Throttle)就是限制客户端对API 的调用频率,是API开发者必须要考虑的因素。比如个别客户端(比如爬虫程序)短时间发起大量请求,超过了服务器能够处理的能力,将会影响其它用户的正常使用。又或者某个接口占用数据库资源比较多,如果同一时间该接口被大量调用,服务器可能会陷入僵死状态。为了保证API服务的稳定性,并防止接口受到恶意用户的攻击,我们必须要对我们的API服务进行限流。
DRF中限制对API的调用频率非常简便,它为我们主要提供了3个可插拔使用的限流类,分别是AnonRateThrottle, UserRateThrottle和ScopeRateThrottle类。
二. 设置自定义限流
定义throttle类
from rest_framework import throttling
from rest_framework.throttling import UserRateThrottleclass CustomScopeThrottle(throttling.ScopedRateThrottle):# scope = 'anon'rate = '1/second'# scope = 'll'# THROTTLE_RATES = {"anon": "1/s"}class CustomUserRateThrottle(UserRateThrottle):rate= '1/second'
定义setting
REST_FRAMEWORK = {# 'DEFAULT_THROTTLE_CLASSES': [# 'testthrottle.throttling.GetUserRateThrottle'# ],'DEFAULT_THROTTLE_RATES': {'ll': '1/second',}
}
三. 在API view中给特定接口添加限流
from rest_framework.viewsets import GenericViewSet
from rest_framework.decorators import throttle_classes
from rest_framework.response import Response
from rest_framework import status
from testthrottle.models import EllisTest
from testthrottle.serilizerModel.ellisTest import EllisTestSerilizer
from testthrottle.throttling import CustomScopeThrottle,CustomUserRateThrottleclass EllisTestView(GenericViewSet):serializer_class = EllisTestSerilizerqueryset = EllisTest.objects.all()throttle_scope = "ll"# throttle_classes = [CustomUserRateThrottle]# 通过这个函数实现给不同的API 添加不同的限流def get_throttles(self):if self.action == 'create':throttle_classes = [CustomUserRateThrottle]else:# throttle_classes = [] # No throttle for other actionsthrottle_classes = [CustomScopeThrottle] # No throttle for other actionsreturn [throttle() for throttle in throttle_classes]def list(self, request, *args, **kwargs):queryset = self.filter_queryset(self.get_queryset())page = self.paginate_queryset(queryset)if page is not None:serializer = self.get_serializer(page, many=True)return self.get_paginated_response(serializer.data)serializer = self.get_serializer(queryset, many=True)return Response(serializer.data)# @throttle_classes([CustomUserRateThrottle])def create(self, request):serializer = self.get_serializer(data=request.data)serializer.is_valid(raise_exception=True)serializer.save()return Response(serializer.data, status=status.HTTP_201_CREATED)
https://www.django-rest-framework.org/api-guide/throttling/
https://pythondjango.cn/django/rest-framework/10-throttling/
https://stackoverflow.com/questions/69068513/how-to-apply-throttling-just-to-create-action-in-drf-viewsets
https://stackoverflow.com/questions/32932357/custom-throttling-response-in-django-rest-framework
https://medium.com/analytics-vidhya/throttling-requests-with-django-rest-framework-for-different-http-methods-3ab0461044c
demo源码