美文网首页
python基于生成器实现加权轮询

python基于生成器实现加权轮询

作者: 逐风细雨 | 来源:发表于2022-07-07 11:18 被阅读0次

  轮询就比较简单了,将句柄放在一个数组里面循环遍历就可以了。例如:[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

相关文章

网友评论

      本文标题:python基于生成器实现加权轮询

      本文链接:https://www.haomeiwen.com/subject/nrzubrtx.html