美文网首页
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