龙卷风ThreadPoolExecutor在产生结果时延迟请求

时间:2019-01-28 16:05:02

标签: python tornado threadpoolexecutor

系统规格  -MacOS 10.13.6  -Python 3.7.0  -龙卷风5.1.1

我想使用ThreadPoolExecutor运行阻止功能 在提供RESTful服务的Tornado实例中。

只要我不试图产生执行函数返回的结果,ThreadPool就可以按预期工作并并行产生四个工作线程(请参见下面的代码和控制台日志)。

ThreadPoolExecutor没有产生结果

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.4

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    menuBar: MenuBar {
        Menu {
            title: qsTr("&File")
            Action { text: qsTr("&New...") }
            Action { text: qsTr("&Open...") }
            Action { text: qsTr("&Save") }
            Action { text: qsTr("Save &As...") }
            MenuSeparator { }
            Action { text: qsTr("&Quit") }
        }
        Menu {
            title: qsTr("&Edit")
            Action { text: qsTr("Cu&t") }
            Action { text: qsTr("&Copy") }
            Action { text: qsTr("&Paste") }
        }
        Menu {
            title: qsTr("&Help")
            Action { text: qsTr("&About") }
        }
    }
}

控制台输出

import time
import tornado.web
from tornado.concurrent import run_on_executor
from concurrent.futures import ThreadPoolExecutor
from tornado.ioloop import IOLoop

MAX_WORKERS = 4
i = 0

class Handler(tornado.web.RequestHandler):
    executor = ThreadPoolExecutor(max_workers=MAX_WORKERS)

    @run_on_executor
    def background_task(self, i):
        print("going sleep %s" % (i))
        time.sleep(10);
        print("waking up from sleep %s" % (i))
        return str(i)

    @tornado.gen.coroutine
    def get(self):
        global i
        i+=1
        self.background_task(i)


def make_app():
    return tornado.web.Application([
        (r"/", Handler),
    ])


if __name__ == "__main__":
    app = make_app()
    app.listen(8000, '0.0.0.0')
    IOLoop.current().start()        

可以看出,有四个并行的工作程序正在运行,并且一旦完成,就会执行一个排队的函数。

但是,当我尝试使用协程产生返回函数时,我遇到了一些问题。虽然它不能完全阻止IoLoop,但会延迟而没有清晰的模式。

更改后的代码:ThreadPoolExecutor现在产生结果

going sleep 1
going sleep 2
going sleep 3
going sleep 4
waking up from sleep 1
going sleep 5
waking up from sleep 2
going sleep 6
waking up from sleep 3
going sleep 7
waking up from sleep 4
going sleep 8
waking up from sleep 5
going sleep 9
waking up from sleep 6
waking up from sleep 7
waking up from sleep 8
waking up from sleep 9

查看控制台输出,只有一个线程运行第一个和第二个请求,并在单个线程完成后执行排队任务(延迟10秒启动任务2,另一个延迟启动任务3)。但是,任务3、4、5和6并行执行,但每个调用之间的延迟有所不同。

控制台输出

MAX_WORKERS = 4
i = 0

class Handler(tornado.web.RequestHandler):
    executor = ThreadPoolExecutor(max_workers=MAX_WORKERS)

    @run_on_executor
    def background_task(self, i):
        print("%s: Going sleep %s" % (time.time(), i))
        time.sleep(10);
        print("%s: Waiking up from sleep %s" % (time.time(), i))
        return str(i)

    @tornado.gen.coroutine
    def get(self):
        global i
        i+=1
        result = yield self.background_task(i)
        self.write(result)

有人可以解释这种行为吗?你有什么解决办法吗?

0 个答案:

没有答案