我正在使用以下设置在lighttpd后面开发CherryPy FastCGI服务器,以启用在CherryPy Controller 中使用ORM SQLAlchemy session 。但是,当我用14个并发请求运行大约500个循环的压力测试时,过一会儿,它开始发出诸如AttributeError: '_ThreadData' object has no attribute 'scoped_session_class'
中的open_dbsession()
或AttributeError: 'Request' object has no attribute 'scoped_session_class'
中的close_dbsession()
的错误。错误率总计约为50%。
仅当我在lighttpd后面运行服务器时才会发生这种情况,而当它直接通过cherrypy.engine.start()
运行时则不会发生。已确认connect()
没有引发异常。
我还尝试将scoped_session
的返回值分配给GlobalSession
(就像here一样),但是随后它给出了UnboundExceptionError
之类的错误和其他SA级错误。 (并发:10,循环:1000,错误率:16%。即使直接运行,也会发生。)
有一些可能的原因,但我缺乏足够的知识来选择一个。
1.在FastCGI环境下start_thread
订阅是否不可靠?似乎open_dbsession()
在connect()
之前被调用
2.出于某些原因,会清除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配置
...
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
参数最佳答案
如果查看plugins.ThreadManager.acquire_thread
,您将看到self.bus.publish('start_thread', i)
行,其中i
是可见线程的数组索引。订阅start_thread
channel 的所有监听器都需要接受i
值作为位置参数。因此,将您的connect函数重写为:def connect(i):
我的猜测是某种程度上的默默失败。我将查看是否可以跟踪,测试和修复它。
关于python - 集成CherryPy Web框架,SQLAlchemy session 和lighttpd以提供高负载Web服务的最佳实践,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/625288/