Nginx Unit

Не так давно от команды Nginx была представлена новая разработка Unit. Это Application Server, который позволяет запускать приложения на нескольких языках, при этом предоставляя простую конфигурацию и настройку посредством REST API. На данный момент Unit находится в стадии beta. Посмотрим же на основные возможности, которые предлагает этот продукт.

Установка

Поддерживаются следующие системы

  • Linux >= 2.6
  • FreeBSD >=9
  • Mac Os X
  • Solaris 11

Для Ubuntu установка достаточно простая

  1. Скачиваем ключ
  2. Добавляем ключ
apt-key add nginx_signing.key
3. Создаем файл /etc/apt/sources.list.d/unit.list следующего содержания
deb http://packages.nginx.org/unit/ubuntu/ xenial unit
deb-src http://packages.nginx.org/unit/ubuntu/ xenial unit
  • Устанавливаем unit
  • apt-get update
    apt-get install unit
  • Устанавливаем дополнительные пакеты, которые мы будем использовать
  • apt-get install python2.7 python3

    Я подготовил образ, его можно скачать с хаба докера

    docker pull miholeus/nginx-unit-python

    Настройка

    После установки unit пришло время настроить его и запустить наше приложение. Приложение напишем на python. Самый простой пример wsgi приложения:

    import sys
    def application(environ, start_response):
        body = sys.version.encode("utf-8")
        status = "200 OK"
        headers = [('Content-type','text/plain')]
        start_response(status, headers)
        return body

    Нам надо определить listeners и applications. Applications могут быть на одном из поддерживаемых unit языков. Listener определяет на каком ip-address и порту слушать выбранное приложение. Приложения указывают что надо запускать, основываясь на типе приложения и указанном пути.

    Сделаем тестовое приложение такого вида

    "test": {
         "type": "python",
         "workers": 10,
         "module": "wsgi",
         "user": "root",
         "group": "root",
         "path": "/apps/py"
     }

    Запустим наш контейнер

    docker run --name nginx_unit_python -v pwd/demo:/apps -p 8300:8300 miholeus/nginx-unit-python

    Выполним конфигурацию

    docker exec -ti nginx_unit_python curl -X PUT -d @/apps/python.json '127.0.0.1:8443'

    Проверим наше приложение

    curl 127.0.0.1:8300

    В ответ получим что-то вроде

    2.7.12 (default, Nov 20 2017, 18:23:56)
     [GCC 5.4.0 20160609]

    Давайте теперь добавим приложение, которое слушает порт 8400.

    Наш конфигурационный файл будет выглядеть следующим образом

    {
     "type": "python",
     "workers": 5,
     "module": "wsgi",
     "user": "root",
     "group": "root",
     "path": "/apps/flask"
     }

    Добавим эту конфигурацию в наш unit

    curl -X PUT [email protected]/apps/flask_app.json '127.0.0.1:8443/applications/flask_sample'

    Приложение использует фреймворк Flask. Поэтому придется установить его вручную. Сначала добавим pip в контейнер, а затем установим flask.

    apt-get install python-pip
    pip install flask

    Я не стал добавлять pip на этапе сборки в контейнер, можете сделать это самостоятельно.

    И наконец, внесем наши изменения для приложения в unit

    curl -X PUT -d '{"application":"flask_sample"}' '127.0.0.1:8443/listeners/*:8400'

    Само приложение так же простое

    # Файл wsgi.py
    from hello import application
    if name == "main":
        application.run()
    # Файл hello.py
    from flask import Flask
    application = Flask(name)
    @application.route("/")
    def hello():
        return "<h1 style='color:blue'>Hello From Flask!</h1>"
    if name == "main":
        application.run(host='0.0.0.0')

    Проверим наше приложение

    curl 127.0.0.1:8400

    Получим

    <h1 style='color:blue'>Hello From Flask!</h1>

    Мы легко можем менять наши приложения на лету. К примеру, на порт 8300 может повесить приложение с Flask. Или можно выключить какое-либо приложение

    curl -X DELETE '127.0.0.1:8443/listeners/*:8300'

    При этом все текущие сессии останутся активными, а новые запросы на 8300-й порт уже проходить не будут.

    Интеграция с Nginx

    Интеграция выполняется очень просто. Сначала создается upstream для нашего приложения

    upstream unit_backend {
     server 127.0.0.1:8300;
    }

    А затем основная конфигурация сервера

    server {
      location /static {
        root /var/www/files;
      }
      location / {
        proxy_pass http://unit_backend;
        proxy_set_header Host $host;
      }
    }

    Сам Unit на данный момент не поддерживает авторизацию, поэтому выставлять его открытым наружу нельзя.

    Я не рассматривал работу с другими типами приложений. Она ничем не отличается от приложений на python. Можно в рамках одного юнита объединить несколько приложений на разных языках (платформах).

    В целом решение получилось очень перспективным и оно обязательно найдет свою нишу в современных веб проектах.

    Ссылки:

    miholeus

    Leave a Reply

    2 Comments

    1. Привет. Сейчас хочу настроить сервер приложений для питона и вот nginx unit не хочет запускать flask-приложение из wsgi-файла. В чем проблема – не ясно. Flask установлен. В логах unit пишет:

      2018/04/03 18:22:36 [info] 20579#20579 “sample_flask” application started
      2018/04/03 18:22:36 [alert] 20579#20579 Python failed to import module “wsgi”
      2018/04/03 18:22:36 [notice] 15925#15925 process 20579 exited with code 1
      2018/04/03 18:22:36 [warn] 15928#15928 failed to start application “sample_flask”
      2018/04/03 18:22:36 [alert] 15928#15928 failed to apply new conf
      2018/04/03 18:23:57 [info] 20665#20665 “sample_flask” application started
      2018/04/03 18:23:57 [alert] 20665#20665 Python failed to import module “wsgi”
      2018/04/03 18:23:57 [notice] 15925#15925 process 20665 exited with code 1
      2018/04/03 18:23:57 [warn] 15928#15928 failed to start application “sample_flask”
      2018/04/03 18:23:57 [alert] 15928#15928 failed to apply new conf

    2. Проблема, скорее всего, в неправильном указании пути к wsgi файлу

    Leave a Reply

    Your email address will not be published. Required fields are marked *