限流處理

調用配額

以前一篇文章到經過access key調用API的方式,這種調用方式不免會碰到一個問題,那就是,若是用戶不挺地高頻率調用API,服務器是否會過載,若是過載了,是否會影響內部服務。redis

有個作法,就是給access key設置調用配額(limit,duration),這個配額指的是在某個時間段內(duration),調用的次數不能超過limit指定的數額。若是超過了,則拒絕服務。這種能夠經過緩存來實現,利用緩存的expire時間,而且維持一個計數器,每當調用一次,則計數器減一。數據庫

def init(access_key, limit, duration):
    memcache.set(key=access_key, val=limit, expire=duration)

def handle(access_key):
    count = memcache.get(key=access_key)
    if count == 0:
        return 'DENY'
    memcache.decr(key=access_key)
    return 'OK'

前面init函數作初始化,後面handle函數對請求作判斷,每掉用一次,就把計數器減一;若是當前計數器裏的值爲0,則拒絕服務。segmentfault

使用配額的目的是:對於一些高級客戶,能夠提升配額,以提升體驗。若是是內部服務調用,那麼這個配額,能夠提升些。後端

請求隊列

能夠提供不一樣優先級的隊列,針對不一樣的請求的優先級,把他們放到不一樣的隊列裏,先處理優先級高的隊列,而後優先級更低的隊列。(能夠用redis裏的有序隊列來實現?)若是有針對這個隊列的處理服務,這個服務可以合併請求,那麼則能夠減輕後端服務的負載。緩存

student:
{
    'name': 'ABC',
    'age': 30,
}
requests:
[0] {'action': 'ModifyItems', 'name': 'xiao ming'}
[1] {'action': 'ModifyItems', 'age': 26}

After handled
new request:
[0] {'action': 'ModifyItems', 'age': 26, 'name': 'xiao ming'}

如上,若是數據庫裏有一個對象student,經過請求ModifyItems能夠修改student屬性,請求隊列如requests所示,第一個請求修改了name,第二個請求修改了age,這個時候,能夠把這2個請求合併成一個,這個新的請求跟兩個請求最終達到的小姑都是同樣的,因此是可行的。服務器

若是一直優先處理高優先級的隊列,等這個隊列的請求處理完了,再處理優先級低一級的請求,那麼優先級低的隊列可能要等好久才能處理。函數

這個時候,能夠根據權重來處理,若是優先級隊列有2個,他們優先級分別是:2和1,數值越高,表示優先級更高,那麼根據優先級權重,服務器先處理優先級高的隊列裏的2個請求,而後再去處理優先級低隊列裏的1個請求,優先級低的隊列則不會被餓死。設計

參考:《彈力設計之「限流設計」》陳皓code

相關文章
相關標籤/搜索