运行和部署

您无需配置 WSGI 容器来查找您的应用程序,只需编写一个启动服务器的 main() 函数即可。

1
2
3
4
5
6
7
def main():
app = make_app()
app.listen(8080)
IOLoop.current().start()

if __name__ == "__main__":
main()

进程和端口

由于Python GIL(全局解释器锁)的存在,需要运行多个Python进程才能充分利用多CPU机器。

Tornado 包含一个内置的多进程模式,可以同时启动多个进程。这需要对标准 main 函数稍作修改:

1
2
3
4
5
6
def main():
app = make_app()
server = tornado.httpserver.HTTPServer(app)
server.bind(8080)
server.start(0) # fork on process per CPU
IOLoop.current().start()

这是启动多个进程并让它们共享同一端口的最简单方法,尽管它有一些限制。首先,每个子进程都有自己的 IOLoop,因此在 fork 之前不要触及全局 IOLoop 实例,这一点很重要。其次,这个模块很难做到零停机更新。最后,由于所有进程共享同一端口,因此单独监视它们更加困难。

在负载均衡器后面运行

当在像 nginx 这样的负载均衡器后面运行时,建议将 xheaders=True 传递给 HTTPServer 构造函数。这将告诉 Tornado 使用 X-Real-IP 之类的标头来获取用户的 IP 地址,而不是将所有流量归因于平衡器的 IP 地址。

静态文件和主动文件缓存

您可以通过在应用程序中指定 static_path 设置来从 Tornado 提供静态文件:

1
2
3
4
5
6
7
8
9
10
11
settings= {
"static_path":os.path.join(os.path.dirname(__file__), "static"),
"cookie_secret":"ASSSDASDASDADQWDASDW",
"login_url":"/login",
"xsrf_cookies":True,
}
application = tornado.web.Application([
(r"/", MainHandler),
(r"/login", LoginHandler),
(r"/(apple-touch-icon\.jpg)", tornado.web.StaticFileHandler, dict(path=settings['static_path'])),
])

此设置将自动使所有以 /start/ 开头的请求从该静态目录提供服务,例如http://localhost:8080/static/foo.png 将从指定的静态目录提供文件 foo.png

或者您可以在模板中使用 static_url 方法。

1
2
3
4
5
6
7
8
9
<html>
<head>
<title>FriendFeed - {{ _("Home") }}</title>
</head>
<body>
<div><img src="{{ static_url("images/logo.png") }}"/></div>
</body>
</html>

调试和自动重载

如果将 debug=True 传递给应用程序构造函数,应用程序将以调试/开发模式运行。在此模式下,将启用一些旨在方便开发的功能(每个功能也可用作单独的标志;如果两者都指定,则单独的标志优先):

  • autoreload=True => 应用程序将监视其源文件的更改,并在发生任何更改时重新加载自身。这减少了开发期间手动重新启动服务器的需要。但是,某些故障(例如语法错误)仍然可能导致服务器停机,而调试模式当前无法从中恢复。

  • compiled_template_cache=False => 模板不会被缓存。

  • static_hash_cached=False => 静态文件哈希(由 static_url 函数使用)不会被缓存。

  • serve_traceback=True => 当 RequestHandler 中的异常未被捕获时,将生成包含堆栈跟踪的错误页面。

Autoreload 模式与 HTTPServer 的多进程模式不兼容。如果您使用自动重新加载模式,则不得为 HTTPServer.start 提供 1 以外的参数(或调用 tornado.process.fork_process)。

调试模式的自动重新加载功能可作为 tornado.autoreload 中的独立模块使用。两者可以结合使用,以提供额外的针对语法错误的鲁棒性:在应用程序内设置 autoreloaded=True 以检测运行时的更改,并使用 python -m tornado.autoreload myserver.py 启动它以在启动时捕获任何语法错误或其他错误。

WSGI

Tornado 通常旨在独立运行,无需 WSGI 容器。然而,在某些环境中,只允许使用 WSGI,应用程序无法运行自己的服务器。在这种情况下,Tornado 支持有限的操作模式,不支持异步操作,但允许在仅 WSGI 环境中使用 Tornado 的功能子集。 WSGI 模式中不允许的功能包括协程、@asynchronous 装饰器、AsyncHTTPClientauth 模块和 Web Sockets。

您可以使用 tornado.wsgi.WSGIAdapter 将 Tornado 应用程序转换为 WSGI 应用程序。在此示例中,配置 WSGI 容器以查找应用程序对象。

1
2
3
4
5
6
7
8
9
10
11
12
import tornado.web
import tornado.wsgi

class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello world")

tornado_app = tornado.web.Application([
(r'/', MainHandler)
])
application = tornado.wsgi.WSGIAdapter(tornado_app)