调用配额

之前一篇文章到通过access key调用API的方式,这种调用方式难免会碰到一个问题,那就是,如果用户不挺地高频率调用API,服务器是否会过载,如果过载了,是否会影响内部服务。

有个做法,就是给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,则拒绝服务。

使用配额的目的是:对于一些高级客户,可以提高配额,以提高体验。如果是内部服务调用,那么这个配额,可以提高些。

请求队列

可以提供不同优先级的队列,针对不同的请求的优先级,把他们放到不同的队列里,先处理优先级高的队列,然后优先级更低的队列。(可以用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个请求,优先级低的队列则不会被饿死。

参考:《弹力设计之“限流设计”》陈皓


yoop
10 声望2 粉丝

我要/一步一步往上爬