14 февраля 2011 в 12:48

Автоматизируем выкладку django-проектов на сервер

Настраивать VDS'ки для выкладки django-проектов довольно утомительно бывает, да и легко что-то забыть (т.к. делаешь это не каждый день). Гораздо лучше, когда этот процесс автоматизирован: с меньшими усилиями можно получить правильно настроенный проект и набор команд для работы с ним.

Существую разные подходы к этому процессу: специфичные для питона (fabric, buildout) или неспецифичные (puppet, Chef, наборы shell-скриптов и т.д.).

Подход fabric — локально выполняемый скрипт ходит по ssh на сервер и выполняет там команды. Этот подход довольно прямолинеен и прост в отладке, тем и хорош (обзор на хабре). Из разнообразных команд fabric постепенно вырисовался велосипед под названием django-fab-deploy. Это набор fabric-скриптов, который умеет настраивать серверы под Debian Lenny или Squeeze, а потом с минимальными усилиями разворачивать там django-проекты и управлять этими проектами в дальнейшем.

С выходом Debian Squeeze взялся за django-fab-deploy посерьезнее, поправил некоторые шероховатости и теперь, думаю, самое время об этом проекте рассказать. У проекта есть документация, тут будет краткий пересказ с лирическими отступлениями.


Общие принципы:
  • проекты изолировны с помощью virtualenv;
  • зависимости управляются с помощью requirements-файлов pip;
  • все общение с сервером ведется по ssh и должно быть автоматизировано ( => повторяемо);

Серверная часть:
  • поддерживаются Debian Lenny и Debian Squeeze;
  • способ запуска python-кода: apache + mod_wsgi + nginx перед ними;
  • на одном VPS/сервере может крутиться сколько угодно проектов, управляемых django-fab-deploy;
  • один проект может быть выложен на несколько серверов (в том числе с разными настройками).

Главными критериями для выбора способа развертывания были стабильность/надежность, и тут связке apache+mod_wsgi+nginx на данный момент равных нет. Думаю, поддержку убунты добавить будет не сложно, но чего об этом говорить-то, раз поддержки убунты прямо сейчас нет (сам убунтой не пользуюсь).

Проекту хорошо бы хранится в системе контроля версий (сейчас поддерживается mercurial). Имеется полузаглушка с загрузкой/распаковкой tar.gz на случай, если проект не в VCS; она работает, но в продакшн-режиме я ее не проверял (незачем было), и есть вероятность, что проявятся какие-нибудь особенности.

Автоматизируем развертывание


Ниже описан базовый способ развертывания сервера, если он по каким-то причинам не подходит, то не страшно: django-fab-deploy — просто набор скриптов; их можно использовать по частям, или какие-нибудь полезности подсмотреть, или отправить патч, или просто статью почитать.

Предполагается, что у нас есть чистый Debian-сервер (можно и не «чистый», об этом позже), настроен ssh-доступ по публичному ключу к root.

Пожалуйста, не используйте VPS на OpenVZ, т.к. на них ограничивается VIRT вместо RSS и поэтому куча софта (в том числе апач и mysql+innodb) под OpenVZ ест гораздо больше памяти, чем под xen/kvm (в 10 раз — да легко).

Подготовка проекта

Джанго-проекты и так часто используют какую-нибудь разновидность трюка с 'local_settings.py', лежат в системе контроля версий, в репозитории имеют файлик с pip-зависимостями и папку с настройками для веб-сервера. Ничего кроме этого django-fab-deploy, по сути, и не требует. Дальше — детали.

1. Устанавливаем django-fab-deploy и его зависимости:

pip install django-fab-deploy
pip install jinja2
pip install -e git+git://github.com/bitprophet/fabric.git#egg=Fabric-dev

django-fab-deploy не работает с Fabric 0.9.x, Fabric должен быть установлен с github'а.

2. Создаем файл fabfile.py в корне проекта. В этом файле должна быть одна или несколько функций, настраивающих параметры сервера. Ну и т.к. это обычный fabric-скрипт, там могут быть любые другие (специфичные для проекта) команды. Пример:

# my_project/fabfile.py
from fab_deploy import *

def my_site():
    env.hosts = ['my_site@example.com']
    env.conf = dict(
        DB_PASSWORD = 'password',
        PROCESSES = 2,

        # раскомментировать, если на сервере Debian Squeeze; по умолчанию стоит значение 'lenny'
        # OS = 'squeeze',

        # раскомментировать, если проект не хранится в системе контроля версий (по умолчанию - 'hg')
        # VCS = 'none',
    )
    update_env()

my_site()


Обратите внимание на env.hosts. Тут есть фишка: укажите в качестве пользователя (my_site) название своего проекта (оно должно быть правильным названием переменной в python — без тире и пробелов). Не страшно, если такого пользователя нет, django-fab-deploy сможет его создать и настроить ssh-доступ позже. В любом случае, иметь отдельного пользователя для каждого проекта — хорошая идея.

В env.conf применяются некоторые соглашения для упрощения всего. Например, название БД (DB_NAME) по умолчанию совпадает с названием экземпляра проекта (INSTANCE_NAME), которое, в свою очередь, совпадает с пользователем из env.hosts.

Чтобы узнать больше о том, что и как можно настраивать тут, см. документацию по fabfile api.

3. Создадим шаблоны настроек для веб-сервера и т.д.:

django-fab-deploy config_templates

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

В шаблонах настроек можно использовать переменные, заключенные в {{ }} (шаблонизатор тут — jinja2). Эти переменные будут заменены на значения из словаря env.conf при выкладке шаблонов на сервер.

4. Создайте config.server.py в корне проекта. Этот файл станет файлом config.py на сервере. Пример:

# my_project/config.server.py

DEBUG = False
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': '{{ DB_NAME }}',
        'USER': '{{ DB_USER }}',
        'PASSWORD': '{{ DB_PASSWORD }}',
        'HOST': '',
        'PORT': '',
        'OPTIONS': {
            "init_command": "SET storage_engine=INNODB"
        },
    }
}


Создайте также config.py с локальными настройками для разработки. Импортируйте config.py в settings.py:
# Django settings for my_project project.
# ...
from config import *
# ...

Трюк широко известный, часто config.py называют также local_settings.py. Этот файл должен быть добавлен в игнорируемые в VCS (если VCS используется).

Как можно было заметить, config.server.py — тоже шаблон (как и файлы из папки config_templates), в него тоже будут подставляться переменные из env.conf.

5. Создайте папку 'reqs' в корне проекта. Пример такой папки можно получить, выполнив следующую команду из корня проекта:

django-fab-deploy example_reqs

В этой папке должны лежать текстовые файлы с pip-зависимостями. Один файл имеет особое значение: reqs/all.txt. Это главный файл с зависимостями, все пакеты оттуда будут установлены при развертывании. Там можно или все зависимости просто перечислить, или (лучше) подключать другие файлы с зависимостями через опцию “-r”.

Есть еще команда django-fab-deploy generate_reqs, которая создает папку reqs с одним файлом all.txt, в котором перечислены все установленные в локальном окружении питоньи пакеты (то, что показывает pip freeze).

После того, как шаги 1-5 выполнены, проект должен выглядеть как-то так:

my_project
    ...
    config_templates 
        ...
    reqs             
        all.txt      
        ...     

    fabfile.py      
    config.py      
    config.server.py 
    settings.py
    manage.py

Если все так, то проект готов.

Подготовка сервера

1. Если в env.hosts был указан несуществующий пользователь, то создадим его и настроим ssh-доступ по ключу, вручную или вот так (понадобится файл с вашим публичным ключом):

fab create_linux_account:"/home/kmike/.ssh/id_rsa.pub"

Проверяем, что ssh работает:

ssh my_site@example.com

2. Настроим БД. Если БД уже настроена вручную (например, проект уже работает), то ничего делать не нужно. django-fab-deploy сейчас умеет устанавливать mysql и создавать пустую базу под проект:

fab mysql_install
fab mysql_create_db

mysql_install ничего не делает, если mysql уже установлен на сервер. Если mysql не установлен, то он устанавливается, а пароль для mysql-пользователя root выставляется в env.conf['DB_PASSWORD'].

mysql_create_db создает пустую базу с названием env.conf['DB_NAME'] (в нашем примере это будет имя пользователя из env.hosts).

Если используется не mysql или пользователь mysql — не root, то лучше сейчас все руками сделать. А еще лучше — автоматизировать (написать fabric-скрипт для этого) и отправить патч в django-fab-deploy.

3. Все, сервер готов. Можно скрестить пальцы и запустить команду из корня проекта:

fab full_deploy

Если все было сделано правильно, сайт должен заработать.

Эта команда:
  • установит необходимые системные пакеты
  • создаст virtualenv и установит туда питоньи зависимости
  • настроит апач и nginx
  • загрузит проект на сервер
  • выполнит syncdb и migrate

Исходные коды будут лежать в ~/src/<INSTANCE_NAME>, virtualenv будет помещен в ~/envs/<INSTANCE_NAME>.

django-fab-deploy отключит сайты «default» для апача и nginx'а, а также станет командовать апачевским ports.conf (апач больше не будет слушать 80 порт). Если на сервере крутились другие сайты под апачем, то они станут недоступными из-за этого. Если наружу торчал только nginx, то все должно быть хорошо — django-fab-deploy ничего хитрого с сервером не делает.

Управление сервером


Залить изменения на сервер и применить их: fab push

Еще пример (выложить изменения на сервер prod, при этом обновить зависимости и выполнить миграции): fab prod push:pip_update,migrate

Обновить настройки веб-сервера: fab setup_web_server
Обновить настройки джанги (config.server.py): fab update_django_config

Полный список команд можно найти в документации. Если хочется чего-то более высокоуровнего (в духе — запустил fab redeploy и все сразу обновилось, и код, и настройки, и зависимости, и миграции выполнились) — можно легко написать свою fab-команду как обертку над базовыми командами. Если команда push делает слишком много (она, например, запускает тесты по умолчанию), то не стесняйтесь — гляньте на код и напишите в своем fabfile.py более подходящую версию. Если считаете какой-то такой эксперимент полезным и удачным — открывайте тикет в баг-трекере.

Аналоги


Наиболее близкий аналог django-fab-deploy — woven. Судя по всему, тоже отличная штука. Woven ориентирован на Ubuntu, Debian поддерживается примерно как Ubuntu в django-fab-deploy: «вроде должно работать с небольшими изменениями, но никто не знает точно». Начинали мы делать все примерно в одно и то же время, там сначала была какая-то дичь на классах, потом они все упростили. Продвинулись они подальше. С другой стороны, в django-fab-deploy в несколько раз меньше исходного кода, он поменьше и попроще, и останется таким.

Похожие проекты много кто делает. По гитхабу/битбакету поискал недавно, и в djangopackages еще 11 штук аналогов добавил (разной степени проработанности), можно тут глянуть сравнительную табличку: djangopackages.com/grids/g/deployment

Ссылки


Актуальную документацию всегда можно найти тут: packages.python.org/django-fab-deploy
Репозиторий с исходным кодом и баг-трекером: bitbucket.org/kmike/django-fab-deploy

Подключайтесь: используйте, исправляйте, пишите замечания, предложения, как все улучшить и т.д.

Описание в статье относится к версии 0.4 и может устареть; читайте, по возможности, документацию.

Не обязательно пользоваться именно django-fab-deploy, можно писать свои скрипты с 0, использовать woven, buildout или что угодно. Только все же перед тем, как писать все с 0, лучше, понятно, сделать «домашнюю работу» и посмотреть, как реализованы существующие проекты.

Главный совет — автоматизируйте как-то процесс настройки сервера и выкладки изменений даже для простейших проектов, это не сложнее ручной настройки и многократно окупается в дальнейшем.
Коробов Михаил @kmike
карма
339,7
рейтинг 0,0
Пользователь
Похожие публикации
Самое читаемое Разработка

Комментарии (30)

  • +1
    «Главными критериями для выбора способа развертывания были стабильность/надежность, и тут связке apache+mod_wsgi+nginx на данный момент равных нет.»
    Вот тут можно было бы сильно поспорить с вами в сторону связки Cherokee+UWSGI+nginx (хотя и без него отлично), но толку в споре мало, стоит лишь отметить, что стабильность/надежность данной связки так же весьма и весьма на высоте.
    За статью спасибо, будет полезна начинающим Django-деплоерам и не только.
    • +1
      равно как и fastcgi + nginx через flup. Работает уже давно так.
    • 0
      Угу, согласен, и uwsgi, и gunicorn, и fastcgi — способы хорошие и надежные, и используются в куче мест в продакшне. Ничего плохого про них сказать не могу. При всем при этом апач+mod_wsgi остается самым популярным способом запуска джанги (например, вот тут немного статистики: www.djangosites.org/stats/ — под апачем больше 70%, под чероки — меньше 1%. ). С ним уж точно все понятно, на все грабли давно наступили, много людей имеет опыт настройки этой связки, пакеты лежат в репозиториях операционных систем, нет необходимости разбираться с авто-запуском всего хозяйства и перезапуском процессов (завершившихся или зависших).

      Я рассматривал gunicorn как альтернативу apache+mod_wsgi, но не из-за незначительных преимуществ в скорости и т.д., а из-за того, что можно было бы пользовательский апач не трогать, а gunicorn прямо в virtualenv устанавливать. Но трогать апач придется в любом случае, т.к. он не должен слушать 80 порт, так что смысла особого что-то менять сейчас пока не вижу.
      • 0
        Тут да… в плане популярности и перевеса в сторону, пусть относительной, но простоты конфигурации, статистическое преимущество, конечно же, явное.
      • 0
        Учтите, что nginx не поддерживает HTTP/1.1 для proxy_pass, так что способ хоть и самый популярный, но и самый неудачный, с точки зрения потребления ресурсов и производительности.

        Также вызывает недоумение использование MySQL, вместо PostgreSQL, стандартной и рекомендуемой для django.
        • 0
          Мне кажется, насчет nginx Вы заблуждаетесь. Nginx не умеет keep-alive в сторону бэкенда, поэтому пишут, что он http 1.1 не поддерживает в эту сторону. Но keep-alive в сторону бэкенда и не нужен. А наоборот, противопоказан. Бэкенду лучше с запросом разобирался поскорее и ресурсы бесполезно не тратить. См., например, тут. А наружу nginx 1.1 умеет — для передачи той же статики новые соединения открываться не будут.

          Насчет MySQL — так уж сложилось, что его использую. Соответственно и команды были для него. На mysql почти ничего не завязано (создание и настройку базы специально вынес из стандартного процесса установки), так что ничто не мешает написать свои fab-команды для postgres (буду рад патчам).
          • 0
            По ссылке верно написано: «avoiding the TCP setup/teardown overhead», а что касается «idle HTTP server just consumes RAM that an active one should be using», то:
            1) это зависит главным образом от настройки, и не факт, что без keep-alive у вас ничего простаивать не будет, в конце-концов воркеры апача так и будут висеть, какое-то минимальное количество;
            2) это куда лучше, чем бесконечный старт-стоп воркеров, и виделение-освобождение памяти туда-сюда, все это весьма затратные операции;
            … а учитывая, что память ресурс дешевый, и то количество которое там расходуется, оно весьма скромно. Ну и да, вообще-то смешно говорить об экономии памяти, на фоне того, что вы apache запускаете.

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

            Популярность связки с использованием apache объясняется исключительно тем, что так проще shared-хостнигам, клиенты могут править .htaccess и прочие плюшки за счет апача, что в общем-то также сказывается негативно на производительности, но в данном случае главное объем возможностей, которые можно предоставить клиенту.
            • 0
              Проблема с воркерами не в том, что они висят (они и так висят в памяти при запуске через daemon mode), а в том, что при keep-alive они не могут обрабатывать соседние запросы и могут от этого закончиться.

              Оверхед апача — несколько мегабайт на сайт ( grab.by/90Ax — вот пример, 2.9M RSS, это стандартный апач из дебиана без всякой настройки специальной) — это висящий в памяти управляющий процесс, от которого запускается mod_wsgi в daemon_mode. Оверхед mod_wsgi — несколько сотен килобайт на процесс, это C-код, сомневаюсь, что у fastcgi через flup (написанного на python) и т.д. оверхед меньше. О чем речь?

              Апач в случае джанги выбирают из-за mod_wsgi, который умеет все: прождать и следить за процессами и тредами, втч не только запускать умершие, но и перезапускать повисшие, не инициировать интерпретатор без необходимости, перезапускать все хозяйство при изменении времени у wsgi-файла, ограничивать потребление памяти и CPU, перезапускать процессы, которые потребляют слишком много CPU и тд.
              • 0
                «а в том, что при keep-alive они не могут обрабатывать соседние запросы»
                Это почему же вы так решили? Те http соединения которые nginx устанавливает с backend-ом никак не привязаны к соединению с клиентом, этим занимается отдельный модуль (HttpProxyModule), с тем же успехом он мог бы держать некий пул открытых соединений и их использовать, обрабатывая запросы от разных клиентов в рамках одного keep-alive соединения.

                Overhead апача это не только дополнительный расход памяти на мастер-процесс и каждый воркер, это еще выполнение всей внутренней апачевской логики на каждый запрос, разбор http-заголовков, дерганье всех внутренних хэндлеров.
                • 0
                  У mod_wsgi/daemon_mode нет дополнительного расхода памяти на каждый воркер, обусловленного апачем, т.к. воркерами (процессами и тредами) он управляет сам, апач со своими модулями и т.д. в воркеры не загружается (в отличие от того же mod_python).

                  Ok, с keep-alive согласен.

                  Я правильно т.е. понимаю, что в сухом остатке мы имеем все-таки не дикий расход памяти или какие-то другие страшные вещи, а лишь оверхед по разбору апачем заголовков и установке соединений через localhost?

                  Этот оверхед, конечно, есть, но в абсолютных величинах — несколько тысяч запросов в секунду через локалхост апач уж обработает. Если кто-то сделает это вдвое быстрее, выигрыш будет измеряться, похоже, в долях ms, нет?
                  • 0
                    nichol.as/benchmark-of-python-web-servers — при правильном подходе к делу выигрыш можно вполне ощутимый получить.
                    • 0
                      Вопрос в том, правильный ли это подход — делать бенчмарки «тупых» хеллоу-вордов и на основе них выбирать способ запуска приложений.

                      blog.ianbicking.org/2010/03/16/web-server-benchmarking-we-need/

                      Слабо, например, представляю приложение, которому будут жать 2000 хеллоувордов/сек от mod_wsgi из теста. В то же время, можно вполне себе можно представить сервер, умерший наглухо из-за того, что 0.01% запросов вызывает сегфолты, а сервер не умеет эту ситуацию обрабатывать, постепенно забивая воркеры, пока все не застопорятся. Поэтому мне кажется, что чуть большая уверенность в надежности и проверенности (обусловленная, в частности, популярностью mod_wsgi и уверенностью в том, что автор имеет достаточно глубокие познания и умеет работать с коммьюнити) значит для реальных приложений больше, чем бенчмарки хеллоу-вордов (которые показывают только, что все популярные серверы имеют достаточную скорость).
                      • 0
                        Естественно, что задавшись целью сравнить разницу в производительности между различными wsgi-серверами, человек использовал приложение-затычку, чтобы оно вносило минимальный вклад в общую картинку, и не смешивало краски.

                        Если у вас медленное приложение, то, конечно, оно будет узким местом разницу вы не заметите.

                        Я не использую mod_wsgi для django-проектов у себя на хиленьком vds, поскольку там очень мало памяти, а apache реально очень много жрет. Приведенный вам выше скриншот одной строчки из top (?) и его интерпретация малость не адекватны. Во-первых, там все-таки 17,5Мб, и то что 15 из них выловились в swap, еще ни о чем не говорит, вероятно у вас дефицит памяти, а данный процесс как раз находится в простое. А то я вам тоже покажу:
                        35516 vbart 1 4 0 22828K 8K select 0:07 0.00% python
                        8Кб, смешно, да? =) А вот процесс который недавно обработывал запрос:
                        45866 vbart 1 4 0 21732K 16060K select 0:26 0.00% python

                        У меня большой опыт эксплуатации слабеньких vds-ок с малым количеством памяти, и он показывает, что apache на них не место. И не один я так считаю.

                        А для большого проекта и под высокой нагрузкой, я не буду использовать mod_wsgi, поскольку он не поддерживает асинхронный режим работы. Такой роскоши я себе позволить не могу, мне нужно получить и обработать данные от нескольких запросов к двум различным пулам серверов СУБД, если я от каждого буду ждать ответа по очереди, то пользователь получит свою страницу минимум через секунду-две, а ОС придется держать тысячи процессов.

                        «что 0.01% запросов вызывает сегфолты, а сервер не умеет эту ситуацию обрабатывать, постепенно забивая воркеры, пока все не застопорятся»
                        Это какой-то некий мифический сервер. У того же uwsgi есть «harakiri mode».
                        • 0
                          Во-первых, там все-таки 17,5Мб, и то что 15 из них выловились в swap, еще ни о чем не говорит, вероятно у вас дефицит памяти, а данный процесс как раз находится в простое.


                          17.5M — VIRT. Это к свопу не имеет абсолютно никакого отношения. Почитайте, например, тут: linux-mm.org/ActualMemoryFootprint

                          Обычно эти 17.5M вообще ни на что не влияют. Т.е. если бы там было 375M вместо 17.5M — ничего бы не изменилось. Или 1Gb. Совсем ничего. Ну это, наверное, как-то слегка влияет на работу планировщика памяти, но уж очень слегка.

                          Кроме одного исключения, к которому мы сейчас подойдем.

                          У меня большой опыт эксплуатации слабеньких vds-ок с малым количеством памяти, и он показывает, что apache на них не место. И не один я так считаю.


                          Вот оно, опять. Дико распространенный миф о прожорливости апача вызван вызван именно кривыми слабыми вдсками на OpenVZ. Т.к. OpenVZ настолько крив, что ограничивает именно VIRT, а не RSS. В реальных серверах учитывается RSS память, в VDS на XEN и KVM — тоже RSS. Куча софта (включая саму операционную систему — то, как она работает с потоками — выделяет в стеке место под каждый поток в VIRT памяти, порядка 8M обычно) написано в том предположении, что VIRT дается бесплатно. А на OpenVZ это не так. Поэтому любой софт, использующий потоки или, например, делающий mmap файлов — апач, mysql+innodb и т.д., на OpenVZ будет есть неприличное количество памяти. Это можно только слегка сгладить костылями, даже статью про это писал. Но проще — не использовать OpenVZ, очень вероятно, что XEN c 256метров больше памяти даст реально, чем OpenVZ на 512.

                          И тут в инструкции курсивом, и в документации к django-fab-deploy красным про OpenVZ предупреждаю не зря — не будет на нем конфигурация apache+mod_wsgi+nginx работать нормально. А на XEN или реальном сервере — будет.

                          В статье про fapws, на которую Вы ссылаетесь, автор вот тоже не разобрался ну совсем. Запустил однопоточный асинхронный fapsw и синхронную джангу за ним. Причем 1 инстанс. Джанга спрашивает базу — обработка стоит. Джанга обратилась к стороннему ресурсу через urllib, а тот не ответил — обработка встала на несколько секунд, а если таймаут не стоял, то совсем встала. Идет загрузка файла через джангу — все ждут, ничего не работает. Ну ок, выход — запустить несколько инстансов, чтоб работали примерно так же, что и апач. Так и потреблять будет как mod_wsgi без тредов, на одних процессах. Т.е. больше, чем mod_wsgi с тредами. На нормальном сервере или VDS под XEN — ужасная конфигурация, проигрывающая апачевской по всем статьям. И, кстати, бенчмарк с хеллоувордом это все не выявит. Что и требовалось доказать, как говорится. Вредные это статьи, вредные бенчмарки. Сколько вот людей ту статью причитало и времени потратило, настраивая совершенно корявую конфигурацию с уверенностью в том, что добиваются высокой производительности.

                          Вы вот тоже странные вещи пишете, что mod_wsgi не асинхронный и из-за этого его под высокой нагрузкой использовать не будете. У нас же про джангу речь? Нет совсем никаких преимуществ в запуске синхронной джанги через асинхронный сервер. Т.к. джанга-то синхронная. Будет ваш весь из себя асинхронный сервер обращаться к синхронной джанге, и все будут стоять и ждать, пока джанга ответит и можно будет в event loop вернуться. Для того, чтобы получать преимущества от асинхронных серверов, нужно, чтоб и код, который выполняется, асинхронным был. К джанге все это никаким боком не относится.

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

                          Если есть треды, то это будет плохо работать на вдсках под OpenVZ, будет казаться, что прожорливо очень. И в бенчмарке про хеллоуворд софт с тредами медленнее результат покажет, чем с 1 процессом (из-за того, что все будет CPU-bound, а треды вызовут GIL). Ну и будут опять все говорить, что вот способ X — отстой, вот эти быстрее. А реальные проекты обычно не CPU-bound, а IO-bound, и конфигурация с тредами будет надежнее, потреблять меньше памяти и обрабатывать больше запросов. Т.е. опять бенчмарки и опыт дешевых вдсок нам будет врать.

                          Я не к тому, что апач — панацея. Я к тому, что он работает, и работает хорошо и предсказуемо. А с остальным нужно разбираться и как минимум внимательно смотреть, что конкретно там происходит. Если знаний достаточно — вперед. А если нет — то легко начитаться бенчмарков и в лужу сесть, как вот автор статьи про fapsw3.
                          • 0
                            Про OpenVZ зря упомянули. У меня все vds-ки на XEN.

                            17.5M — VIRT. Это к свопу не имеет абсолютно никакого отношения. Почитайте, например, тут: linux-mm.org/ActualMemoryFootprint

                            По ссылке ни слова не сказано, что VIRT не имеет отношения к swap-у. И да, man top четко и ясно нам говорит, что: VIRT = SWAP + RES. Тот факт, что в него входит mmap файлы и разделяемая память, еще не отменяет того, что у вас почти все приложение сидит в свопе. Как только получит запрос, ваш RSS мигом возрастет. Что это за django-приложение которое кушает всего 2,5Мб? По-моему даже Hello world на django съест больше.

                            В статье про fapws, на которую Вы ссылаетесь, автор вот тоже не разобрался ну совсем. Запустил однопоточный асинхронный fapsw и синхронную джангу за ним.

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

                            Вы вот тоже странные вещи пишете, что mod_wsgi не асинхронный и из-за этого его под высокой нагрузкой использовать не будете. У нас же про джангу речь?

                            Нет. Я конечно мог бы сделать для django асинхронную обертку, но она мне никаким боком не сдалась. Я явно указал ситуацию, когда синхронный режим работы не приемлем. Есть пара кластеров различных СУБД, и приложению надо выполнить, к примеру, 8 независимых запросов. Каждый занимает, предположим, ~100мс, если мы будем делать их по очереди, то только на запросах потеряем порядка 800мс. Единственный выход: сделать эти 8 запросов асинхронно, повесив на них обработчики, и вернуть управление application-серверу, тому же uwsgi.

                            Я не к тому, что апач — панацея. Я к тому, что он работает, и работает хорошо и предсказуемо.

                            С этим согласен.
                            • 0
                              А в общем-то, в целом Вы меня убедили, что выбранный вами метод не так уж плох.
                              • 0
                                у меня тоже несколько мифов в голове развеялось, спасибо за полезную дискуссию)
                            • 0
                              2,5Mb тут кушает не джанго-приложение, а надзирающий воркер, который запускает демон-процессы джанги с потоками. Демон-процессы кушают (оверхед mod_wsgi = несколько сот кб) + (интерпретатор питона) + (собственно приложение). При других способах запуска все то же самое, только вместо оверхеда mod_wsgi будет оверхед от другой библиотеки.

                              Насчет VIRT — значит в мане top неправильная формула) VIRT — это в линуксе то, что приложение себе заммапило. Память под стек в VIRT выделяется, разделяемые библиотеки тоже там учитываются. Но согласен, насчет того, что вообще никакого отношения не имеет — не прав был, имеет, своп там тоже считается. Другое дело, что у меня на серверах в свопе обычно нет ничего и куча свободной памяти еще. Так что привык, что в VIRT своп не учитывается, своп там — совсем не главное. А в OpenVZ user-level свопа-то нет вообще, а VIRT у апача может раз в 20 больше RSS быть, но черт с ним, с OpenVZ.

                              Асинхронность — отдельная тема, статья все-таки про django. Highload — не обязательно асинхронность. Возьмем, например, disqus. Самый нагруженный django-сайт, десятки тысяч запросов в секунду обрабатывает. БОльший опыт деплоя highload-приложений на django вряд-ли у кого-то есть. И что там внутри? HAProxy+apache+mod_wsgi+postgres.
                              • 0
                                2,5Mb тут кушает не джанго-приложение, а надзирающий воркер

                                И правда. Виноват, упустил сей факт из виду.

                                Вообще, почитал сейчас про mod_wsgi побольше, как оно устроено, понял, что заблуждался на счет прожорливости. Действительно хорошая очень штука. Мое впечатление об apache скорее больше базировалось на тех временах когда mod_python повсеместно был в ходу. Давно я от апача отказался, а негатив остался. Что ж, и у меня теперь одним мифом в голове меньше.

                                Однако, использовать специализированный application-сервер, типа uwsgi, мне все ж больше нравится. И проще, и когда на одной машине, можно использовать сокеты, вместо TCP. А для highload-а тут и в синхронном режиме полно всяких плюшек, даже перечислять замучаешься, можно очень здоровскую систему построить. ;-)
                      • 0
                        Да и, кстати, как поведет ваш хваленой надежности mod_wsgi если приложение словит не segfault, а впадет в бесконечный цикл, или вечный i/o wait?
                        • 0
                          Убьет процесс по inactivity timeout и возродит со следующим запросом. Работало еще в 2007 году.
              • 0
                Про flup, кстати, я не упоминал. Есть python-fastcgi, если нужно производительно и сурово. Есть uwsgi если нужно супер-гибко.
  • +3
    Использую для этого свою самописную систему, не привязанную к джанго: github.com/klen/makesite

    Вкратце оно может все выше перечисленное + что касается джанго, сборка статики, добавление задач в крон, celery, сброс мемкеша при деплое, оно умеет создавать базы и пользователей для них при необходимости, оно умеет заводить ветки в git. Оно умеет обновлять проекты и это легко прикрутить к хукам систем контроля версий. Оно содержит вспомогательные скрипты для работы с проектами (типа поиск проекта и активация его виртуального окружения с автодополнением в баше). Оно может развернуть свою веб морду со списком проектов на сервере, оно может развернуть скелет базового джанго проекта из своей поставки. Оно умеет удалять проекты. Оно легко расширяемо с помощью системы темплейтов и так же легко конфигурируется. Например на сервере можно задать глобальные настройки для всех проектов или хранить настройки в своем домике. Оно вообще может еще много чего, но мне все лень написать нормальную документацию, а еще лучше серию скринкастов.
    • 0
      Интересная штука, добавил в djangopackages.com/grids/g/deployment/.

      Тоже пол-года за документацию взяться не мог, это процентов 50 усилий как минимум) Как писать начал, куча тонкостей вылезла — я, оказывается, разные предположения делал о предварительной настройке сервера и структуре проекта, ну и не замечал, что перевод существующего проекта переусложнен.

      Задачи в крон добавлять (и, что немаловажно, надежно их потом оттуда удалять), пользователей заводить, базы создавать и проекты удалять django-fab-deploy тоже умеет. На локальной машине django не требуется, к слову.

      Скрипты для работы и развертывания celery, rabbitmq, redis, node.js + npm (все интегрировано с питоньим виртуаленвом), tornado, supervisord, memcached, geoip/geos, munin с плагинами и т.д. у меня для разных проектов тоже написаны, но в django-fab-deploy я это все осознанно пихать не стал. Лучше, чтоб кода было меньше, и он делал какую-то четко определенную задачу. Может, что-то вроде fab_deploy.contrib потом будет иметь смысл сделать, пока не уверен.

      Вместо сброса memcached при деплое (зло как-то: один сайт поменялся, у всех кеш слетел) лучше imho в ключи версию кеша добавлять. В django 1.3 это из коробки, раньше можно было сторонние бэкенды использовать (django-newcache, django-cache-utils).

      В том, из чего вырос django-fab-deploy, все изначально было прикручено к хукам системы контроля версий, но потом от этого пришлось отказаться, т.к. такой способ очень усложняет условную логику. Например, если хочется выложить изменения на сервер, но пока не делать миграции, а миграции в хуке уже прописаны. Подход с «глупым» сервером и «умным» клиентом гибче показался.
      • 0
        А как там можно редактировать информацию?
        • 0
          Зарегистрироваться и ткнуть в нужный квадрат.
  • 0
    django-fab-deploy не работает с Fabric 0.9.x, Fabric должен быть установлен с github'а — и урл приводится без ссылки на коммит даже? Ну и на гитхабе, судя по code.fabfile.org/projects/roadmap/fabric, идёт работа над 0.9.4 (странно, что там нет ветки под 1.0, которая также в разработке)
    • 0
      Я, если честно, не очень понимаю, почему 1.0 или хотя бы 0.10.0 не выпустили уже давно. Там много разных улучшений внутренних, в master они лежат давно (чуть ли не по полтора года, судя по трекеру), и которые в 0.9 не бекпортят — и, видимо, не будут.

      Fabric периодически обновляю и слежу, чтоб ничего не сломалось (за пол-года никаких проблем так и не было). Но так-то да, коммит было бы хорошо вписать.
  • 0
    данный способ осущ. последовательное обновление на серверах а не параллельное т к Fabric не поддерживает параллельные запуски. Есть правда форк по ссылке который это умеет. По моему это нужно отметить в статье.
    • 0
      Я, по правде говоря, не очень понимаю, в чем тут проблема, и почему за это дело переживают так. Т.е. понятно, то удобно, когда хорошая поддержка таких штук, но:

      fab stage push & fab prod push — вот и параллельный запуск готов. Это при желании элементарно автоматизируется.

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