tornado: http_server.start multiple instance fails in python3.5
the very basic multi instances code fails on python 3.5 env. It works with python2.7 and 3.6.4.
Python 3.5.2
tornado 5.0.1
Flask 0.12.2
Flask-Cors 3.0.3
gevent 1.2.2
greenlet 0.4.13
gunicorn 19.7.1
lxml 4.2.0
from flask import Flask, request, jsonify
from flask_cors import CORS, cross_origin
from tornado.wsgi import WSGIContainer
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
app = Flask(__name__)
PROD = True
CORS(app)
@app.route('/api/check/alive', methods=['GET'])
def handle_api_alive():
resp = jsonify(dict(status="OK"))
return resp
if __name__ == '__main__':
# start HTTP server
http_server = HTTPServer(WSGIContainer(app))
http_server.bind(9999)
http_server.start(num_processes=2)
IOLoop.instance().start()
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Comments: 15 (5 by maintainers)
This is a result of the move to
asyncio.asynciois not as multiprocess-friendly as the old Tornado implementation was. I highly recommend using a process manager like supervisord and a separate load balancer instead of Tornado’s multi-process mode.If you want to continue using Tornado’s multi-process mode, you must be very careful not to do anything that might initialize the IOLoop before the fork. In particular, this may mean using the “advanced” multi-process instructions so that the only thing that happens before the fork is
tornado.netutil.bind_sockets.It may not be possible to use the non-advanced versions of multi-process mode any more in Python 3. If so, maybe these modes should be removed in Tornado 6.0.
@bdarnell Thanks for helping. As you said, yes I created an unused
IOLoopinstance usingunused = IOLoop.current(), and anApplicationwithdebug=True.In the source code about
Application.__init__,debug=Truewill setautoreload=Trueif you don’t setautoreload=Falsein the application kwargs. And theautoreload=Truecalltornado.autoreload.start(), this method initializes theIOLoopas you said “too soon”.So I remove the unused
IOLoopinstance, and create anApplicationwithdebug=Trueandautoreload=False, it works fine. I’ve used nginx and docker for load balancing even though it’s a bit more complicated than this multi-process mode.I see what happened, at least in @chrjxj 's case. In Tornado 5.0, simply importing
tornado.wsgiis enough to initialize the IOLoop and breakbind/start.@MioYvo, I’m not sure if you’re seeing the same thing. If you’re seeing this error without importing
tornado.wsgi, you’re probably doing something else that initializes theIOLooptoo soon. The most common things that do this are creating anApplicationwithdebug=Trueand creating anAsyncHTTPClient. This is not allowed in older versions of Tornado either, although the move toasyncioin Tornado 5.0 has made it harder to give good error messages.@ajayuranakar on Linux,
listenworks, i tried on my centos7 server and debian docker container on macOS ; on macOS(10.13.5),listendon’t work.Thank you for your help.