一. 什么是限流
限流(Throttle)就是限制客户端对API 的调用频率,是API开发者必须要考虑的因素。比如个别客户端(比如爬虫程序)短时间发起大量请求,超过了服务器能够处理的能力,将会影响其它用户的正常使用。又或者某个接口占用数据库资源比较多,如果同一时间该接口被大量调用,服务器可能会陷入僵死状态。为了保证API服务的稳定性,并防止接口受到恶意用户的攻击,我们必须要对我们的API服务进行限流。
DRF中限制对API的调用频率非常简便,它为我们主要提供了3个可插拔使用的限流类,分别是AnonRateThrottle, UserRateThrottle和ScopeRateThrottle类。
二. 设置自定义限流
定义throttle类
from rest_framework import throttling
from rest_framework.throttling import UserRateThrottle
class 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,CustomUserRateThrottle
class EllisTestView(GenericViewSet):
serializer_class = EllisTestSerilizer
queryset = 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 actions
throttle_classes = [CustomScopeThrottle] # No throttle for other actions
return [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/32932357/custom-throttling-response-in-django-rest-framework