2012-03-23 3 views
3

私は、cherrypyアプリケーションを実行するためにgevent wsgiを使用しており、要求ハンドラでいくつかのブロッキングgeventコールを行っています。ブロッキング呼び出しは、単一の要求を行うと、いくつかのブロッキングリソース(他のプロセスへのパイプ)の使用を並列化することに成功しました。問題は、私は複数の要求を発射する場合、その後、CherryPyには、この例外をスロー内部サーバーエラーを返し起こる:cherrypy throwsブロッキングgeventコールの使用時に内部サーバーエラーの原因となる例外

[23/Mar/2012:17:50:35] Traceback (most recent call last): 
    File "/usr/local/lib/python2.7/site-packages/CherryPy-3.2.2-py2.7.egg/cherrypy/_cpwsgi.py", line 170, in trap 
return func(*args, **kwargs) 
    File "/usr/local/lib/python2.7/site-packages/CherryPy-3.2.2-py2.7.egg/cherrypy/_cpwsgi.py", line 97, in __call__ 
return self.nextapp(environ, start_response) 
    File "/usr/local/lib/python2.7/site-packages/CherryPy-3.2.2-py2.7.egg/cherrypy/_cpwsgi.py", line 385, in tail 
return self.response_class(environ, start_response, self.cpapp) 
    File "/usr/local/lib/python2.7/site-packages/CherryPy-3.2.2-py2.7.egg/cherrypy/_cpwsgi.py", line 232, in __init__ 
outstatus = r.output_status 
AttributeError: 'Response' object has no attribute 'output_status' 

私がコアに問題を低減し、次のような単純なアプリケーションが問題を毎回再現:

import cherrypy 
import gevent 
from gevent import wsgi 

class BugServer(object): 
    @cherrypy.expose 
    def index(self): 
     gevent.sleep(2) 
     return 'dummy foo' 

if __name__ == "__main__": 
     app = cherrypy.tree.mount(BugServer(), '/') 
     wsgi.WSGIServer(('', 27726), app).serve_forever() 
それをテストする

私は、同時に3つの要求を発射し、次のスクリプトを使用:私はCherryPyに掘る必要がある場合はわからない

import httplib 
import threading 

def make_req(host): 
     conn = httplib.HTTPConnection(host) 
     conn.request("GET", "/") 
     return conn.getresponse() 

threads = [] 
for i in range(3): 
     t = threading.Thread(target=make_req, args=('192.168.128.7:27726',), kwargs={}) 
     t.start() 
     threads.append(t) 

for t in threads: 
     t.join() 

をまたはgevent(wsgi)ライブラリを使用してバグを見つけます。 spawn = Noneをwsgiサーバに設定すると、リクエスト内のリソースコールをブロックするために未使用のグリーンレットを使用する目的に反しますが、とにかく動作しません。

提案がありますか?ありがとう。

答えて

2

CherryPyはthreadlocalsを広範囲に使用しているため、イベントループや、同じスレッドで複数の要求を処理する他のアプローチでは使用できません。テストで呼び出しを同期させるとしばらく動いているように見えるかもしれませんが、ハンドラが応答を返すよりも速く到着する複数の同時要求を試みるとすぐに、このようなエラーが発生します。

cherrypy.servingをgreenletsやその他の並列性のために設計された何らかの種類のコンテキストオブジェクトに置き換えることは可能ですが、今日まで誰も実験に時間を割いていません。

+0

ああ、わかります。サーバーが常に要求を同期して処理する方法はありませんか?並列化全体がすでに要求レベル以下で実装されているためです。とにかく、チップのおかげで、私はしようとし、cheryrpy.servingを見てみましょう。もし私がそれを行うためのスイッチを見つけなければ、実際には別のWebフレームワークを使用するか、まったく使用しないことを検討するでしょう。私は多くの処理能力を必要とする非常に特殊化された要求に対してのみ必要です。 – pletoss

4

Cherrypyは、リクエスト\応答オブジェクト(あなたのPythonバージョンでサポートされている場合)のためにthreading.localを使用します。このオブジェクトは、gevent.monkey.patch_allを使用してgeentローカルストレージを使用するようにパッチすることができます。ただ、使用:

from gevent.monkey import patch_all 
patch_all() 

を輸入のいずれかの前に、(あなたがしても、代わりにgevent.timeの正常な「時間」機能を使用することができます)。これで修正されました。

関連する問題