国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

腳本之家,腳本語言編程技術(shù)及教程分享平臺!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

香港云服务器
服務(wù)器之家 - 腳本之家 - Python - Django REST framework 限流功能的使用

Django REST framework 限流功能的使用

2021-12-08 00:16火腿蛋炒飯 Python

DRF常用功能的案例基本用法都有講解,關(guān)于限流(Throttling)這個功能其實(shí)在真實(shí)的業(yè)務(wù)場景中能真正用到的其實(shí)不算多。今天說這個話題其實(shí)一方面是討論功能,另一方面也是希望換個角度去審視我們的開發(fā)過程,希望大家可以在

正文開始

先說一個限流這個概念,最早接觸這個概念是在前端。真實(shí)的業(yè)務(wù)場景是在搜索框中輸入文字進(jìn)行搜索時,并不希望每輸一個字符都去調(diào)用后端接口,而是有停頓后才真正的調(diào)用接口。這個功能很有必要,一方面減少前端請求與渲染的壓力,同時減輕后端接口訪問的壓力。類似前端的功能的代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 前端函數(shù)限流示例
function throttle(fn, delay) {
    var timer;
    return function () {
        var _this = this;
        var args = arguments;
        if (timer) {
            return;
        }
        timer = setTimeout(function () {
            fn.apply(_this, args);
            timer = null;
        }, delay)
    }
}

但是后端的限流從目的上來說與前端類似,但是實(shí)現(xiàn)上會有所不同,讓我們看看 DRF 的限流。

1. DRF 中的限流

項(xiàng)目配置

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# demo/settings.py
 
REST_FRAMEWORK = {
    # ...
    'DEFAULT_THROTTLE_CLASSES': (
        'rest_framework.throttling.AnonRateThrottle',
        'rest_framework.throttling.UserRateThrottle',
         'rest_framework.throttling.ScopedRateThrottle',
    ),
    'DEFAULT_THROTTLE_RATES': {
        'anon': '10/day',
        'user': '2/day'
    },
}
 
# article/views.py
 
# 基于ViewSet的限流
class ArticleViewSet(viewsets.ModelViewSet, ExceptionMixin):
    """
    允許用戶查看或編輯的API路徑。
    """
    queryset = Article.objects.all()
    # 使用默認(rèn)的用戶限流
    throttle_classes = (UserRateThrottle,)
    serializer_class = ArticleSerializer
 
# 基于view的限流
@throttle_classes([UserRateThrottle])

因?yàn)槲遗渲玫挠脩裘刻熘荒苷埱髢纱?,所以在請求第三次之后就會給出 429 Too Many Requests的異常,具體的異常信息為下一次可用時間為 86398 秒后。

2. 限流進(jìn)階配置

上述演示的限流配置適用于對用戶的限流,比如我換個用戶繼續(xù)訪問,依然是有兩次的機(jī)會。

?
1
2
3
4
5
6
7
8
$ curl -H 'Accept: application/json; indent=4' -u root:root   http://127.0.0.1:8000/api/article/1/
{
    "id": 1,
    "creator": "admin",
    "tag": "現(xiàn)代詩",
    "title": "如果",
    "content": "今生今世 永不再將你想起\n除了\n除了在有些個\n因落淚而濕潤的夜里 如果\n如果你愿意"
}

分別介紹一下三種限流類

  • AnonRateThrottle 適用于任何用戶對接口訪問的限制
  • UserRateThrottle 適用于請求認(rèn)證結(jié)束后對接口訪問的限制
  • ScopedRateThrottle 適用于對多個接口訪問的限制

所以三種不同的類適用于不同的業(yè)務(wù)場景,具體使用根據(jù)不同的業(yè)務(wù)場景選擇,通過配置相對應(yīng) scope 的頻率的配置就可以達(dá)到預(yù)期的效果。

3. 限流思路分析

試想一下如果是你編碼實(shí)現(xiàn)這個需求應(yīng)該怎么實(shí)現(xiàn)?

其實(shí)這個功能不難,核心的參數(shù)就是 時間、次數(shù)、使用范圍,下面演示對函數(shù)調(diào)用次數(shù)的限制。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
from functools import wraps
 
TOTAL_RATE = 2
 
FUNC_SCOPE = ['test', 'test1']
 
 
def rate_count(func):
    func_num = {
        # 需要注意函數(shù)名不能重復(fù)
        func.__name__: 0
    }
 
    @wraps(func)
    def wrapper():
        if func.__name__ in FUNC_SCOPE:
            if func_num[func.__name__] >= TOTAL_RATE:
                raise Exception(f"{func.__name__}函數(shù)調(diào)用超過設(shè)定次數(shù)")
            result = func()
            func_num[func.__name__] += 1
            print(f" 函數(shù) {func.__name__} 調(diào)用次數(shù)為: {func_num[func.__name__]}")
            return result
        else:
            # 不在計數(shù)限制的函數(shù)不受限制
            return func()
 
    return wrapper
 
 
@rate_count
def test1():
    pass
 
 
@rate_count
def test2():
    print("test2")
    pass
 
 
if __name__ == "__main__":
    try:
        test2()
        test2()
        test1()
        test1()
        test1()
    except Exception as e:
        print(e)
    test2()
    test2()
    
"""
test2
test2
 函數(shù) test1 調(diào)用次數(shù)為: 1
 函數(shù) test1 調(diào)用次數(shù)為: 2
test1函數(shù)調(diào)用超過設(shè)定次數(shù)
test2
test2
"""

這里實(shí)現(xiàn)了對函數(shù)調(diào)用次數(shù)的監(jiān)控同時設(shè)置了能夠使用該功能的函數(shù)。當(dāng)函數(shù)調(diào)用次數(shù)超過設(shè)定閥值久拋出異常。只是這里沒有對時間做限制。

4. 源碼分析

剛才分析了如何實(shí)現(xiàn)對函數(shù)調(diào)用次數(shù)的限制,對于一個請求來說可能會復(fù)雜一點(diǎn),下面就看看 DRF 如何實(shí)現(xiàn)的:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class SimpleRateThrottle(BaseThrottle):
   
    # ......
    
    def allow_request(self, request, view):
        """
        Implement the check to see if the request should be throttled.
 
        On success calls `throttle_success`.
        On failure calls `throttle_failure`.
        """
        if self.rate is None:
            return True
 
        self.key = self.get_cache_key(request, view)
        if self.key is None:
            return True
 
        self.history = self.cache.get(self.key, [])
        self.now = self.timer()
 
        # 根據(jù)設(shè)置時間的限制改變請求次數(shù)的緩存
        while self.history and self.history[-1] <= self.now - self.duration:
            self.history.pop()
        # 核心邏輯就是這里判斷請求次數(shù)
        if len(self.history) >= self.num_requests:
            return self.throttle_failure()
        return self.throttle_success()
    
    # ......
    
class UserRateThrottle(SimpleRateThrottle):
    """
    Limits the rate of API calls that may be made by a given user.
 
    The user id will be used as a unique cache key if the user is
    authenticated.  For anonymous requests, the IP address of the request will
    be used.
    """
    scope = 'user'
 
    def get_cache_key(self, request, view):
        if request.user.is_authenticated:
            ident = request.user.pk
        else:
            # 考慮到用戶沒有認(rèn)證的情況 與 AnonRateThrottle 中 key 一致
            ident = self.get_ident(request)
        # 根據(jù)設(shè)置的范圍構(gòu)建緩存的 key
        return self.cache_format % {
            'scope': self.scope,
            'ident': ident
        }

綜上所述:

  • 核心的判斷邏輯依舊是緩存中獲取每個用戶調(diào)用次數(shù),根據(jù)范圍與時間判斷是否超過設(shè)置定的閥值。
  • 不同類型的限流,在緩存 key 的設(shè)計上會有區(qū)別,默認(rèn)的 key 為請求中REMOTE_ADDR。

5. 其它注意事項(xiàng)

  • 因?yàn)檫@里的實(shí)現(xiàn)用到緩存,所以需要注意在多實(shí)例部署的情況下需要配置統(tǒng)一的緩存服務(wù)(默認(rèn)的緩存為 Django 基于內(nèi)存實(shí)現(xiàn)的)。
  • 緩存服務(wù)的重啟可能會導(dǎo)致已有的計數(shù)清零,如果有較強(qiáng)的業(yè)務(wù)邏輯需要,還請自己實(shí)現(xiàn)限流的邏輯。
  • 如果是自定義的用戶表,需要重寫緩存中 get_cache_key 的邏輯。
  • 如果需要統(tǒng)計分析用戶被限流情況也是需要重新設(shè)計限流的邏輯。
  • 限流的邏輯在生產(chǎn)環(huán)境中慎用,因?yàn)闀拗朴脩羰褂卯a(chǎn)品,對用戶不夠友好。

參考資料

DRF 限流
Django 緩存

以上就是Django REST framework 限流功能的使用的詳細(xì)內(nèi)容,更多關(guān)于Django REST framework 限流功能的資料請關(guān)注服務(wù)器之家其它相關(guān)文章!

原文鏈接:https://juejin.cn/post/6976921186982690853

延伸 · 閱讀

精彩推薦
538
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 夜夜嗨av色一区二区不卡 | 国产精品毛片一区视频播不卡 | 国产成人免费视频 | 亚洲视频欧美视频 | 最新国产在线 | 欧美一级特黄aaaaaa大片在线观看 | 亚洲欧美观看 | 国产视频在线看 | 亚洲成人一级片 | 久久久日本 | 国产精品国产精品国产专区不片 | 国产日韩视频在线观看 | 91毛片网 | 国产九九九 | 日韩美女一级片 | 国产精品自拍视频 | 久久综合2019 | 北条麻妃一区二区免费播放 | 亚洲www视频 | 91在线网 | 日韩欧美一区二区三区免费观看 | 欧洲一区在线 | 成人午夜视频在线播放 | 蜜桃一区 | 黄色精品一区二区 | 久草在线免费资源 | 日韩色综合 | 国产久 | 久久精品国产一区二区三区不卡 | 精品成人佐山爱一区二区 | 亚洲视频在线观看视频 | 亚洲欧美中文字幕 | 我要看黄色一级大片 | 成人网av | 91精品在线看 | 日韩欧美一区二区中文字幕 | 欧美视频精品在线观看 | 婷婷激情五月 | 91视频精选 | 亚洲第一视频网站 | 91亚洲精品乱码久久久久久蜜桃 |