django-1.0でmultithread webサーバ

djangoのrunserverで使っているdjango.core.servers.basehttp.WSGIServerは、Python標準のBaseHTTPServer.HTTPServerがベースになっています。

これはスレッドを使わずに複数のリクエストを耳順に処理していく仕組みになっています。このためrunserverでは、AJAXでCometのようなことができません(監視したときのPOSTでの待ちで、サーバ自体がとまってしまう)。

BaseHTTPServer.HTTPServerはSocketServer.TCPServerがベースになっています。TCPServerはThreadingMixInと一緒に多重継承させたクラスを作ることで、そのクラスはacceptした各ソケットごとに独立したスレッドで処理してくれるようになります。

そこで、以下のような、django manager.py用コマンドを追加します。、runserverと同じことをするコマンドだけど、...basehttpモジュール中のWSGIServerを入れ替えることで、マルチスレッド化させたrunserverを実行させる、という試みのものです。

myapp/management/commands/runthreadingserver.py

import django.core.management.commands.runserver as base
import django.core.servers.basehttp as basehttp
from SocketServer import ThreadingMixIn

class WSGIServer(ThreadingMixIn, basehttp.WSGIServer): pass
basehttp.WSGIServer = WSGIServer

class Command(base.Command): pass

これによってマルチスレッドでリクエストが処理されるようになります。スケール性やバージョン互換性、databaseを使ったときなどで排他制御などに心配がありそうだけど、djangoでの正しいマルチスレッド化の方法ってあるのかな。

例:チャット

実行:

python broadcast/manage.py runthreadingserver 0.0.0.0:3200

などで実行し、FirefoxChromeで"http://〜:3200/ui"にアクセスするとチャット画面がでます。

この実装はPOSTコネクションでメッセージ到着を待ち続けさせるので、

python broadcast/manage.py runserver 0.0.0.0:3200

では、無反応になります。