问题描述
我正在尝试在多个线程中运行多个 IOLoop,我想知道 IOLoop 的实际工作原理.
I am trying to run multiple IOLoop in multiple threads and I am wondering how the IOLoop actually works.
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()
根据文档,我不能使用 IOLoop.instance() 因为它是一个单例并且我在一个线程中工作.所以我创建了自己的 IOLoop.但是这段代码监听了8888端口却无法渲染任何网页.我想知道是否遗漏了什么,或者我是否需要以某种方式将 http_server 绑定到 IOLoop?
According to the doc, I can not use IOLoop.instance() since it's a singleton and I am working in a thread. So I created my own IOLoop. But this piece of code listens on the port 8888 but can not render any web page. I am wondering is there anything missed, or do I need to tie the http_server to the IOLoop in some way?
此外,我发现删除最后 3 行并替换为 tornado.ioloop.IOLoop.instance().start
非常适合单线程.但是单例和自创IOLoop有什么区别呢?
Also, I find that removing the last 3 lines and substitute with tornado.ioloop.IOLoop.instance().start
works perfectly for single thread. But what's the difference between the singleton and self created IOLoop?
我是 Tornado 的新手,欢迎提供任何答案.
I am new to Tornado and any answers are welcomed.
推荐答案
IOLoop.current
不带参数返回已创建线程的ioloop 或调用IOLoop.instance()
.而HTTPServer(实际上在TCPServer中)使用IOLoop.current与ioloop交互,所以你唯一应该改变的是在HTTPServer之前创建ioloop,例如
IOLoop.current
without params returns already created ioloop of thread or it calls IOLoop.instance()
. And HTTPServer (actually in TCPServer) use IOLoop.current to interact with ioloop, so the only thing you should change is to create ioloop before HTTPServer e.g.
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()
我也删除了 IOLoop.make_current
,因为它是多余的 - IOLoop()
将 self 设置为当前.
Also I've removed IOLoop.make_current
, since it's redundant - IOLoop()
sets self as a current.
上面的代码可以工作,但只能使用一个线程,因为默认情况下不启用重用端口.你最终会得到:
Code above will work, but only with one thread, because reuse_port is not enabled by default. You will end up with:
OSError: [Errno 98] Address already in use
您可以使用
http_server_api.bind(port=8888, reuse_port=True)
http_server_api.start()
代替http_server_api.listen(8888)
这篇关于Tornado 多线程中的多个 IOLoop的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!