Застосунок дванадцяти факторів () — це методологія для створення SaaS-застосунків, які: Використовують декларативний формат для автоматизації встановлення та налаштування, що зводить до мінімуму витрати часу і коштів для нових розробників, що приєднуються до проекту; Мають угоду з операційною системою, пропонуючи максимальну переносимість між середовищами виконання; Придатні для розгортання на сучасних хмарних платформах, що усуває необхідність у серверах та їх системному адмініструванні; Мінімізують різницю між середовищем розробки і production середовищем, що дозволяє безперервне розгортання для забезпечення максимальної спритності розробки (agility); Можуть масштабуватися без значних змін в інструментах, архітектурі і практиці розробки. Методологію дванадцяти факторів можна використати для застосунків, що написані будь-якою мовою програмування та використовують будь-яку комбінацію із сторонніх служб (бази даних, черги, кеш-пам’ять тощо).

Дванадцять факторів + Дванадцять факторів # Фактор Опис I Кодова база Одна кодова база, що відслідковується в системі контролю версій та має багато розгортань. II Залежності Явно оголошуйте та ізолюйте залежності. III Конфігурація Зберігайте конфігурацію в середовищі виконання. IV Сторонні служби Вважайте сторонні служби (backing services) підключеними ресурсами. V Збірка, реліз, виконання Суворо відокремлюйте етапи збірки та виконання. VI Процеси Запускайте застосунок як один або декілька процесів без збереження внутрішнього стану (stateless). VII Прив’язка портів Експортуйте сервіси за допомогою прив’язки портів (port binding). VIII Конкурентність Масштабуйте застосунок за допомогою процесів IX Утилізовуваність Підвищуйте надійність за допомогою швидкого запуску і коректного вимкнення. X Dev/prod паритет Усі середовища (development, staging, production, тощо) мають бути максимально ідентичними між собою. XI Журналювання Сприймайте журналювання (logs) як потоки подій. XII Задачі адміністрування Виконуйте задачі адміністрування/керування за допомогою разових процесів.

Детальний опис I. Кодова база Застосунок дванадцяти факторів завжди відслідковуються в системі контролю версій, такій як Git, Mercurial або Subversion. Копія бази даних відстеження ревізій називається репозиторій коду (code repository), що часто скорочується до code repo або просто repo.

Кодова база — це один репозиторій (в централізованих системах контролю версій, як Subversion), або декілька репозиторіїв, які мають спільний початковий комміт (в децентралізованих системах контролю версій, як Git).

Одна кодова база — багато розгортань

Завжди існує однозначна відповідність між кодовою базою і застосунком:

За наявності кількох баз коду, це не застосунок, це — розподілена система. Кожен компонент в розподіленій системі є застосунком, і кожен з них може окремо дотримуватися дванадцяти факторів. Кілька різних застосунків, що спільно використовують загальну базу коду, є порушенням дванадцяти факторів. Рішенням в даній ситуації є виділення загального коду в бібліотеки, які можуть бути підключені через менеджер залежностей. Існує тільки одна кодова база для кожного застосунку, але може бути багато розгортань одного і того самого застосунку. Розгортанням є запущений екземпляр застосунку. Це, як правило, production-сайт і один або більше staging-сайтів (проміжних розгортань). Крім того, розробник має копію застосунку, запущеного в його локальному середовищі розробки. Кожну з таких копій також можна кваліфікувати як розгортання.

Кодова база має бути єдина для всіх розгортань, хоча в кожному розгортанні можуть бути активні різні її версії. Наприклад, розробник може мати деякі зміни у коді, які ще не додані в staging-розгортання; staging-розгортання може мати деякі зміни, які ще не додані в production-розгортання. Але всі вони використовують одну і ту саму кодову базу, таким чином можна їх ідентифікувати як різні розгортання одного і того ж застосунку.

II. Залежності Більшість мов програмування мають системи пакунків для розповсюдження бібліотек, такі як CPAN для Perl або Rubygems для Ruby. Бібліотеки, встановлені через систему пакунків, можуть бути доступними для всієї системи (так звані “site-packages”) або встановлені в каталог застосунку (так звані “vendoring” або “bundling”).

Застосунок дванадцяти факторів ніколи не залежить від неявно існуючих, досупних всій системі пакунків. Застосунок повно і точно вказує всі свої залежності за допомогою маніфесту оголошення залежностей. Крім того, він використовує інструмент ізоляції залежністей під час виконання, щоб гарантувати, що ніякі неявні залежності не “просочилися” з зовнішньої системи. Повна і явна специфікація залежностей використовується однаково як при розробці, так і в production.

Наприклад, Bundler в Ruby використовує Gemfile як формат маніфесту для оголошення залежностей і bundle exec для ізоляції залежностей. У Python є два окремі інструменти для цих задач - Pip використовується для оголошення і Virtualenv для ізоляції. Навіть C має Autoconf для оголошення залежностей, а статичне зв’язування може забезпечити ізоляцію залежностей. Який би не використовувався набір інструментів, оголошення і ізоляція залежностей завжди мають використовуватися разом — тільки одне або інше не є достатньою умовою для задоволення дванадцяти факторів.

Однією з переваг явного оголошення залежностей є те, що це спрощує налаштування застосунку для нових розробників. Новий розробник може скопіювати кодову базу застосунку на свою машину, необхідними вимогами для якої є тільки наявність середовища виконання мови програмування та наявність менеджера залежностей. Все необхідне для запуску коду застосунку може бути налаштоване за допомогою визначеної команди збірки. Наприклад, команда збірки для Ruby/Bundler є bundle install, а для Clojure/Leiningen це lein deps.

Застосунок дванадцяти факторів також ніколи не залежить від неявно існуючих будь-яких системних інструментів. Прикладом може бути запуск застосунком таких системних інструментів, як ImageMagick або curl. У той час, як ці інструменти можуть бути встановлені на багатьох або навіть більшості систем, немає жодної гарантії, що вони будуть встановлені на всіх системах, де застосунок може запускатися в майбутньому, або версія інструменту, встановлена в системі, буде сумісна з застосунком. Якщо застосунку потрібно запускати певні системні інструменти, то такі інструменти мають бути включені в сам застосунок.

III. Конфігурація Конфігурація застосунку — це все, що може змінюватися між розгортаннями (staging-розгортання, production-розгортання, локальне середовище розробника тощо). Це включає:

Параметри підключення до бази даних, Memcached і інших сторонніх сервісів; Реєстраційні дані для підключення до зовнішніх сервісів, таких як Amazon S3 або Twitter; Значення, що залежать від середовища розгортання, такі як канонічне ім’я хосту.

Застосунки іноді зберігають конфігурації як константи в коді. Це є порушенням методології дванадцяти факторів, яка вимагає обов’язкового відокремлення конфігурації від коду. Конфігурації застосунку в розгортаннях суттєво відрізняються, код — однаковий.

Лакмусовим папірцем того, чи правильно розділені конфігурація і код, є можливість в будь-який момент відкрити вихідний код застосунку у вільний доступ, при цьому не оприлюднюючи будь-яких приватних даних.

Визначення “конфігурації” не включає в себе внутрішні налаштування застосунку, такі як config/routes.rb в Rails, або як пов’язані основні модулі в Spring Framework. Ці налаштування не змінюються між розгортаннями, і тому краще місце для них — саме в коді.

Іншим підходом до конфігурації є використання конфігураційних файлів, що не зберігаються в систему контролю версій, таких як config/database.yml в Rails. Це перевага у порівнянні з використанням констант в коді, але все ж таки має суттєві недоліки: є ймовірність помилково зберегти файл конфігурації в репозиторій; існує тенденція коли конфігураційні файли розкидані в різних місцях і в різних форматах, і стає важко передивлятися всі налаштування і керувати ними в одному місці. Крім того, формати цих файлів, як правило, специфічні для конкретної мови програмування чи фреймворку.

Застосунок дванадцяти факторів зберігає конфігурацію в змінних оточення (часто скорочується до env vars або env). Значення змінних оточення легко змінити між розгортаннями без зміни коду; на відміну від конфігураційних файлів, менш ймовірно випадково зберегти їх в репозиторій коду; і на відміну від конфігураційних файлів або інших механізмів конфігурації, таких як Java System Properties, вони є стандартом, незалежним від мови програмування чи фреймворку.

Іншим аспектом керування конфігурацією є групування. Іноді застосунки об’єднують конфігурації в іменовані групи (які часто називаються “оточеннями”), які називаються в залежності від конкретного розгортання, наприклад, development, test і production оточення в Rails. Цей метод погано масштабується: чим більше створюється різних розгортань застосунку, тим більше необхідно нових імен оточень, наприклад, staging або qa. При подальшому рості проекту розробники можуть додавати свої власні спеціальні оточення, наприклад, joes-staging, що призводить до комбінаторного вибуху конфігурації, який робить керування розгортанням застосунку нестабільним.

У застосунку дванадцяти факторів змінні оточення є незв’язаними між собою засобами керування. Кожна змінна повністю незалежна від інших. Вони ніколи не групуються разом в “оточення”, керування ними здійснюється незалежно для кожного розгортання. Ця модель добре масштабується разом з появою більшої кількості розгортань застосунку протягом його експлуатації.

IV. Сторонні служби Стороння служба — це будь-яка служба, яка доступна застосунку по мережі і необхідна для його нормальної роботи: бази даних (наприклад, MySQL або CouchDB), системи черг повідомлень (наприклад, RabbitMQ або Beanstalkd), служби SMTP для вихідної пошти (наприклад, Postfix), системи кешування (наприклад, Memcached) тощо.

Допоміжні служби, такі як бази даних, традиційно управляються тими ж системними адміністраторами, які розгортають застосунок. Окрім локальних служб, застосунок може також використовувати служби, що надаються і керуються третіми сторонами: SMTP-сервіси (наприклад, Postmark), сервіси збору метрик (наприклад, New Relic або Loggly), сховища бінарних даних (наприклад, Amazon S3), а також різні сервіси, що надають доступ через API (наприклад, Twitter, Google Maps, або Last.fm).

Код застосунку дванадцяти факторів не бачить жодних відмінностей між локальними і сторонніми сервісами. Для застосунку кожен з них є підключеним ресурсом, доступним за URL-адресою або іншими даними, що зберігаються в конфігурації. Розгортання застосунку дванадцяти факторів повинно мати можливість, наприклад, замінити локальну базу даних MySQL на будь-яку керовану третьою стороною (наприклад, Amazon RDS) без жодних змін в коді застосунку. Крім того, локальний сервер SMTP може бути замінений на сторонній SMTP-сервіс (наприклад, Postmark) без зміни коду. В обох випадках необхідно змінити лише налаштування відповідного ресурсу в конфігурації застосунку.

Кожна окрема стороння служба є ресурсом. Наприклад, база даних MySQL є ресурсом; дві бази даних MySQL (що використовуються для шардінгу на рівні застосунку) кваліфікуються як два різних ресурси. Застосунок дванадцяти факторів сприймає ці бази даних як підключені ресурси, що вказує на їхній слабкий зв’язок з розгортанням, в якому вони підключені.

Ресурси за необхідності можуть бути підключені та відключені до розгортання застосунку. Наприклад, якщо база даних застосунку функціонує некорекно у зв’язку з апаратними проблемами, адміністратор може запустити новий сервер бази даних, відновленої з останньої резервної копії. Поточна база даних може бути відключена, а нова база даних підключена — все це без будь-яких змін коду.

V. Збірка, реліз, виконання Кодова база перетворюється в розгортання (крім розгортання для розробки) у три етапи: