Я пытаюсь развернуть api Flask через Apache / mod_wsgi. API использует Gevent для обеспечения параллелизма для рекурсивного метода. Однако это вызывает следующую ошибку
[Mon Feb 08 12:05:37 2016] [error] error: cannot switch to a different thread
[Mon Feb 08 12:05:37 2016] [error] <callback at 0x1094ee350 args=()> failed with error
Весь api отлично работает с Gevent при запуске с использованием встроенного веб-сервера Pycharm, а api отлично работает с Apache / mod_wsgi, когда я не использую gevent для обеспечения параллелизма.
Я предполагаю, что это должно быть запущено в Apache, но мне пока не удалось найти решение. Я все время вижу упоминания об исправлении обезьян, поэтому я добавил эту строку в модуль, в котором вызывается gevent
from gevent import monkey; monkey.patch_all()
но, похоже, это не помогло.
Я нашел этот бит в автономных контейнерах WSGI в документации Flask (http://flask.pocoo.org/docs/0.10/deploying/wsgi-standalone/):
Gevent is a coroutine-based Python networking library that uses greenlet to provide a high-level synchronous API on top of libevent event loop:
from gevent.wsgi import WSGIServer
from yourapplication import app
http_server = WSGIServer(('', 5000), app)
http_server.serve_forever()
Также говорится, что
There are popular servers written in Python that contain WSGI applications and serve HTTP. These servers stand alone when they run; you can proxy to them from your web server. Note the section on Proxy Setups if you run into issues.
Нужно ли мне отказаться от использования mod_wsgi и использовать встроенный в Gevent сервер WSGI, а затем проксировать его через Apache? Это будет королевский PITA, особенно для решения проблем CORS (у нас есть веб-интерфейс, который обращается к api на том же сервере, и проксирование с другого порта вызовет множество проблем с перекрестным происхождением - если кто-то не убедит меня в обратном).
Мы будем очень благодарны за любое понимание того, что попробовать дальше.
apache mod_wsgi в настоящее время несовместим с gevent. Для эластичного beanstalk AWS с Apache я использовал async_mode = "threading" для Flask, и он хорошо работает. Обратите внимание, что многопоточность имеет меньшую производительность, чем gevent.
https://flask-socketio.readthedocs.io/en/latest/#deployment
app = Flask(__name__,static_folder='static')
socketio = SocketIO(app, async_mode="threading")
Обратите внимание, что Flask может работать автономно с gevent.
app = Flask(__name__,static_folder='static')
socketio = SocketIO(app, async_mode="gevent")
if __name__ == '__main__':
HOST = '127.0.0.1'
PORT = 5055
socketio.run(app, port=PORT, host=HOST)
Однако вам действительно нужен HTTP-сервер перед ним, такой как Gunicorn.
Я нашел здесь ответ: Почему директива WSGIApplicationGroup% {GLOBAL} работает для создания новых потоков
В двух словах:
WSGIApplicationGroup: установите выполнение для того же интерпретатора Python (созданного первым).
Таким образом, по умолчанию каждый новый поток не должен использовать один и тот же экземпляр интерпретатора Python.
Для uWSGI эквивалентный метод - добавить это в ваш файл .ini:
single-interpreter = true
Я только что нашел здесь похожую тему https://stackoverflow.com/questions/9692089/why-gevent-on-a-flask-app-with-apache-mod-wsgi-is-raising-notimplementederror у этого есть решение.
Чтобы сделать то, что мне нужно, мне нужно добавить директиву WSGIApplicationGroup %{GLOBAL}
в мой Apache conf. Мне тоже любопытно, почему это решает проблему.