2010-12-26 11 views
2

私はDjango Webアプリケーションを持っています。私はまた、呪文サーバをdjango(localhost:8090を実行している)を持つ同じマシン上でねじれた走りを使って書いています。ユーザーが何らかのアクションをしたときのアイデアは、Djangoに送られます.Djangoはこのねじれたサーバーに接続します。&サーバーはDjangoにデータを返します。最後に、Djangoはこのデータをいくつかのhtmlテンプレートに入れます。&はそれをユーザに返します。問題を引き起こすPython、Twisted、Django、reactor.run()

ここで私は問題が発生しています。私のDjangoアプリでは、リクエストが来ると、ローカルで実行されているツイストサーバーに接続する単純なツイストクライアントを作成します。

... 
     factory = Spell_Factory(query) 
     reactor.connectTCP(AS_SERVER_HOST, AS_SERVER_PORT, factory) 
     reactor.run(installSignalHandlers=0) 
     print factory.results 
... 

reactor.run()が問題の原因です。それはイベントループなので次回この同じコードがDjangoによって実行されると、私はサーバーに接続できません。誰がこれをどう扱うのですか?

答えて

4

上記2つの答えは正しいです。しかし、すでにというスペルを実装していると考えて、を入力した場合、として実行してください。別のプロセスと同じマシンで実行することで開始することができます - localhost:PORT。今のところ非常にシンプルなバイナリプロトコルインターフェイスを既に持っているようです。標準libのsocketインターフェイスをブロッキングモードで使って、同様に単純なPythonクライアントを実装できます。

しかし、私はtwisted.webで遊んで、簡単なWebインターフェイスを公開することをお勧めします。 JSONを使用してデータをシリアライズおよびデシリアライズすることができます。これはDjangoで十分サポートされています。ここでは非常に簡単な例です:

import json 
from twisted.web import server, resource 
from twisted.python import log 

class Root(resource.Resource): 
    def getChild(self, path, request): 
     # represents/on your web interface 
     return self 

class WebInterface(resource.Resource): 
    isLeaf = True 
    def render_GET(self, request): 
     log.msg('GOT a GET request.') 
     # read request.args if you need to process query args 
     # ... call some internal service and get output ... 
     return json.dumps(output) 

class SpellingSite(server.Site): 
    def __init__(self, *args, **kwargs): 
     self.root = Root() 
     server.Site.__init__(self, self.root, **kwargs) 
     self.root.putChild('spell', WebInterface()) 

そして、あなたは、次のスケルトン.tacファイルを使用することができ、それを実行するために:他のファーストクラスのサービスを使用すると、別のマシンのいずれかでそれを実行することを可能にするよう

from twisted.application import service, internet 

site = SpellingSite() 
application = service.Application('WebSpell') 
# attach the service to its parent application 
service_collection = service.IServiceCollection(application) 
internet.TCPServer(PORT, site).setServiceParent(service_collection) 

はあなたのサービスを実行しますウェブインタフェースを公開することで、リバースプロキシロードバランサの背後で水平に簡単にスケーリングすることができます。

+0

は既にこれを理解していました。しかし、ありがとう... –

1

Twistedサーバーからの結果やエラー/タイムアウトが発生した後は、リアクターを停止する必要があります。したがって、Djangoの各要求に対して、Twistedサーバーを照会する必要がある場合は、reactorを実行してから停止する必要があります。しかし、Twistedライブラリではサポートされていません。リアクタは再起動できません。考えられる解決策:ツイスト原子炉のための

  • 使用別のスレッドがありますが、私は今、これらのいずれかをしませんが、あなたが書くことができます(長時間実行スレッドをサポートしているサーバとあなたのDjangoアプリケーションをデプロイする必要があります。あなた自身が簡単に:-))。

  • クライアントプロトコルを実装するためにTwistedを使用しないでください。単純なstdlibのsocketモジュールを使用してください。

3

reactor.run()は、プログラム全体で1回だけ呼び出す必要があります。 「私が持っているこの1つの要求を開始する」と考えてはいけません。「すべてのものを始める」と考えてください。

リアクタをバックグラウンドスレッドで実行することは、この問題を回避するための1つの方法です。あなたのdjangoアプリケーションでは、DjangoアプリケーションでblockingCallFromThreadを使用して、Twisted APIをブロッキングAPIと同じように使用できます。しかし、あなたのWSGIコンテナからの少しの協力が必要です。なぜなら、このTwistedスレッドが適切なタイミングで(それぞれインタープリタが初期化されて解体されたときに)開始され停止されるようにする必要があるからです。

また、TwistedをWSGIコンテナとして使用して、特別な操作を開始または停止する必要はありません。 blockingCallFromThreadはただちに動作します。 twistd web --wsgiのコマンドラインヘルプを参照してください。

関連する問題