DRF内蔵限流ユニットのカスタム限流機構

5955 ワード

DRFは周波数セットThrottlingを内蔵しています.
サーバの圧力を軽減するために、インターフェースへのアクセス頻度を制限することができます.
一般的には有料購入回数、投票などの場面で使われます.
オプションの制限レベル
1)AnonRateThrottle
  • は、すべての匿名未認証ユーザを制限し、IPを使用してユーザを区別する.
  • は、DEFAULT_THROTTLE_RATES['anon']を使用して、周波数帯域
  • を設定する.
    2)UserRateThrottle
  • は認証ユーザを制限し、User idを用いて区別する.
  • は、DEFAULT_THROTTLE_RATES['user']を使用して、周波数帯域
  • を設定する.
    グローバル設定
    全体構成は、構成ファイルにおいてDEFAULT_THROTTLE_CLASSESおよびDEFAULT_THROTTLE_RATESを使用して行うことができる.
    REST_FRAMEWORK = {
        
        #       
        'DEFAULT_THROTTLE_CLASSES': (
            
            #            ,  IP    
            'rest_framework.throttling.AnonRateThrottle', 
            
            #           ,  User_id    
            'rest_framework.throttling.UserRateThrottle' 
        ),
        
        #       
        'DEFAULT_THROTTLE_RATES': {
            
            #                     3 
            'anon': '3/m',
            
            #                      10 
            'user': '10/m'
        }
    }
    
    DEFAULT_THROTTLE_RATESは、secondminutehour、またはdayを使用して周期を指定しても良い.
      :
    {'s': 1, 'm': 60, 'h': 3600, 'd': 86400} m    ,   m,    minute
    
    ローカル設定
    具体的なビューにおいて、throttle_classess属性によって構成されてもよい.
    from rest_framework.views import APIView
    from rest_framework.throttling import AnonRateThrottle
    from rest_framework.throttling import UserRateThrottle
    
    
    class ExampleView1(APIView):
        
        #                      3 
        #                      10 
        throttle_classes = (AnonRateThrottle, UserRateThrottle)
        ...
        
        
    # settings.py                              
    REST_FRAMEWORK = {
        
        #       
        'DEFAULT_THROTTLE_RATES': {
            
            #                     3 
            'anon': '3/m',
            
            #                      10 
            'user': '10/m'
        }
    }
    
    ScopedRateThrottle DRFはまた、異なるインターフェースに対して異なるアクセス頻度をカスタマイズすることができる制限ストリームレベルを提供する.
    settings.pyプロファイルには以下のように構成されています.
    REST_FRAMEWORK = {
        
        'DEFAULT_THROTTLE_CLASSES': (
            'rest_framework.throttling.ScopedRateThrottle',
        ),
        
        'DEFAULT_THROTTLE_RATES': {
            
            #          :throttle_scope = 'contacts',             10 
            'contacts': '10/m',
            
            #          :throttle_scope = 'uploads',             5 
            'uploads': '5/m'
            
            ...
            ...
            ...
        }
    }
    
    たとえば:
    from rest_framework.views import APIView
    
    
    class ContactListView(APIView):
        
        #                  10 
        throttle_scope = 'contacts'
        ...
    
    class ContactDetailView(APIView):
        #                  10 
        throttle_scope = 'contacts'
        ...
    
    class UploadView(APIView):
        #                  5 
        throttle_scope = 'uploads'
        ...
    
    
    カスタムストリーム
    フロー制限コンポーネントは周波数コンポーネントとも呼ばれ、クライアントを制御するためにAPIの要求周波数、例えば1分間に3回アクセスし、1分間に3回以上の場合はクライアントを制限する.
    現在APIへのアクセスが30 s以内で3回を超えてはいけないとしたら、どうやって実現すればいいですか?
    カスタムストリーム制限コンポーネント
    VISIT_RECORD = {} #      ,        
    class VisitThrottle(object):
    
        def __init__(self):     #  await        
            self.history = None
    
        def allow_request(self,request,view):
            #    ip       
            remote_addr = request.META.get('REMOTE_ADDR')
    
            #          
            ctime = time.time()
            #          ,      ,    True,      
             if remote_addr not in VISIT_RECORD:
                 VISIT_RECORD[remote_addr] = [ctime,]
                 return True
    
            #          ,       
            history = VISIT_RECORD.get(remote_addr)
    
            self.history = history
            #                             ,   60s ,    ,
            #             
            while history and history[-1] < ctime - 30:
                history.pop()
            #                      ,               
    
            if len(history) < 3:
                history.insert(0,ctime)
                return True
    
        def wait(self):
            #            
            ctime = time.time()
            return 60 - (ctime - self.history[-1])
    
    対応するビューで設定します.
    class BookView(ListAPIView):
        throttle_classes = [VisitThrottle,] #      
        queryset = models.Book.objects.all()
        serializer_class = BookModelSerializer
    
    限流の原理
    rest frame ewarkフレームでは、クラスのリストとして定義されています.グローバル構成またはローカル構成だけが必要です.上記のフロー制限の原理は、クライアントの一意の表示をキーとして、アクセスの瞬間に形成されるリストを値として形成した辞書であり、辞書を介して動作する.
    {
        http://127.0.0.1:8020/ :[11:43:30,11:42:22,11:42:20,11:42:09]
    }
    
    上の辞書に示すように、後の訪問時間はリストの一番左に挿入され、現在の訪問時間は11:43:30である.最初の訪問時間と11:42:09と差をつけて、規定時間30 sと比較し、30秒以内でない場合は一番左の記録を除去し、同じようにwhileを使って順番に比較します.最後に決められた時間範囲での記録:
    {
      http://127.0.0.1:8020/ :[11:43:30,]
    }
    
    訪問回数を再計算します.つまりリストの数です.明らかにリストの数が3より小さい場合はアクセスを続けてもいいです.そうでなければいけません.
    上記ではグローバル変数を使って記録することもできます.もちろんキャッシュを使って記録することもできます.djangoのキャッシュAPI、from django.com re.cache import cacheを使用して、このAPIを導入したらsetとget方法を使用して、cacheに格納されているオブジェクトを設定して取得して、グローバル変数を操作して置換するだけでいいです.
    from django.core.cache import cache as default_cache
    import time
    
    class VisitThrottle(object):
    
        cache = default_cache
         
        def allow_request(self,request,view):
             ...
             ...    
            #          ,      ,    True,      
    
            if not self.cache.get(remote_addr):
                self.cache.set(remote_addr,[ctime,])
                return True
            #          ,       
    
            history = self.cache.get(remote_addr)
            self.history = history
            ...
            ...
    
    rest frame ewarkの限流コンポーネントはcacheに基づいて完成した.  
    上記のwait方法では、このAPIにどれぐらいの時間がかかりますか?
    {
        "detail": "Request was throttled. Expected available in 56 seconds."
    }