Я разрабатываю сервер CherryPy FastCGI за lighttpd со следующей настройкой, чтобы включить использование сеансов ORM SQLAlchemy внутри контроллеров CherryPy. Однако, когда я запускаю стресс-тесты с 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
(как это делает здесь ), но затем он выдал ошибки, такие как UnboundExceptionError
и другие ошибки уровня SA. (Параллельность: 10, циклы: 1000, частота ошибок: 16%. Происходит даже при непосредственном запуске.)
Есть несколько возможных причин, но мне не хватает знаний, чтобы выбрать одну.
1. Надежны ли подписки start_thread
в среде FastCGI? Похоже, 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 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