Celery - 一个任务使用不同的参数调用较小的任务n次

时间:2015-01-21 19:05:18

标签: python flask celery

这里的基本思想是我想要一个celery任务调用一个方法n次,然后将一些较小的任务分组,每次都有不同的任务参数值。

第一个任务是每次调用一个方法的for循环,这反过来将group一些较小的任务。第一项任务将使用for循环的进度更新网页。

这样做的最佳方法是什么?

我尝试了几种方法,包括只是简单地延迟任务,但是我发现其中一个工作人员被锁定在第一个任务中,然后任何分配给它的小任务都没有得到处理。

我看不到它与chains一起使用。

我目前正在使用-Ofair标志来禁用预取,但这会使得获取结果时非常慢。

celeryTasks.py

@app.task()
def sweepSubnets(subnets):
    ...
    for subnet in subnets:
        print "subnet:{0}".format(subnet)
        sweep.runSweep(subnet, finished)
        finished += 1
        percent = (float((float(finished)/ float(noSubnets))) * 100)
        current_task.update_state(state='PROGRESS',
        meta={'process_percent': percent, 'subnet' : subnet})

    results = sweep.getResults()
    return results

@app.task()
def ping(ip):
    result = os.system("ping -W 1 -c 1 " + ip + " >/dev/null")
    return (ip,result)

sweep.py

def runSweep(self, subnet, number):
    if self.checkSubnet(subnet):
         print "Pinging {0}".format(subnet)
         netAdd, nodeAdd, poolSize = self.splitSubnet(subnet) 
         pingResults = self.queuePings(netAdd, nodeAdd, poolSize)
         activeResults = self.getActiveResults(pingResults)

        # Adds a tuple to the results list (subnet, active hosts, total hosts)
        self.results.append({"subnet":subnet, "activeNo":len(activeResults), "totalNo":len(pingResults), "active":activeResults, "total":pingResults, "number":number})
    else:
        self.results.append({"subnet":subnet, "activeNo":0, "totalNo":0, "active":[], "total":[], "number":number})

def queuePings(self, netAdd, nodeAdd, poolSize):
    from celeryTasks import ping

    ipToPing = []

    # For each address, puts the address on the job queue
    for i in range(1, poolSize):
        # Checks if the node address is over 254 and increases the network address if so
        nodeAdd = int(nodeAdd) + 1
        if int(nodeAdd) > 255:
            nodeAdd = 0
            netAdd = netAdd.split(".")
            netAdd = netAdd[0] + "." + netAdd[1] + "." + str(int(netAdd[2]) + 1)

        ipToPing.append("{0}.{1}".format(netAdd, nodeAdd))

    job = group(ping.s(ip) for ip in ipToPing)

    result = job.apply_async()
    print "Getting Results"
    return result.get()

1 个答案:

答案 0 :(得分:0)

对于任何可能遇到类似问题的人,我所做的是:

我像以前一样使用一个组运行所有ping,但是我保存了组的id,以便我可以返回它并稍后恢复结果,而不是让它们进入更大的任务。

job = group(ping.s(ip) for ip in ipToPing)
result = job.apply_async()
while not result.ready():
    time.sleep(0.1)
result.save()
return result.id

然后我有一个组ID的列表,我已经恢复并在更大的任务完成后继续工作。

for job in jobList:
     jobIDs = GroupResult.restore(job)
     results = jobIDs.get()