说起RR (round robin)平均轮询,我想大家都知道的,常见的负载均衡服务器,比如 nginx、haproxy、lvs 都是支持轮询调度的… 公司有几个高人现着手开发公网爬虫的架构,分布式的http代理。 我这边会大量的调用他的http代理,这就用到了轮询,但是有个问题是 我的程序架构是 多进程加多线程。不能很好的做好统一和线程安全的轮询获取方式。 统一轮询带来的好处,可以让单个ip被访问的频次最低,这样 一个大轮询下来,最初的代理ip是鲜活的。 如果你的程序是把所有的代理做随机,很有可能在短时间内,用同一个代理出去,流量大的话,很有可能被封堵ip。
辛辛苦苦写得文章总是跑到别的网站上,标记下博客的链接.. http://xiaorui.cc/?p=1385 http://xiaorui.cc
实现RR轮询的方式还是很多的,比如最简单的 每次pop一个数据,就马上回塞到队列里面,总之保证队列是满的。 另外说下,这个时候列表推荐用双端队列deque,性能的损耗要比普通的list低的多。 我这里用的是 itertools里面的cycle功能。 创建一个迭代器,然后不停的顺序调度。 一般来说用了cycle之后是无停止的迭代器,So 用yield来做适当的停顿,在用next() 来进行下个数据。
我已经把代码推到了github上, 功能虽然很小,但是有需要的朋友可以用用。 后期我会用tornado开发一个针对round robin轮询方案 。 代码如下…. …
https://github.com/rfyiamcool/py_round_robin
大家也可以直接pypi上下载,安装方式如下…..
pip install py_round_robind
#!/usr/bin/python #blog: xiaorui.cc #author: rfyiamcool@163.com from itertools import * class Round_Robin(): def __init__(self,data): self.data = data self.data_rr = self.get_item() def cycle(self,iterable): saved = [] for element in iterable: yield element saved.append(element) while saved: for element in saved: yield element def get_item(self): count = 0 for item in self.cycle(self.data): count += 1 yield (count, item) def get_next(self): return self.data_rr.next() if __name__ == "__main__": rr_obj = Round_Robin(['a','b','c']) for i in range(50): print rr_obj.get_next()
这是py_round_robin使用的方法,代码本身就很简单,用起来也相当的简单。 我这边已经在多线程下测试了,是可以保证线程安全的,不会出现数据乱跳的情况. ……
from py_round_robin import Round_Robin rr_obj = Round_Robin(['a','b','c']) for i in range(50): print rr_obj.get_next()测试的结果,会发现他的结果是我们想要的….
[ruifengyun@spiderman rr (master ✗)]$ python Round_Robin.py (1, 'a') (2, 'b') (3, 'c') (4, 'a') (5, 'b') (6, 'c') (7, 'a') (8, 'b') (9, 'c') (10, 'a') (11, 'b') (12, 'c') (13, 'a') (14, 'b') (15, 'c') (16, 'a') (17, 'b') (18, 'c') (19, 'a') (20, 'b') (21, 'c') (22, 'a') (23, 'b') (24, 'c') (25, 'a') (26, 'b') (27, 'c') (28, 'a')
如果有更有想实现加权 weight的算法,那么最简单的方式就是构造函数的时候,多加入一个元素,这样会提供他的命中的几率…. ….
so great !!!!!
好精细的模块哈。
你在黑我么 ?