6

CherryPyコントローラー内でORMSQLAlchemyセッションを使用できるようにするために、次の設定でlighttpdの背後にあるCherryPyFastCGIサーバーを開発しています。しかし、約500ループの14の同時リクエストでストレステストを実行すると、しばらくするとエラーが発生し始めAttributeError: '_ThreadData' object has no attribute 'scoped_session_class'ます。エラー率は合計で約50%です。open_dbsession()AttributeError: 'Request' object has no attribute 'scoped_session_class'close_dbsession()

これは、サーバーをlighttpdの背後で実行した場合にのみ発生し、サーバーを直接実行した場合には発生しませんcherrypy.engine.start()connect()例外が発生していないことが確認されています。

scoped_sessionまた、の戻り値をに割り当てようとしましたが(ここGlobalSessionで行うように)、他のSAレベルのエラーなどのエラーが発生しました。(同時実行:10、ループ:1000、エラー率:16%。直接実行した場合でも発生します。)UnboundExceptionError

考えられる原因はいくつかありますが、1つ選ぶのに十分な知識がありません。
1. start_threadFastCGI環境ではサブスクリプションの信頼性は低くなりますか? 2のopen_dbsession()前に呼び出されたようです。何らかの理由でクリアされますか?connect()
cherrypy.thread_data

サーバーコード

import sqlalchemy as sa  
from sqlalchemy.orm import session_maker, scoped_session

engine = sa.create_engine(dburi, strategy="threadlocal")  
GlobalSession = session_maker(bind=engine, transactional=False)

def connect(thread_index):  
    cherrypy.thread_data.scoped_session_class = scoped_session(GlobalSession)

def open_dbsession():  
    cherrypy.request.scoped_session_class = cherrypy.thread_data.scoped_session_class

def close_dbsession():  
    cherrypy.request.scoped_session_class.remove()


cherrypy.tools.dbsession_open = cherrypy.Tool('on_start_resource', open_dbsession)  
cherrypy.tools.dbsession_close = cherrypy.Tool('on_end_resource', close_dbsession)  
cherrypy.engine.subscribe('start_thread', connect)

lighttpd fastcgi config

...
var.server_name = "test"
var.server_root = "/path/to/root"
var.svc_env = "test"
fastcgi.server = (
  "/" => (
    "cherry.fcgi" => (
      "bin-path" => server_root + "/fcgi_" + server_name + ".fcgi",
      "bin-environment" => (
        "SVC_ENV" => svc_env
      ),
      "bin-copy-environment" => ("PATH", "LC_CTYPE"),
      "socket" => "/tmp/cherry_" + server_name + "." + svc_env + ".sock",
      "check-local" => "disable",
      "disable-time"    => 1,
      "min-procs"       => 1,
      "max-procs"       => 4,
    ),
  ),
)

編集

  • コード例で欠落thread_indexしていた引数を元のソースコードから復元しました(コメントのおかげで)
  • エラーがすぐに発生しないことを明確にしました
  • 条件をlighttpdに絞り込みました
4

2 に答える 2

0

また、scoped_sessionの戻り値をGlobalSessionに割り当てようとしましたが(ここでのように)、UnboundExceptionErrorやその他のSAレベルのエラーなどのエラーが発生しました。(同時実行:10、ループ:1000、エラー率:16%)

scoped_sessionクラスを明示的にインスタンス化しなかった場合、このエラーは発生しませんでした。

すなわち

GlobalSession = scoped_session(session_maker(bind=engine, transactional=False))

def connect(thread_index):  
    cherrypy.thread_data.scoped_session_class = GlobalSession

def open_dbsession():  
    cherrypy.request.scoped_session_class = cherrypy.thread_data.scoped_session_class

def close_dbsession():  
    cherrypy.request.scoped_session_class.remove()
于 2009-03-10T03:13:21.860 に答える