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
  4. Устанавливаем unit
    apt-get update
    apt-get install unit
  5. Устанавливаем дополнительные пакеты, которые мы будем использовать
    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 -d@/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. Можно в рамках одного юнита объединить несколько приложений на разных языках (платформах).

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

Ссылки:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *