Tornado 多线程中的多个 IOLoop

She*_*ang 3 python multithreading tornado

我正在尝试在多个线程中运行多个 IOLoop,我想知道 IOLoop 实际是如何工作的。

class WebThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self, name='WebThread')

    def run(self):
        curdir = os.path.dirname(os.path.realpath(__file__))

        application = Application() #Very simple tornado.web.Application
        http_server_api = tornado.httpserver.HTTPServer(application)
        http_server_api.listen(8888)

        logging.info('Starting application')

        #tornado.ioloop.IOLoop.instance() is singleton, not for thread, right?

        ioloop = tornado.ioloop.IOLoop()
        ioloop.make_current()
        ioloop.start()
Run Code Online (Sandbox Code Playgroud)

根据文档,我不能使用 IOLoop.instance() 因为它是一个单例并且我在一个线程中工作。所以我创建了自己的 IOLoop。但是这段代码监听了8888端口却无法渲染任何网页。我想知道是否遗漏了什么,或者我是否需要以某种方式将 http_server 绑定到 IOLoop?

此外,我发现删除最后 3 行并替换tornado.ioloop.IOLoop.instance().start为单线程完美。但是单例和自创IOLoop有什么区别呢?

我是 Tornado 的新手,欢迎提供任何答案。

kwa*_*nek 5

通常,在构造异步对象时,您应该使用 IOLoop.current 作为默认值,而当您打算从不同的主线程与主线程进行通信时,应使用 IOLoop.instance。

IOLoop.current没有 params 返回已经创建的线程 ioloop或它调用IOLoop.instance(). 而HTTPServer(实际上在TCPServer中)使用IOLoop.current与ioloop交互,所以你唯一应该改变的是在HTTPServer之前创建ioloop,例如

class WebThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self, name='WebThread')

    def run(self):
        curdir = os.path.dirname(os.path.realpath(__file__))

        ioloop = tornado.ioloop.IOLoop()

        application = Application() #Very simple tornado.web.Application
        http_server_api = tornado.httpserver.HTTPServer(application)
        http_server_api.listen(8888)

        logging.info('Starting application')

        ioloop.start()
Run Code Online (Sandbox Code Playgroud)

我也删除了IOLoop.make_current,因为它是多余的 -IOLoop()将 self 设置为当前。


上面的代码可以工作,但只能使用一个线程,因为默认情况下不启用重用端口。你最终会得到:

OSError: [Errno 98] Address already in use
Run Code Online (Sandbox Code Playgroud)

你可以用

    http_server_api.bind(port=8888, reuse_port=True)
    http_server_api.start()
Run Code Online (Sandbox Code Playgroud)

代替 http_server_api.listen(8888)