Развертывание приложения Python WSGI с помощью веб-сервера CherryPy+Nginx

Вступление

Сервер CherryPy часто вызывает у разработчиков множество вопросов, и самые распространенные из них:

  • Зачем использовать веб-сервер Python CherryPy, если можно выбрать автономный сервер, написанный на языке C?
  • Разве CherryPy не фреймворк? Справится ли он с развертыванием приложений Bottle, Flask и т.п.?

Ответы на эти и многие другие вопросы можно найти в данной статье. Речь в ней пойдет о том, что такое CherryPy, а также о преимуществах его использования при развертывании веб-приложений. Кроме того, здесь можно найти полезные советы по развертыванию приложений Python с помощью веб-сервера CherryPy.

Что такое CherryPy и Nginx?

В целом, CherryPy – это минималистический веб-фреймворк Python. В данном контексте «минималистический» значит, что он поставляется без большого количества готовых компонентов. Минимализм подразумевает воздержание от навязывания разработчикам инструментов и приложений, таким образом предоставляя им возможность принимать самостоятельное решение. CherryPy (а также другие в этом отношении подобные ему фреймворки),  как правило, выполняет основные задачи (например, обрабатывает сессии, кэширование, загружает файлы и т.п.), оставляя выбор остальных программ и инструментов за разработчиком.

От других (в том числе и полноценных) фреймворков Python CherryPy отличает стремление его создателей предоставить готовый к работе (т.е. разработке) и  развертыванию комплект (пакет) в качестве автономного приложения. Для достижения этой цели веб-приложению, конечно, необходим надежный веб-сервер. Потому CherryPy имеет собственный совместимый с HTTP/1.1 веб-сервер WSGI, что делает его полностью готовым к работе и качественно выделяет среди остальных фреймворков.

Кратко о веб-сервере WSGI CherryPy

Веб-сервер Python CherryPy – компактный сервер, поставляемый с одноименным фреймворком. Проект CherryPy описывает его как «готовый к производству высокоскоростной общий HTTP-сервер». Это модульный компонент, который может быть использован для обслуживания любого веб-приложения Python WSGI.

Особенности веб-сервера CherryPy

  • Это компактный и простой в использовании сервер Python;
  • Простой в настройке и работе;
  • Легко адаптируемый и быстрый;
  • Масштабируемый;
  • Поддерживает SSL.

Развертывание на веб-сервере WSGI CherryPy

Благодаря невероятно гибким техническим требованиям WSGI создать веб-сервер не составляло труда. На протяжении многих лет было создано огромное количество серверов; некоторые из них достигли определенного уровня популярности, но большинство так и не вышло за пределы машины разработчика. На сегодня существует огромное количество вариантов, и, в основном, они практически ничем не отличаются.

Как было сказано в начале статьи, веб-сервер CherryPy вызывает у разработчиков множество вопросов.

Почему для развертывания приложения нужно использовать сервер CherryPy?

Ответ на этот вопрос достаточно прост: с ним легко и удобно работать. Сервер CherryPy, обслуживающий веб-приложения WSGI, исключительно прост в использовании.  Он способен сэкономить огромное количество времени и сил, поскольку его запуск занимает всего пару минут. Кроме того, он настраиваем под пользователя, что дает возможность запускать многозадачные и многопоточные проекты с помощью одного файла (например, server.py).

Запомните: для многозадачных проектов необходимо настроить несколько серверов.

Конечно, никакой гарантии, что в течение нескольких минут после выхода приложения в Интернет оно будет получать десятки тысяч запросов в секунду; потому использовать несколько серверов для балансировки нагрузки просто нецелесообразно, в таком случае лучше продолжить разработку приложения, чем тратить время на решение совместимости библиотек, оптимизацию процессора, устранение аварий и т.д.

Веб-сервер CherryPy в сочетании с Nginx как фронтальный инвертированный прокси – по-настоящему надежный способ обслуживания веб-приложений Python WSGI, разработанных на основе Bottle, CherryPy, Django, Flask, Pyramid или любого другого фреймворка.

Запомните: подобная архитектура (см. ниже) позволяет легко выполнить как горизонтальное масштабирование (увеличение количества серверов), так и вертикальное (увеличение производительности каждого сервера). Здесь так называемым «узким местом», вероятно, будет база данных. Вот почему не стоит пытаться оптимизировать систему, не имея ни малейшего намека на вероятность экстремальных нагрузок. И даже тогда адекватный механизм кэширования, вероятно, решит большинство проблем.

Nginx как обратный прокси + CherryPy

Nginx – это веб-сервер/инвертированный прокси очень высокой производительности.

Он стал популярен потому, что он относительно легок в использовании, мало весит и легко расширяется (с помощью дополнений и плагинов). Благодаря своей архитектуре он способен обрабатывать множество запросов (практически без ограничений), с которыми более старые альтернативы справляются с трудом (в зависимости от загрузки приложения или веб-сайта).

Запомните: технически обработка соединения означает, что соединение не только установлено, но и постоянно обслуживается. То есть, приложение и база данных должны правильно работать, чтобы Nginx мог обслуживать ответы клиентов, не выводя сообщений об ошибках.

Почему нужно использовать Nginx как инвертированный прокси?

Хотя сервер приложений (в данном случае веб-сервер WSGI CherryPy) может обслуживать статические файлы (например, JavaScript, CSS, изображения и т.д.) вместе с ответами от приложений, лучше установить инвертированный прокси-сервер (как Nginx), который будет обслуживать эти файлы и управлять соединениями (запросами). Обрабатывая запросы от клиентов, это существенно снизит нагрузку на сервер приложений, и тем самым улучшит общую производительность.

По мере роста приложения появится необходимость его оптимизации и распределения на несколько серверов (VPS), чтобы иметь возможность обрабатывать больше соединений одновременно (и обеспечить более надежную архитектуру в целом). Инвертированный прокси-сервер выполняет все это с самого начала.

Расширяемость Nginx (то есть, кэширование наряду с отказоустойчивостью и другими механизмами) – еще одно огромное преимущество этого сервера перед более простыми серверами приложений.

Пример базовой архитектуры сервера:

Client Request ----> Nginx (Reverse-Proxy)
________________________|
_______________________/|\
______________________| | `-> App. Server I. 127.0.0.1:8081
______________________| `--> App. Server II. 127.0.0.1:8082
_______________________`----> App. Server III. 127.0.0.1:8083

Примечание: когда приложение прослушивает входящие соединения на 127.0.0.1, доступ к нему можно получить только локально. При использовании 0.0.0.0, оно также будет принимать соединения извне.

Подготовка сервера к производству

Данный раздел посвящен подготовке виртуального сервера к производству (то есть, к развертыванию приложения).

Для начала нужно:

  • Обновить операционную систему по умолчанию;
  • Скачать и установить общие инструменты Python (pip и virtualenv);
  • Создать виртуальную среду, которая будет содержать приложение, а также его зависимости (uWSGI).

Примечание: здесь приведены краткие инструкции. Более подробную информацию можно получить, прочитав статью «Общие инструменты Python: использование virtualenv, установка пакетов с помощью pip и управление пакетами».

Обновление операционной системы

Примечание: в данном руководстве все дальнейшие действия выполнены на новом сервере с использованием последних версий операционных систем. Теоретически, данные инструкции сработают должным образом на любом другом VPS. Тем не менее, старую версию системы, которая используется долгое время, рекомендуется сменить на новую.

Итак, чтобы обеспечить использование последней доступной версии необходимых приложений, необходимо обновить систему.

Для обновления систем на основе Debian (Ubuntu, Debian):

aptitude    update
aptitude -y upgrade

Для обновления систем на основе RHEL (CentOS):

yum -y update

Установка Python, pip и virtualenv

Примечание для пользователей CentOS / RHEL

По умолчанию CentOS / RHEL поставляются почти чистыми. Набор инструментов на данном сервере предоставляется не для запуска приложений пользователя, а для питания инструментов системы (например, yum).

Чтобы подготовить систему CentOS, нужно установить (то есть, скомпилировать из исходного кода) Python, а затем установить pip и virtualenv при помощи специального интерпретатора Python.

Чтобы получить подробную информацию по установке Python 2.7.6 и 3.3.3 на CentOS 6.4 и 5.8, прочтите данную статью.

На Ubuntu и Debian последняя версия интерпретатора Python (который можно использовать) поставляется по умолчанию. Потому все, что осталось установить:

  • python-dev – средства разработки
  • pip- для управления пакетами
  • virtualenv- для создания изолированной виртуальной среды

python-dev: общесистемный пакет, который содержит расширенные средства разработки для построения модулей Python.

Для установки python-dev с помощью aptitude запустите:

aptitude install python-dev

pip: менеджер пакетов, который помогает устанавливать необходимые пакеты приложений.

Выполните следующие команды для установки pip:

curl https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py | python -
curl https://raw.github.com/pypa/pip/master/contrib/get-pip.py | python -
export PATH="/usr/local/bin:$PATH"

На данном этапе могут понадобиться привилегии sudo.

Virtualenv:

Приложение Python вместе со всеми его зависимостями рекомендуется хранить в отдельной среде. Проще говоря, среда – это изолированное место (каталог) для размещения пакетов веб-приложения. Для этого используется инструмент под названием virtualenv.

Чтобы установить virtualenv с помощью pip, используйте:

sudo pip install virtualenv

Создание автономной виртуальной среды Python

Подготовив все необходимые инструменты, можно перейти к созданию среды для развертывания приложения.

Запомните: если на локальной машине разработки нет virtualenv (или виртуальной среды), необходимо создать ее и переместить туда приложение и его зависимости.

Для начала нужно создать папку, которая будет содержать виртуальную среду и модуль приложения:

mkdir my_app

Конечно, папку можно назвать согласно требованиям разработчика или проекта.

Затем нужно войти в эту папку и создать в ней новую виртуальную среду:

cd my_app
virtualenv my_app_venv

Виртуальную среду также можно назвать как угодно.

Теперь создайте новую папку для модуля приложения Python:

mkdir app

Активируйте интерпретатор внутри виртуальной среды:

source my_app_venv/bin/activate

Пожалуйста, убедитесь в том, что заменили имя виртуальной среды «my_app_venv» именем своей venv (в случае, если она имеет другое имя).

Теперь главный каталог развертывания приложений должен выглядеть так:

my_app              # Main Folder to Contain Everything Together
|
|=== my_app_venv  # V. Env. folder with the Python Int.
|=== app          # Your application module
|..
|.

Загрузка и установка CherryPy

Чтобы установить CherryPy с помощью pip, запустите следующее:

pip install cherrypy

Примечание: если виртуальная среда активна, CherryPy будет установлен внутри этой среды. В противном случае установка будет глобально доступной (т.е. общесистемной), что не рекомендуется. Всегда используйте virtualenv и на сервере, и на машине разработки.

Загрузка и установка Nginx

Примечание для пользователей CentOS / RHEL

Приведенные ниже инструкции недействительны для системы CentOS. При необходимости, пожалуйста, обратитесь к руководству «Как установить nginx на CentOS 6 с помощью yum».

Запустите следующую команду, чтобы установить Nginx с помощью aptitude, менеджера пакетов по умолчанию:

sudo aptitude install nginx

Чтобы запустить Nginx, используйте:

sudo service nginx start

Чтобы выключить Nginx, запустите:

sudo service nginx stop

Чтобы перезапустить Nginx:

sudo service nginx restart

Примечание: Nginx нужно перезапускать после внесения любых изменений в конфигурации, чтобы новые настройки вступили в силу.

Чтобы получить дополнительные инструкции по установке Nginx на Ubuntu, читайте статью «Установка Nginx на Ubuntu 12.04 LTS».

Обслуживание приложений Python WSGI с помощью CherryPy

Данный раздел демонстрирует работу WSGI-приложений на сервере CherryPy. Для этого нужно предоставить серверу callable объект приложения WSGI (например, application = (..)) как точку входа.

Что такое WSGI?

Очень упрощенно говоря, WSGI представляет собой интерфейс между веб-сервером и самим приложением. Он устанавливает стандартное соединение между различными серверами и приложениями (фреймворками), что обеспечивает их взаимозаменяемость в случае необходимости (например, переход от среды разработки к производственной среде), что очень важно в настоящее время.

Примечание: для получения дополнительной информации о WSGI и веб-серверах Python читайте статью “Сравнение веб-серверов для приложений на основе Python“.

Callable объект приложения WSGI: wsgi.py

Как уже было сказано, веб-серверам, запущенным на WSGI, необходим объект приложения.

Для большинства фреймворков и приложений данный объект приложения (или callable) состоит из:

  • файла wsgi.py, который используется сервером;
  • и файла server.py, который включает в себя объект приложения и использует его для обслуживания.

Для начала создайте образец wsgi.py для использования его сервером CherryPy.

Конечно, вместо имени «wsgi.py» можно выбрать любое другое имя. Но имя wsgi.py считается стандартным и используется чаще всего (например, в Django).

Итак, можно приступить к созданию файла wsgi.py, который будет содержать базовое приложение WSGI.

Чтобы создать данный файл с помощью текстового редактора nano, запустите команду:

nano wsgi.py

Теперь нужно переместить (скопировать и вставить) в него базовый код приложения WSGI (замените его собственным callable приложения):

def application(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return ["Hello!"]

Каждый раз, когда поступает запрос, сервер использует этот callable приложения, чтобы запустить его обработчики запросов (контроллеры), анализируя URL (например, mysite.tld/controller/method/variable).

Разместив код приложения в файле, нажмите CTRL+X, чтобы сохранить файл в папке my_app наряду с виртуальной средой и модулем приложения (нажмите Y для подтверждения).

Примечание: данное WSGI-приложение является самым базовым примером. Необходимо заменить данный блок кода, чтобы внести свой собственный объект приложения.

Теперь главный каталог развертывания приложения выглядит следующим образом:

my_app              # Main Folder to Contain Everything Together
|
|=== my_app_venv  # V. Env. folder with the Python Int.
|=== app          # Your application module
|
|--- wsgi.py      # File containing application callable
|..
|.

Написание скрипта для веб-сервера CherryPy: server.py

Итак, теперь в текущем рабочем каталоге (например, в my_app) нужно создать скрипт Python, который:

  • Содержит приложение
  • Создает один или несколько экземпляров веб-сервера CherryPy
  • Содержит конфигурации этих экземпляров сервера
  • Запускает и останавливает серверы

Существует несколько способов создания такого скрипта; в примере ниже используется простой, легко конфигурируемый вариант.

С помощью nano создайте файл server.py, который будет содержать скрипт запуска веб-сервера:

nano server.py

Скопируйте и вставьте в данный файл следующий фрагмент кода:

# Import your application as:
# from wsgi import application
# Example:
from wsgi import application
# Import CherryPy
import cherrypy
if __name__ == '__main__':
# Mount the application
cherrypy.tree.graft(application, "/")
# Unsubscribe the default server
cherrypy.server.unsubscribe()
# Instantiate a new server object
server = cherrypy._cpserver.Server()
# Configure the server object
server.socket_host = "0.0.0.0"
server.socket_port = 8080
server.thread_pool = 30
# For SSL Support
# server.ssl_module            = 'pyopenssl'
# server.ssl_certificate       = 'ssl/certificate.crt'
# server.ssl_private_key       = 'ssl/private.key'
# server.ssl_certificate_chain = 'ssl/bundle.crt'
# Subscribe this server
server.subscribe()
# Example for a 2nd server (same steps as above):
# Remember to use a different port
# server2             = cherrypy._cpserver.Server()
# server2.socket_host = "0.0.0.0"
# server2.socket_port = 8081
# server2.thread_pool = 30
# server2.subscribe()
# Start the server engine (Option 1 *and* 2)
cherrypy.engine.start()
cherrypy.engine.block()

Сохраните изменения и закройте файл, нажав CTRL+X и Y для подтверждения.

Теперь главный каталог развертывания приложения выглядит так:

my_app              # Main Folder to Contain Everything Together
|
|=== my_app_venv  # V. Env. folder with the Python Int.
|=== app          # Your application module
|
|--- wsgi.py      # File containing application callable
|--- server.py    # Python executable to launch the server
|..
|.

Запуск сервера

Чтобы начать обслуживать приложение, нужно запустить server.py с помощью установки Python.

Чтобы запустить сервер согласно конфигурациям, выполните:

python server.py

Примечание: это запустит скрипт при помощи активированного интерпретатора Python, поскольку виртуальная среда все еще активна. Если же среда дезактивирована, необходимо указать путь: my_app/bin/python server.py.

Это запустит сервер в приоритетном режиме. Чтобы отключить его, нажмите клавиши CTRL + C.

Чтобы запустить сервер в фоновом режиме, выполните следующую команду:

python server.py &

Чтобы вернуться в командную строку, просто нажмите Enter. При этом приложение будет все еще запущено.

Запуская приложение в фоновом режиме, используйте менеджер процессов (например, htop), чтобы прервать его.

Настройка Nginx

Настроив и запустив CherryPy, нужно настроить Nginx, чтобы он мог взаимодействовать с сервером CherryPy при запуске приложения. Для этого нужно отредактировать nginx.conf, конфигурационный файл Nginx.

Чтобы открыть данный файл в редакторе nano, запустите:

sudo nano /etc/nginx/nginx.conf

Затем замените содержимое файла приведеными ниже конфигурациями, чтобы Nginx был запущен как инвертированный прокси и взаимодействовал с приложением.

Примечание: чтобы активировать поддрежку SSL, пожалуйста, прочтите статью «Создание SSL-сертификата на Nginx».

Пример конфигураций для веб-приложения:

worker_processes 1;
events {
worker_connections 1024;
}
http {
sendfile on;
gzip              on;
gzip_http_version 1.0;
gzip_proxied      any;
gzip_min_length   500;
gzip_disable      "MSIE [1-6]\.";
gzip_types        text/plain text/xml text/css
text/comma-separated-values
text/javascript
application/x-javascript
application/atom+xml;
# Configuration containing list of application servers
upstream app_servers {
server 127.0.0.1:8080;
# server 127.0.0.1:8081;
# ..
# .
}
# Configuration for Nginx
server {
# Running port
listen 80;
# Settings to serve static files
location ^~ /static/  {
# Example:
# root /full/path/to/application/static/file/dir;
root /app/static/;
}
# Serve a static file (ex. favico)
# outside /static directory
location = /favico.ico  {
root /app/favico.ico;
}
# Proxy connections to the application servers
# app_servers
location / {
proxy_pass         http://app_servers;
proxy_redirect     off;
proxy_set_header   Host $host;
proxy_set_header   X-Real-IP $remote_addr;
proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header   X-Forwarded-Host $server_name;
}
}
}

Завершив редактирование конфигураций, нажмите CTRL+X, чтобы сохранить изменения и выйти, а затем Y для подтверждения.

Для перезапуска Nginx используйте:

sudo service nginx stop
sudo service nginx start

Готово!

Tags: , , , , , , , , , , , , ,

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