Программист
0,0
рейтинг
17 апреля 2013 в 18:29

Разработка → Foreman — менеджер процессов для ваших веб-приложений tutorial

Все более популярной становится модель разработки веб-приложений, основанная на идее масштабирования с помощью процессов. Современное приложение представляет из себя набор выполняющихся процессов, не хранящих состояния, причем каждый изолирован друг от друга. Каждому такому процессу назначается свой локальный порт, что позволяет прозрачно экспортировать ваши сервисы для последующего их потребления кем-нибудь еще, возможно даже, что друг другом (например, один обслуживает http-запросы от пользователей, принимая url-адреса видео, а другой медленно, но верно, загружает их и конвертирует). Как правило, в большинстве случаев http-сервисы просто ставят за reverse proxy в nginx, но возможны варианты.

Не секрет, что у каждого разработчика есть свой арсенал инструментов, позволяющий ему так или иначе сделать свою жизнь проще. Сегодня мы поговорим о таком инструменте, как Foreman. Используя его, вы можете объявить в одном месте все процессы, которые необходимы для запуска вашего приложения. Для этого используется так называемый Procfile, который выглядит как-то так:

web:    mono ./awesome-app --port $PORT
api:    node ./api.js -p $PORT
worker: bundle exec rake resque:work QUEUE=*
habr:   bundle exec ./bin/thin -a localhost -p $PORT

Как видите, все довольно просто, в каждой строчке файла содержится по названию типа процесса и строка для его запуска.

Установка и использование


Чтобы начать им пользоваться, достаточно его установить, воспользовавшись для этого вашим системным пакетным менеджером или с помощью rubygems:

$ gem install foreman

Если ваше приложение использует Foreman, то его запуск, при наличии готового Procfile, будет выглядеть довольно просто:

$ editor .env
$ foreman start

Вот как выглядит запуск всех процессов:



Foreman установит необходимые переменные окружения, запустит все процессы, ассоциированные с вашим приложением, а также отобразит вывод стандартных потоков (stdout и stderr) каждого. Как можно заметить, имена процессов раскрашиваются в различные цвета, что позволяет визуально их отличить. Значение переменной $PORT автоматически устанавливается Foreman отдельно для каждого запускаемого процесса.

Необходимо заметить, что ваши процессы не должны сами демонизироваться, потому как Foreman не сможет в таком случае управлять циклом их запуска-остановки.

Развертывание


Foreman может экспортировать ваши задания на запуск в upstart, а также в классический юниксовый init (впрочем, так делать не рекомендуется), bluepill, runit и supervisord. Поддержка systemd также на подходе.

Экспорт в upstart


$ foreman export upstart /etc/init
[foreman export] writing: /etc/init/testapp.conf
[foreman export] writing: /etc/init/testapp-web.conf
[foreman export] writing: /etc/init/testapp-web-1.conf
[foreman export] writing: /etc/init/testapp-worker.conf
[foreman export] writing: /etc/init/testapp-worker-1.conf
[foreman export] writing: /etc/init/testapp-habr.conf
[foreman export] writing: /etc/init/testapp-habr-1.conf

После экспорта в upstart, становятся доступными следующие команды:

$ start testapp
$ stop testapp-habr
$ restart testapp-worker-1

Экспорт в inittab


$ foreman export inittab
# ----- foreman testapp processes -----
TE01:4:respawn:/bin/su - testapp -c 'PORT=5000 mono ./awesome-app --port $PORT >> /var/log/testapp/web-1.log 2>&1'
TE02:4:respawn:/bin/su - testapp -c 'PORT=5100 bundle exec rake resque:work QUEUE=* >> /var/log/testapp/worker-1.log 2>&1'
TE03:4:respawn:/bin/su - testapp -c 'PORT=5200 bundle exec ./bin/thin -a localhost -p $PORT >> /var/log/testapp/habr-1.log 2>&1'
# ----- end foreman testapp processes -----


Возможности


Параллелизм



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

# запустить по одному экземпляру процесса «worker», четыре процесса «habr» и два «web»
$ foreman start -c habr=4 -c web=2

# то же самое, только не запускать, а экспортировать в upstart
$ foreman export upstart /etc/init -c habr=4 -c web=2

# не запускать процесс «worker»
$ foreman start -c worker=0

Переменные окружения


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

Для того, чтобы использовать эту возможность, в директории проекта необходимо создать файл .env, содержащий перечисление всех необходимых значений переменных окружения, например:

APP_ENV=production
DATABASE_URL=mysql://user:password@localhost/table

Хорошей практикой здесь будет создание и постановка на учет в систему контроля версий файла sample.env, который будет содержать пример конфигурации вашего приложения. Таким образом, для его развертывания в новом окружении, необходимо будет скопировать файл sample.env в .env, отредактировать его в соответствии с вашим окружением, после чего запустить Foreman.

Вы также можете попросить Foreman запустить процессы с переменными окружения из другого файла:

$ foreman start -e development.env

Назначение портов


По умолчанию Foreman назначает порты процессам, начиная с 5000, и делает это блоками в 100 штук на каждый тип процесса, причем в том порядке, в котором они перечислены в Procfile.

Скажем, для Procfile из примера выше, процесс web.1 получит 5000-ый порт, worker.1 — 5100-ый, а habr.1 — 5200-ый. Если вы запустите два процесса habr, то процессу habr.2 будет назначен порт с номером 5201.

Вы также можете выбрать стартовый порт вручную, например:

$ foreman start -p 7000


Заключение


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

Для получения более подробной информации обо всех доступных возможностях, вы можете обратиться к документации, а также на страницу репозитория проекта на github.
Артур Хашаев @Invizory
карма
67,5
рейтинг 0,0
Программист
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

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

  • +1
    А я что-то и забыл, что в нем есть експорт в bluepill и тп. А можно как-то сделать експорт, указав кол-во запускаемых процессов?
    • +1
      Да, конечно можно, например:

      $ foreman export upstart /etc/init -c habr=4 -c web=2
  • +1
    Отлично! Спасибо. Мне всегда нравился foreman, но всегда пугало, что оно не может следить за жизнью процессов, как bluepill, теперь все станет еще проще и красивее :)

    P.S., что-то пошло не так, но этот комментарий был ответом на habrahabr.ru/post/176947/#comment_6147833
  • +1
    Так как у меня проекты на питоне, пользуюсь альтернативой написанной на python — honcho.
    есть еще на shell — shoreman, и norman на nodejs.
  • +2
    А в чем отличие от, к примеру, того же Supervisor? Насколько понимаю — и то, и другое — демонайзеры.
    Или я не правильно осознаю суть Foreman?
    • +2
      foreman создавался для хостинга heroku(там нет возможности задать настройки для supervisor). Для удобства чтобы просто в репозитории был Procfile с необходимыми командами для запуска и .env файл с переменными окружения. Я вот с foreman познакомился давно, после того как попробовал heroku и как-то с тех пор мне оч понравилось и пользуюсь. Для работы с .env файлами пользуюсь autoenv который при входе в папку помимо того что считывает переменные окружения еще и может активировать например виртуальное окружение питона.
    • +2
      Хотелось бы еще добавить к комментарию выше, что Foreman в первую очередь — инструмент разработчика, а не администратора. Более того, он поддерживает экспорт в том числе и в supervisord.
  • 0
    Существует подход, постепенно завоевывающий популярность у разработчиков, заключающийся в том, чтобы хранить конфигурацию приложения в переменных окружения.

    Не могли бы вы дать больше информации об этом?
    • +1
      Говоря о конфигурации веб-приложения, мы, как правило, имеем в виду все, что может отличаться для нескольких экземпляров одного и того же приложения, запущенного в разных окружениях. Скажем, параметры доступа к БД, очередям сообщений, внешним сервисам (API-ключи, логины-пароли) — это все конфигурация, тогда как список роутов или описание подключаемых компонентов в IoC-контейнере ею не являются — это уже внутренний конфиг, фактически, часть кода. Отсюда сразу следует рекомендация строго разделять конфигурацию и код — конфиг может меняться в разных окружениях, тогда как код для всех един.

      Поэтому, как правило, разработчики используют конфигурационные файлы. Некоторые все еще продолжают их класть в репозиторий, а остальные этого уже не делают и заполняют конфиги для каждого деплоя. Еще одна часто распространенная практика — написать пару-тройку готовых конфигов для основных окружений и положить их в репозиторий — в качестве примера можно привести известное заклинание «development, test, production». Понятно, однако, что такой способ не очень-то масштабируется.

      Соответственно, также используется и тот подход, о котором мы говорим — хранить конфигурацию в переменных окружения. Вот его достоинства:

      • Переменные окружения легко менять, к тому же для разработчиков есть такие штуки как Foreman и autoenv.
      • Не получится случайно закоммитить конфиг от околобоевого окружения в репозиторий, в отличие от файлов-конфигов.
      • Это, фактически, единственный способ описать конфигурацию, который не зависит от ОС, используемой платформы или языка.

      Как можно понять, это все неплохо вписывается в приложения, которым нужен высокий уровень гибкости и масштабируемости, а также подходит для новомодных облачных моделей типа PaaS и IaaS — одними переменными окружения мы можем рулить чем и кем угодно, вне зависимости от платформы — можно хоть на чистом C код писать. Именно поэтому такие сервисы, как, например, Heroku, используют переменные окружения для конфигурирования.

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