结构:仅为单个功能(非任务)设置“气泡大小”(速率限制)

时间:2015-03-26 20:16:37

标签: python multithreading fabric

假设我有以下Fabric fabfile:

import time

def part1():
    print 'doing part 1'
    time.sleep(1)

def part2():
    print 'doing part 2'
    time.sleep(10)

def bothparts():
    part1()
    part2()

我希望能够以自然语义运行fab -H a,b,c,d bothparts(串行)和fab -P -H a,b,c,d bothparts(并行)。串行执行需要44秒;并行执行需要11秒。

然而,这就是皱纹。在我的真实代码中,part1向远程服务器发出查询,该服务器对传入的查询进行速率限制(to,let'比方说,一次两个)。因此,fab -P -H a,b,c,d bothparts在主机ab上运行完成,但在cd上爆炸。

我正在寻找一种方法来限制"限速"与part1的并发呼叫数。

我知道"bubble size",但我不能接受fab -P -z 2 -H a,b,c,d bothparts作为答案,因为这需要22秒才能完成。我正在寻找一种方法来实现只需12秒的答案(part1a,b为1秒,part1c,d为1秒a,b继续开始part2,所有四项任务并行运行9秒,最后c,d完成part2时间为1秒。

我浪费了很多时间尝试使用" @ synchronized"装饰器(使用threading.Semaphore,类似于this blog post),但是当它不起作用时,我做了一些研究,并意识到Fabric使用多个进程并行!如果我想解决问题,我需要那些多个进程互相交流。


我也不能接受手动解决方案fab -P -z 2 -H a,b,c,d part1 && fab -P -H a,b,c,d part2;基本上我正在寻找最简单的Fabric代码,可以将其包装成一个简单的bothparts任务。我怀疑在execute内有bothparts的解决方案,但我的 理想 解决方案将是{{{}内部的本地更改1}}(因为我不想因为这个实现细节而不得不重写part1的所有调用者)。

1 个答案:

答案 0 :(得分:0)

这是一个“技术上正确”的解决方案,不太令人满意,因为它不可组合:

import time
from fabric.decorators import parallel, runs_once

@parallel(pool_size=2)
def part1():
    print 'doing part 1'
    time.sleep(1)

@parallel
def part2():
    print 'doing part 2'
    time.sleep(10)

@runs_once
def bothparts():
    execute(part1)
    execute(part2)

$ fab -H a,b,c,d bothparts

这个解决方案的哲学问题是它似乎没有很好地构成;我非常不清楚如何从其他任务调用part1part2,或者如何从其他任务调用bothparts

此外,这个bothparts超级任务需要知道其子任务的奇怪行为。请注意,如果您移除@runs_once上的bothparts装饰,则最终会在每台计算机上运行part1四次 ,然后再运行part2四次每台机器,这是不正确的。