Я управляю uwsgi Emperor с различными вассалами, каждый из которых обслуживает определенное приложение Python из разных виртуальных сред. Поскольку uwsgi был скомпилирован с собственным интерпретатором Python 2.7, попытка использовать virtualenv с Python 3 в нем приводит к следующей ошибке в vassal.log:
ImportError: No module named site
Я считаю, что причина этой ошибки заключается в том, что uwsgi использует свой встроенный интерпретатор Python 2.7, а каталог virtualenv, в котором он работает, поддерживает только интерпретаторы Python 3. Действительно, когда я использую другой uwsgi (просто установив его с помощью pip install uwsgi
в том же virtualenv) ошибка пропадает. Тем не менее, я бы хотел, чтобы один Император правил несколькими разными виртуальными серверами, поэтому установка отдельных uwsgi для каждого из них - не вариант.
В соответствии с этот ответ в Stackoverflow. Правильный способ решить эту проблему - скомпилировать uwsgi с различными интерпретаторами Python в качестве загружаемых модулей. Прежде чем я выберу этот подход, я хотел бы знать, как я могу настроить своих вассалов, чтобы каждый из них использовал другой плагин интерпретатора.
Прямо сейчас у меня есть один Emperor, который запускается из моего /etc/rc.local со следующими настройками:
[uwsgi]
uid = www-data
gid = www-data
master = true
emperor = /etc/uwsgi/vassals
daemonize = /var/log/uwsgi/emperor.log
Затем у меня есть куча вассалов с такими ini-файлами:
[uwsgi]
master = false
single-interpreter = true
socket = /tmp/%n.sock
virtualenv = /home/user/.virtualenvs/djangoproject
chdir = /home/user/djangoproject
wsgi-file = project/wsgi.py
logto = /var/log/uwsgi/%n.log
У меня нет проблем с компиляцией измененной версии uwsgi с несколькими плагинами интерпретатора, но я хотел бы знать, что мне нужно изменить в моей конфигурации, чтобы на самом деле использовать эти отдельные переводчики. Могу я просто сказать один vassal.ini:
plugin = python3.4
а в другом:
plugin = python2.7
?
Пожалуйста, помогите мне понять, как объединить виртуальные библиотеки Python 2.7 и Python 3 под одним и тем же uwsgi Emperor.
Ну, так как я не совсем был ошеломлен ответами, вот решение, которое я придумал сам:
Сначала я создал новый virtualenv с интерпретатором Python 3:
mkvirtualenv -p /usr/bin/python3 python3env
Затем я установил стандартный uwsgi из Pypi, который автоматически компилируется с помощью интерпретатора Python 3:
pip install uwsgi
Я создал каталог конфигурации /etc/uwsgi-python3
который содержит emperor.ini и подкаталог vassals, содержащий vassal.ini. Наконец, я добавил следующую строку в /etc/rc.local
/home/user/.virtualenvs/python3env/bin/uwsgi --ini /etc/uwsgi-python3/emperor.ini
Теперь там работает uwsgi Emperor, который использует интерпретатор Python 3 для своих вассалов. Это не мешает работе другого uwsgi Emperor, который уже работал и использует интерпретатор Python 2.7.
Я знаю, что это не оптимально, потому что я не использую подключаемую архитектуру интерпретатора, которая объяснено в документации (спасибо, Роберто! Не знаю, как я мог это не заметить). Однако он работает безупречно, и мне не пришлось трогать мою существующую установку uwsgi, обслуживающую множество производственных приложений.
Под osx я сделал вот так. Я удалил все uwsgi в своей системе (от brew from pip и т. Д.).
После этого я загрузил в / usr / local исходный код
wget https://projects.unbit.it/downloads/uwsgi-latest.tar.gz
tar zxvf uwsgi-latest.tar.gz
после
cd uwsgi-2.0.17
make PROFILE=nolang
Таким образом я создал исполняемый файл без плагинов для python.
После этого я сделал каждый плагин для каждой версии в моей системе:
PYTHON=python3.6 ./uwsgi --build-plugin "plugins/python python36"
PYTHON=python2.7 ./uwsgi --build-plugin "plugins/python python27"
PYTHON=python2.6 ./uwsgi --build-plugin "plugins/python python26"
Теперь у меня 3 плагина.
В моих файлах ini для императора я указал каталог плагинов и версию плагина для каждого файла
[uwsgi]
plugins-dir = /usr/local/uwsgi-2.0.17
plugin = python36
[uwsgi]
plugins-dir = /usr/local/uwsgi-2.0.17
plugin = python27
[uwsgi]
plugins-dir = /usr/local/uwsgi-2.0.17
plugin = python26
...
Я создал символическую ссылку на двоичный файл uwsgi в моей папке / usr / local
ln -s /usr/local/uwsgi-2.0.17/uwsgi /usr/local/bin/uwsgi
И после запуска император
uwsgi --emperor /PATH/TO/INI/FILES/FOLDER/
И вуаля, теперь я могу запускать проекты python26, python27 и python36 одновременно
Другое возможное решение - повторно использовать общесистемного «императора» и заменить вассала только новой версией. Таким образом, вам не нужно изобретать новые папки под /etc
ни запускать новые услуги для rc.local
.
uwsgi
через pip
в виртуальный.Отредактируйте /etc/uwsgi/apps-enabled/your-app.ini
следующим образом:
plugins=...
строка (потому что скомпилированный uwsgi
не поддерживает плагины).Добавьте строку:
unprivileged-binary-patch = /path/to/your/venv/bin/uwsgi
Это заставит императора uWSGI запустить свой собственный uwsgi
бинарный как вассал.
Перезагрузите приложение в императоре service uwsgi restart your-app
.
Последний шаг почему-то сообщает об ошибке перезапуска сервера:
* Starting app server(s) uwsgi
...fail!
Однако на самом деле новый вассал запускается нормально, как и все другие приложения. У меня не было времени отладить это.