[technology][python]flaskのHTTP/1.1(keep-alive)対応設定
ちょっと仕事で簡単なWebUIを作る必要があって、数日前からflaskを弄っています。
flaskはpythonでwebアプリケーションをお手軽に書けるフレームワークです。
node.js + expressとかでやっている様な
を少ないコード量で書ける様にしてくれるありがたい仕組みです。
Javascript使いならnode.js + expressとかで良いのですが、自分はWebのフロントエンド周りは苦手で、特にJavascriptを使い慣れておらず、なるべくpythonで全部書きたいためflaskを弄り始めた次第。(ブラウザサイドでは最低限Javascript使う必要はあるのですが)
flaskの使い方のチュートリアル的なものはqiita等に色々載っていて、REST APIとか作るだけならこういった記事を参考に真似するだけで超カンタンに出来るのですが、そういえばこれ、HTTP keep-alive対応させるにはどうするんだろう?と疑問が生じたので調べてみました。ちょっと自分が作ろうと思っているものがクライアント側から結構高頻度でREST API叩きそうなので、その度にTCPセッション張り直しは無駄だなと思ったので。
結論から言うと以下の様な感じです。
ソースはStackoverflow
stackoverflow.com
WSGIRequestHandlerをimportして、アプリをrun()する前にHTTP protocol versionとしてHTTP/1.1を設定する。
#!/usr/bin/env python # -*- coding: utf-8 -*- # flaskをimport from flask import Flask, render_template, request, redirect, url_for,jsonify # WSGIRequestHandlerをimport、これにHTTP/1,1対応を設定する from werkzeug.serving import WSGIRequestHandler app = Flask(__name__) 〜中略〜 if __name__ == '__main__': WSGIRequestHandler.protocol_version = "HTTP/1.1" # HTTP/1.1対応の宣言 app.run(host='0.0.0.0')
ちなみにpythonでクライアント側を書く場合、httpクライアントとしてはurllib.requestだったり、http.clientだったり、いくつか選択肢があります。requestsが割とシンプルなので、requestsを使う場合だと、Session()というメソッドでHTTPセッションのインスタンスを作り、そこにgetやputを投げれば良いみたいです。
import requests s = requests.Session() response1 = s.get('http://localhost:5000/api1') response2 = s.get('http://localhost:5000/api2')
こんな感じにすると、localhost:5000に対する/api1と/api2のGETが同じHTTPセッション上で実行されます。
Wiresharkでパケット拾いながら確認した限りでは上手く行っている様に見えます。
あとflask側でkeep-alive timeoutを設定する方法が良く判らない。
WSGIServerのattributeにtimeoutがあるみたいだけど、これクラス変数なのかな?
よく判らないので、公式サイトからソースコード落として確認する。
f.gallai.re
ソースコードはwsgiserver.pyに全部入っているみたい。
class HTTPServer(object): """An HTTP server.""" 〜中略〜 timeout = 10 """The timeout in seconds for accepted connections (default 10).""" 〜中略〜 class WSGIServer(HTTPServer): """A subclass of HTTPServer which calls a WSGI application.""" 〜中略〜 def __init__(self, wsgi_app, host='0.0.0.0', port=8080, numthreads=10, server_name=None, max=-1, request_queue_size=5, timeout=10, shutdown_timeout=5, accepted_queue_size=-1, accepted_queue_timeout=10, certfile=None, keyfile=None, ca_certs=None): 〜中略〜 self.timeout = timeout
WSGIServerのインスタンスを初期化する際にクラス変数のtimeoutの値をインスタンス変数のtimeoutに引き継いでいるみたいですね。
ということはインスタンス生成前にこれを書き換えればtimeout値を自由に設定できそうです。
10秒なら自分の目的には問題無いので触らないですけど。
[technology][python]追記: Flaskのログを抑制する
Flaskを使うとAPIサーバーをサクサクっと書けて便利なのですが、巷に載っているサンプルコードの通りに動かすと、HTTPアクセスがある度にログが標準出力に吐き出されます。
これを止めたいなと思って、調べたら、これまたStackoverFlowに答えがありました。
簡単に言えばFlaskはloggingモジュール使っているので、loggingをimportして、ログの出力レベルを設定するなり、出力を止めるなりしなさいという話。
import logging 〜中略〜 app = Flask(__name__) log = logging.getLogger('werkzeug') log.disabled = True
ログを止めるのはこんな感じ。実際試してみてうまく行きました。
ログの出力レベルを変えるならlog.disabled = Trueのところを
log.setLevel(logging.ERROR)
等にすると、出力レベルを変えられる。
setHandler()で出力先のファイルを設定して、出力先毎にログレベルを変える様な事も出来ます。