轮询就比较简单了,将句柄放在一个数组里面循环遍历就可以了。例如:[a,b,c,d] 一直轮询的结果是 a,b,c,d,a,b,c,d,。加权轮询,权重就是每个句柄被调用的次数不同,感觉有两种方式 如果在刚才那个数组中,假设b的权重是2,加权轮询2遍的效果有:a,b,b,c,d,a,b,b,c,d 和 a,b,c,d,b,a,b,c,d,b 第一种情况将连续遍历,权重高的执行完了以后再执行其它的。第二种情况是,每次都先完整遍历后再去执行权重高的。有点深度优先和广度优先的意思。个人感觉第二种分摊压力的效果更好,因此下面的代码实现的是第二种情况,但添加了按权重降序的操作。代码如下:
"""
加权轮询
"""
poll_dict = {
"A": 1,
"B": 2,
"C": 3,
"D": 4,
}
def poll_by_weights(poll_dict):
"""
加权轮询,返回一个生成器
调用举例 :
# 轮询20次 退出循环
poll_dict = {
"A": 1,
"B": 2,
"C": 3,
"D": 4,
}
for i, name in enumerate(poll_by_weights(poll_dict)):
print(i + 1, name)
if i + 1 == 20:
break
------打印------
1 D
2 C
3 B
4 A
5 D
6 C
7 B
8 D
9 C
10 D
11 D
12 C
13 B
14 A
15 D
16 C
17 B
18 D
19 C
20 D
"""
pool = []
funcs = []
def iter_func(name, weights):
"""
根据权重次数返回name的生成器
"""
for _ in range(weights):
yield name
# 轮回返回name 类似于 itertools.cycle()方法
def poll(iters):
while True:
yield from iters
# 将字典按权重排序,遍历添加生成器
for name, weights in sorted(poll_dict.items(), reverse=True, key=lambda i: i[1]):
funcs.append(iter_func(name, weights))
# 在pool中按权重添加一次循环
while funcs:
for func in funcs:
try:
pool.append(next(func))
except StopIteration:
funcs.remove(func)
return poll(pool)
if __name__ == "__main__":
# 轮询 20 次 退出循环
for i, name in enumerate(poll_by_weights(poll_dict)):
print(i + 1, name)
if i + 1 == 20:
break