Назад | Перейти на главную страницу

Различные версии Python под одним и тем же uwsgi Emperor?

Я управляю 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.

  1. Установить uwsgi через pip в виртуальный.
  2. Отредактируйте /etc/uwsgi/apps-enabled/your-app.ini следующим образом:

    • Удалить plugins=... строка (потому что скомпилированный uwsgi не поддерживает плагины).
    • Добавьте строку:

      unprivileged-binary-patch = /path/to/your/venv/bin/uwsgi
      

      Это заставит императора uWSGI запустить свой собственный uwsgi бинарный как вассал.

  3. Перезагрузите приложение в императоре service uwsgi restart your-app.

Последний шаг почему-то сообщает об ошибке перезапуска сервера:

 * Starting app server(s) uwsgi
   ...fail!

Однако на самом деле новый вассал запускается нормально, как и все другие приложения. У меня не было времени отладить это.