3

私はgeventwsgiを使用してcherrypyアプリケーションを実行し、リクエストハンドラーでいくつかのブロッキングgevent呼び出しを実行しています。単一のリクエストを行うと、ブロッキング呼び出しは期待どおりに機能し、一部のブロッキングリソース(他のプロセスへのパイプ)の使用を並列化できます。複数のリクエストを実行すると問題が発生し、cherrypyはこの例外をスローする内部サーバーエラーを返します。

[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つのリクエストを同時に起動する次のスクリプトを使用しました。

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()

バグを見つけるためにcherrypyまたはgevent(wsgi)ライブラリを掘り下げる必要があるかどうかはわかりません。wsgiサーバーにspawn=Noneを設定すると、リクエストでリソース呼び出しをブロックするためにグリーンレットを使用するという目的に反することになり、とにかく機能しません。

助言がありますか?ありがとう。

4

2 に答える 2

4

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

from gevent.monkey import patch_all
patch_all()

インポートの前 (その後、gevent.time の代わりに通常の「時間」関数を使用することもできます)。こちらで直りました。

于 2012-10-11T18:25:00.923 に答える
2

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

cherrypy.servingグリーンレットまたは他の並列処理用に設計されたある種のコンテキストオブジェクトに置き換えることは可能であるはずですが、これまで誰も実験に時間をかけていません。

于 2012-03-23T23:27:44.080 に答える