限频一般反向代理都会有自带的一些设置参数,但是入口复杂的情况下,想做分布式限频,仅仅使用分布式反向代理的参数是完全不够用的,这里使用redis 比较好实现,为啥呢?还不是基于redis 的原子性!
使用redis 实现分布式限频,如何做呢?一个是原子计数,一个是按时间戳地板除。
下面是一个简单的python 封装,用于演示基本原理:
#encoding=utf8
import redis
import time
import threading
host = "127.0.0.1"
port = "6379"
password = "123123"
db = 0
pool = redis.ConnectionPool(host=host, port=port, password=password, db=db)
rd = redis.StrictRedis(connection_pool=pool)
class Counter(object):
def __init__(self, key, delta = 1):
self.redis_client = rd
self.delta = delta
self.key = key
def increment(self):
t = int(time.time())
sign = t / self.delta
redis_key = self.key + '_' + str(sign)
counter = self.redis_client.incr(redis_key)
self.redis_client.expire(redis_key, 10 * self.delta) # 控制时间,防止爆掉内存
return counter
def add_task(item):
c = Counter("test", 60) # key 为test,计数周期为60s
threshold = 100
for i in range(1000):
time.sleep(0.2)
x = c.increment()
if x > threshold:
print "over limit"
else:
print "thread:%s ,itme:%s" % (item, x)
if __name__ == '__main__':
t1 = threading.Thread(target=add_task, args=(1,))
t2 = threading.Thread(target=add_task, args=(2,))
t1.start()
t2.start()
t1.join()
t2.join()
封装的要点是对当前时间地板除,参数key 为要计数的key,delta 就是计数周期,redis 只负责计数,由业务逻辑负责阈值判断。