この記事の例では、Python Web フレームワーク Tornado の操作とデプロイメントの詳細を共有します。具体的な内容は次のとおりです
1. Tornado には独自の HTTPServer が組み込まれているためです。 、実行とデプロイは他の Python Web フレームワークと同じです。アプリケーションを実行するように WSGI コンテナを構成する代わりに、サービスを開始する main() 関数を記述する必要があります:
def main(): app = make_app() app.listen(8888) IOLoop.current().start() if __name__ == '__main__': main()
このプログラムを実行してサービスを開始するようにオペレーティング システムまたはプロセス マネージャーを構成します。 (「開いているファイルが多すぎます」エラーを避けるために) プロセスごとにオープンできるファイル ハンドルの最大数を増やす必要がある場合があることに注意してください。この制限を増やす (たとえば、50000 に) には、ulimit コマンドを使用するか、/etc/security/limits.conf を変更するか、supervisord 構成で minfds を設定します。
2. プロセスとポート Python の GIL (Global Interpreter Lock) により、マルチ CPU マシンを最大限に活用するには、複数の Python プロセスを実行する必要があります。一般に、CPU ごとに 1 つのプロセスを実行するのが最善です。
Tornado には、複数のプロセスを一度に開始するための組み込みのマルチプロセス モードが含まれています。これには、メイン関数に小さな変更が必要です:
def main(): app = make_app() server = tornado.httpserver.HTTPServer(app) server.bind(8888) server.start(0) # forks one process per cpu IOLoop.current().start()
これは、複数のプロセスを開始してプロセスを共有させる最も簡単な方法です。ただし、いくつかの制限があります。まず、各子プロセスには独自の IOLoop があるため、フォークする前に (間接的であっても) グローバル IOLoop インスタンスに触れないことが重要です。第 2 に、このモデルでは、ダウンタイムゼロの更新を達成することが困難です。最後に、すべてのプロセスが同じポートを共有するため、プロセスを個別に監視することがより困難になります。
より複雑な展開の場合は、独立したプロセスを開始し、それらが異なるポートをリッスンできるようにすることをお勧めします。supervisord の「プロセス グループ」機能は良い方法です。各プロセスが異なるポートを使用する場合、通常、HAProxy や nginx などの外部ロード バランサーは、送信訪問者に単一のアドレスを提供する必要があります。
3. ロードバランサーの背後で実行する nginx などのロードバランサーの背後で実行する場合は、HTTPServer のコンストラクターに xheaders=True を渡すことをお勧めします。これにより、Tornado は、すべてのトラフィックがロード バランサーの IP アドレスからのものであると想定するのではなく、X-Real-IP などの HTTP ヘッダーを使用してユーザーの IP アドレスを取得するように指示されます。
これはオリジナルの nginx 設定ファイルで、FriendFeed で使用する設定と構造が似ています。これは、nginx と Tornado サーバーが同じマシン上で実行されており、4 つの Tornado サーバーがポート 8000 ~ 8003 で実行されていることを前提としています。アプリケーションで特別な static_path を指定して静的ファイルを作成します:
user nginx; worker_processes 1; error_log /var/log/nginx/error.log; pid /var/run/nginx.pid; events { worker_connections 1024; use epoll; } http { # Enumerate all the Tornado servers here upstream frontends { server 127.0.0.1:8000; server 127.0.0.1:8001; server 127.0.0.1:8002; server 127.0.0.1:8003; } include /etc/nginx/mime.types; default_type application/octet-stream; access_log /var/log/nginx/access.log; keepalive_timeout 65; proxy_read_timeout 200; sendfile on; tcp_nopush on; tcp_nodelay on; gzip on; gzip_min_length 1000; gzip_proxied any; gzip_types text/plain text/html text/css text/xml application/x-javascript application/xml application/atom+xml text/javascript; # Only retry if there was a communication error, not a timeout # on the Tornado server (to avoid propagating "queries of death" # to all frontends) proxy_next_upstream error; server { listen 80; # Allow file uploads client_max_body_size 50M; location ^~ /static/ { root /var/www; if ($query_string) { expires max; } } location = /favicon.ico { rewrite (.*) /static/favicon.ico; } location = /robots.txt { rewrite (.*) /static/robots.txt; } location / { proxy_pass_header Server; proxy_set_header Host $http_host; proxy_redirect off; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; proxy_pass http://frontends; } } }
これらの設定により、/static/ で始まるすべてのリクエストが http://www.php cn/:8888/ などの静的ディレクトリに自動的にルーティングされます。 static/foo.png は、指定された静的ディレクトリを通じて foo.png ファイルを提供します。また、/robots.txt と /favicon.ico も静的ディレクトリから自動的に提供されます (ただし、これらは /static/ プレフィックスで始まりません)。
上記の設定では、ファイルが静的ファイル ディレクトリにあるにもかかわらず、StaticFileHandler ルートから apple-touch-icon.png ファイルを取得するように Tornado を明示的に設定しました。 (正規表現キャプチャ グループは、要求されたファイル名を StaticFileHandler に伝える必要があり、キャプチャ グループを呼び出すと、そのファイル名がメソッド引数としてハンドラーに渡されます。) 同じことを、 Webサイト。 もちろん、HTML で 439940bdb518e9fd892bed955b59e35a タグを使用することで、ルートの apple-touch-icon.png の偽造を避けることもできます。 パフォーマンスを向上させるには、通常、ブラウザーが静的リソースをアクティブにキャッシュできるようにすることをお勧めします。これにより、ブラウザーは、ページのレンダリング時にブロックされる可能性がある不要な If-Modified-Since リクエストや Etag リクエストを送信しなくなり、Tornado は静的コンテンツを使用します。この機能をサポートするためのバージョン管理 (静的コンテンツのバージョン管理)。
settings = { "static_path": os.path.join(os.path.dirname(__file__), "static"), "cookie_secret": "__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__", "login_url": "/login", "xsrf_cookies": True, } application = tornado.web.Application([ (r"/", MainHandler), (r"/login", LoginHandler), (r"/(apple-touch-icon\.png)", tornado.web.StaticFileHandler, dict(path=settings['static_path'])), ], **settings)static_url() 関数は、相対パスを次のような URI に変換します。 /static/images/logo.png?v=aae54 では、v パラメータは logo.png コンテンツのハッシュであり、これが存在すると、Tornado サービスがキャッシュ ヘッダーをユーザーのブラウザに送信し、ブラウザがサーバーはコンテンツを無期限にキャッシュします。 パラメータ v はファイルの内容に基づいているため、ファイルを更新してサービスを再起動すると、新しい v 値が送信されるため、ユーザーのブラウザは自動的に新しいファイルを取得します。ファイルの内容が変更されていない場合、ブラウザはサーバーからの更新を確認せずにローカルにキャッシュされたコピーを使用し続けるため、レンダリングのパフォーマンスが大幅に向上します。 実稼働環境では、nginx などのより優れた静的サーバーを介して静的ファイルを提供することができます。static_url() によって提供されるバージョン タグを認識し、それに応じてキャッシュ ヘッダーを設定するように任意の Web サーバーを構成できます。以下は、FriendFeed で使用する nginx 関連の設定の一部です:
location /static/ { root /var/friendfeed/static; if ($query_string) { expires max; } }
五、Debug模式和自动重载
如果传递 debug=True 配置给 Application 的构造函数,应用程序将会运行在debug/开发模式。 在这个模式下,为了方便于开发的一些功能将被启用( 每一个也可以作为独立的标签使用,如果它们都被专门指定,那它们都将获得独立的优先级):
1、autoreload=True: 应用程序将会观察它的源文件是否改变,并且当任何文件改变的时候便重载它自己。这减少了在开发中需要手动重启服务的需求。然而,在debug模式下,某些错误(例如import的时候有语法错误)会导致服务 关闭,并且无法自动恢复。
2、compiled_template_cache=False: 模板将不会被缓存。
3、static_hash_cache=False: 静态文件哈希 (被 static_url 函数使用) 将不会被缓存。
4、serve_traceback=True: 当一个异常在 RequestHandler 中没有捕获,将会生成一个包含调用栈信息的错误页。
自动重载(autoreload)模式和 HTTPServer 的多进程模式不兼容,你不能给 HTTPServer.start 传递 1 以外的参数(或者调用 tornado.process.fork_processes) 当你使用自动重载模式的时候。
debug模式的自动重载功能可作为一个独立的模块位于 tornado.autoreload。以下两者可以结合使用,在语法错误之时提供额外的健壮性: 设置 autoreload=True 可以在app运行时检测文件修改,还有启动 python -m tornado.autoreload myserver.py 来捕获任意语法错误或者其他的启动时错误。
重载会丢失任何Python解释器命令行参数(-u). 因为它使用 sys.executable 和 sys.argv 重新执行Python。此外,修改这些变量将造成重载错误。
在一些平台(包括Windows 和Mac OSX 10.6之前),进程不能被“原地”更新,所以当检测到代码更新,旧服务就会退出然后启动一个新服务。这已经被公知来混淆一些IDE。
六、WSGI和Google App Engine
Tornado通常是独立运行的,不需要一个WSGI容器。然而,在一些环境中 (例如Google App Engine),只运行WSGI,应用程序不能独立运行自己的服务。在这种情况下,Tornado支持一个有限制的操作模式,不支持异步操作但允许一个Tornado's功能的子集在仅WSGI环境中。以下功能在WSGI模式下是不支持的,包括协程,@asynchronous 装饰器,AsyncHTTPClient,auth 模块和WebSockets。
你可以使用 tornado.wsgi.WSGIAdapter 把一个Tornado Application 转换成WSGI应用。在这个例子中, 配置你的WSGI容器发 现 application 对象:
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)
以上就是本文的全部内容,希望对大家的学习有所帮助。
更多PythonWeb框架Tornado运行和部署详细介绍相关文章请关注PHP中文网!