Я использую gevent wsgi для запуска приложения 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()
Для проверки я использовал следующий скрипт, который запускает три запроса одновременно:
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), чтобы найти ошибку. Установка spawn = None для сервера wsgi не подойдет для цели использования гринлетов для блокировки вызовов ресурсов в запросах, и все равно не работает.
Есть предложения? Спасибо.