Python3中Flask与Tornado如何同时支持HTTP1.1和HTTP2?哪个库更推荐?
Flask与Tornado支持HTTP1.1/HTTP2的实现及选型建议
一、如何让Flask和Tornado同时支持HTTP1.1与HTTP2
1. Tornado的实现方式
Tornado从5.0版本开始原生支持HTTP2,只需配置正确的SSL参数(HTTP2强制要求HTTPS),同时指定ALPN协议列表即可兼容两种协议:
- 确保系统安装的OpenSSL版本≥1.0.2(支持ALPN扩展)
- 创建
HTTPServer时,在ssl_options中添加alpn_protocols=["h2", "http/1.1"],服务器会优先协商HTTP2,协商失败则降级为HTTP1.1 - 配置合法的SSL证书和私钥(测试环境可用自签证书,生产环境需CA签发)
2. Flask的实现方式
Flask是WSGI框架,不原生支持HTTP2,需借助第三方工具实现:
- 方式一:用ASGI服务器托管(推荐)
将Flask包装为ASGI应用,使用支持HTTP2的ASGI服务器(如Hypercorn、Uvicorn)运行:from flask import Flask from asgiref.wsgi import WsgiToAsgi app = Flask(__name__) @app.route("/") def hello(): return "Hello, World!" asgi_app = WsgiToAsgi(app) # 命令行启动(需先安装hypercorn): # hypercorn --bind 0.0.0.0:443 --certfile /path/to/cert.crt --keyfile /path/to/key.key --http2 your_app:asgi_app - 方式二:挂载到Tornado
利用Tornado的WSGIContainer将Flask应用包装为Tornado处理程序,复用Tornado的HTTP2支持:from flask import Flask import tornado.wsgi import tornado.httpserver import tornado.ioloop import ssl app = Flask(__name__) @app.route("/") def hello(): return "Hello, World!" if __name__ == "__main__": container = tornado.wsgi.WSGIContainer(app) tornado_app = tornado.web.Application([(r".*", tornado.web.FallbackHandler, dict(fallback=container))]) server = tornado.httpserver.HTTPServer(tornado_app, ssl_options={ "certfile": "/path/to/cert.crt", "keyfile": "/path/to/key.key", "ssl_version": ssl.PROTOCOL_TLS_SERVER, "alpn_protocols": ["h2", "http/1.1"] }) server.listen(443) tornado.ioloop.IOLoop.current().start()
二、Flask vs Tornado:哪个更值得推荐?
- 优先选Tornado的场景:
- 需处理高并发异步IO场景(如长连接、WebSocket、实时推送)
- 追求服务器性能,原生支持HTTP2无需额外依赖
- 希望用一套框架搞定服务器与业务逻辑,降低依赖复杂度
- 优先选Flask的场景:
- 需要丰富的生态插件(ORM、认证、表单处理等),Flask扩展生态更成熟
- 团队熟悉WSGI生态,快速开发轻量Web应用
- 需灵活切换部署方式,搭配不同ASGI/WSGI服务器
两者没有绝对优劣,完全取决于业务场景和技术栈偏好。
三、Tornado代码错误:AttributeError: Unrecognized option 'ssl-options'
错误原因
代码中options.ssl_options是错误用法,tornado.options的options对象默认没有ssl_options属性,你错误地尝试从该对象获取SSL配置。
修正后的代码
直接使用Python标准库ssl模块的常量配置SSL参数:
import tornado.httpserver import tornado.ioloop import tornado.web import ssl class MainHandler(tornado.web.RequestHandler): def get(self): self.write("Hello, world") if __name__ == "__main__": app = tornado.web.Application([(r"/", MainHandler)]) server = tornado.httpserver.HTTPServer(app, ssl_options={ "certfile": "/path/to/your/certificate.crt", "keyfile": "/path/to/your/private.key", "ssl_version": ssl.PROTOCOL_TLS_SERVER, # 可自定义加密套件,或省略使用默认值 "ciphers": "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256", "alpn_protocols": ["h2", "http/1.1"] }) server.listen(443) tornado.ioloop.IOLoop.current().start()
额外注意事项
- 确保Tornado版本≥5.0,旧版本不支持HTTP2
- 运行443端口需要管理员权限(Linux/macOS加
sudo,Windows用管理员命令行)
内容的提问来源于stack exchange,提问作者小怪兽儿
相关产品推荐
相关产品推荐

