pythonでイベント駆動サーバー
趣味で非同期サーバーが作りたくて土日に色々調べてたんですが一旦まとめてみます。
node.jsなんか使えば苦労せずに出来るのでしょうが僕はpythonが好きなのでできればpythonでやりかったということです。
予めお断りさせていただくと間違ってる情報が含まれてる可能性があるのでお気をつけ下さい。
◯指針
・pythonで書きたい
・できることなら慣れてるし自分の中で一番使いやすいdjangoで書きたい。
・wsgiで動かしたい。
・なんとなくapacheは使いたくない。
・python-amazon-product-apiを使いたい。(bitbucketで公開されてます。)
まず最初にdjangoで書きたいについてなんですが、本当は一番最初tornadoを検討していました。
評判良くて以前は結構話題になっているみたいでしたので。
しかし非同期周りのコードが専用の物になっててサードのライブラリ使おうとするとブロッキングして思った通りの動きをしてくれません。
今回のamazonのライブラリ使うところがそれです。
tornadoで動かそうとするとリクエスト周りを自分で書かないといけないので今回は見送りました。
ではこの問題を解決するには?
調べた限りではgeventのmonkey_patchしかなさそうでした。
uwsgiとgunicornがデフォでgeventに対応してます。
どちらもオプションでコントロールできます。
uwsgiなら
gevent-monkey-patch = true gevent = 100
みたいな感じで動くし
gunicornでも
$ gunicorn wsgi:application --worker-class gevent -k gunicorn.workers.ggevent.GeventWorker
で起動すれば動きます。
ただしdjangoを動かそうとすると話が変わってきます。
uwsgiは何回かアクセスするとdb周りでDatabaseErrorが発生します。
thread.get_ident()が変わるせいです。
ファイルで言うとdjango/db/backends/__init__.py内のvalidate_thread_sharingで例外が出ます。
しかしgunicornだとうまく動きます。なんでかっていうとソースを見ればわかるのですが本来だと↑のvalidate_thread_sharingで引っかかるところをpatchあてて通るようにしているからです。
この当て方で大丈夫なのか疑問なところではありますが。
どうにも無理矢理な感じするのですがdjango側のソースをしっかり見れていないので何とも言えません。
そこは今後の課題にするとして、手間をかけずに動くのはgunicornなのでその方向で行きたいと思います。
とは言えuwsgiでも似たような感じで対応できるのでどっちでも良いような気がします。結局は好きな方使えば良いんじゃないでしょうか。
最後に言いたいのはサードパーティのライブラリがそのまま使えるようになるmonkey_patchは強力です。