使用concurrent.futures异步调用pyspark函数

时间:2018-01-17 13:18:05

标签: python asynchronous pyspark future concurrent.futures

我正在尝试调用使用pyspark rdd对象方法的python函数,并且非常耗时阻塞我的应用程序。 我需要以异步方式编写它,以便我的应用程序不会被阻止。 这是我想要做的实际事物的缩影版。

from concurrent.futures import Future
from pyspark import SparkContext

sc = SparkContext()

def add(a, b):
    f = Future()
    c = a + b
    d = a*b
    t = (c,d)
    rdd = sc.parallelize([t])
    f.set_result(rdd)
    # return rdd

if __name__ == '__main__':

    f1 = add(90,8)
    f2 = add(8, 89)

    while (not f1.done()) and (not f2.done()):
        pass

    print(f1.result())
    print(f2.result())

我知道上面的代码不会立即生效。如何修改它,以便它可以工作?

2 个答案:

答案 0 :(得分:0)

我认为你应该在函数中返回f:

def add(a, b):
    f = Future()
    c = a + b
    d = a*b
    t = (c,d)
    rdd = sc.parallelize([t])
    f.set_result(rdd)
    return f

但不要忘记你的rdd是懒惰的。没有动作,它不应该消耗那么多时间。

答案 1 :(得分:0)

使用线程模块。我刚刚完成了一个类似的项目,它就像一个魅力。

import threading

_newThread = threading.Thread(target=<yourfunctionhere>, args=(<yourfunctionargshere>), name=<nameyourthreadhere>)
_newThread.start()

以上是核心功能。下面是一个更详细的排队作业示例,将该作业(线程)添加到一行以等待轮到(使用thread.join()方法),并返回一个具有行数(线程)的响应用于处理。

_jobId = uuid.uuid4().hex
_currentjobs = []
for t in threading.enumerate():
    if t._Thread__name in [<yourthreadnamehere>,<yourthreadnamehere>]:
        if t.isAlive():
            _currentjobs.append(t)

_newThread = threading.Thread(target=<yourfunctionhere>, args=(<yourfunctionargshere>, _currentjobs), name=<yourthreadnamehere>)
_newThread.start()

if not _currentjobs.__len__() > 0:
    return app.make_response('Job Id: ' + _jobId), 200
else:
    return app.make_response('Job Id: ' + _jobId + '\n' + 'There are '+ str(_currentjobs.__len__()) + ' ahead of you, and so please be patient.'), 200

并将_currentJobs作为参数传递给您的函数,此代码在开头执行:

_currentJobs = currentJobs
for j in _currentJobs:
    j.join()

重要的是要注意,您的函数应包含创建SparkContext的完整逻辑,RDD /数据帧上的惰性工作,以及您希望群集执行的任何实际工作(.collect(),提交到数据库等等) 。),因为这个线程是异步的,并且有自己的范围,传输回主线程会很复杂。