Хабрахабр

[Перевод] Что представляет собой веб-приложение в продакшне?

На заре карьеры я работал в компании, которая выпускала систему управления контентом. Эта CMS помогала отделам маркетинга самостоятельно управлять сайтами, а не полагаться на разработчиков при каждом изменении. Система помогла клиентам сократить операционные расходы, а мне — научиться создавать веб-приложения.

Эти задачи выжимали максимум из CMS, а разработчикам приходилось искать решение проблем. Хотя сам продукт имел очень общее назначение, клиенты обычно использовали его для конкретных задач. Некоторые из них обсудим в этой статье. После десяти лет работы в таком окружении я узнал огромное число способов, как может сломаться веб-приложение в продакшне.

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

Они хорошо работают из коробки и могут отлично решить проблему. Если вы начали работу в таком окружении, а затем приступили к созданию и развёртыванию веб-приложения с нуля, то очень быстро узнаете, что такое «до опасного поверхностные знания».
В отрасли существует ряд решений для решения этой проблемы: управляемые веб-приложения (Beanstalk, AppEngine и т. д.), управление контейнерами (Kubernetes, ECS и т. д.) и многие другие. Но это излишняя сложность при запуске веб-приложения, и обычно такие решения «просто работают».

Если возникает какой-то нюанс, то хочется чуть больше знать об этом зловещем чёрном ящике. К сожалению, не всегда они «просто работают».

На каждом шагу используется реальная проблема, решение которой переносит нас на следующий этап. В статье мы возьмём ненадёжную систему и доработаем её до разумного уровня надёжности. Он лучше демонстрирует, когда и в каком порядке принимать определённые решения. Я считаю, что эффективнее не анализировать все части окончательного дизайна, а использовать именно такой поэтапный подход. В конце концов, мы построим с нуля базовую структуру сервиса хостинга управляемых веб-приложений, и, надеюсь, подробно объясним причины существования каждой его части.

Представьте, что ваш бюджет на хостинг $500 в год, поэтому вы решили арендовать один сервер t2.medium на Amazon AWS. На момент написания статьи это около $400 в год.

Из-за ограниченного бюджета разместим её на нашем единственном сервере. Вы заранее знаете, что у вас будет система авторизации и что понадобится хранить информацию о пользователях, поэтому нужна база данных. В конечном итоге получаем такую инфраструктуру:

1
Рис.

На самом деле такая система может проработать довольно долго. Пока этого достаточно. Возможно, и маленького инстанса было достаточно, но мы с оптимизмом смотрим на рост компании, поэтому предусмотрительно взяли t2.medium. Сервис маленький, менее 10 посещений в день.

Нужно убедиться, что если сервер выходит из строя, вы не потеряете данные. Ценность бизнеса — в базе данных, поэтому она очень важна. Ведь если инстанс удалят, вы потеряете свои данные. Вероятно, следует убедиться, что содержимое базы не хранится на временном диске. Это очень страшная мысль.

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

Теперь система выглядит примерно так:

2
Рис.

Всё идет вроде нормально, пока не появляются ошибки 500, а затем поток ошибок 404, поэтому вы изучаете, что произошло. Вы повысили надёжность базы данных, и пришло время подготовиться к «хабраэффекту», прогнав на сервере нагрузочный тест.

Вы также видите, что процесс не работает, так что можно с большой вероятностью предположить, что именно поэтому появляются ошибки 404. Оказывается, вы понятия не имеете, что произошло, потому что писали логи в консоль и не направляли выдачу в файл. Накатывает волна облегчения, что вы грамотно запустили локальный нагрузочный тест, а не вызвали реальный хабраэффект в качестве тестовой нагрузки.

Затем запускаете ещё один нагрузочный тест для проверки. Вы исправляете проблему с автоматическим перезапуском, создав службу systemd, запускаете веб-сервер, который одновременно решает проблему с записью логов.

Вы проверяете логи. И опять видим ошибки 500 (к счастью, без 404). Обновляете ограничение, перезапускаете БД и снова запускаете нагрузочный тест. Обнаруживается, что пул подключений к базе данных заполнен, потому что было установлено маленькое ограничение в 10 подключений. Всё идёт хорошо, поэтому вы решаете рассказать о своём сайте на Хабре.

Матерь божья! Ваш сервис мгновенно становится хитом. Вы попали на главную страницу и получаете 5000 просмотров за первые 30 минут — и видите комментарии. Что там пишут?

Вот ссылка, если кому надо: … У меня ошибка 404, поэтому пришлось открыть кэшированную версию страницы.

Кроме того, у меня отключен Javascript. Ничего не открывается. Почему люди считают, что я хочу грузить их Javascript на 2 МБ…

Traceroute из Австралии показывает, что сервер размещен где-то в Техасе. Загрузка домашней страницы занимает 4 секунды. Кроме того, почему первая страница загружает 2 мегабайта Javascript?

В безумной спешке вы настраиваете Nginx в качестве обратного прокси-сервера для своего приложения и настраиваете там статическую страницу 404. Вы также изменяете процедуру деплоя, чтобы отправлять статические файлы в S3: это необходимо для работы CloudFront CDN, чтобы сократить время загрузки в Австралии.

3
Рис.

Ваше соединение SSH необычно лагает. Вы решили самую насущную проблему, идёте на сервер и проверяете логи. Создаёте диск гораздо большего размера и монтируете туда логи. После некоторого изучения вы видите, что файлы логов полностью израсходовали дисковое пространство, что привело к сбою процесса и предотвращению его повторного запуска. Настраиваете logrotate, чтобы файлы логов больше не разрастались до таких размеров.

Проходят месяцы. Аудитория растёт. Сайт начинает тормозить. Вы заметили в мониторинге CloudWatch, что это происходит только между 00:00 и 12:00 UTC. Из-за одинакового времени начала и окончания лагов вы догадываетесь, что это связано с запланированной задачей на сервере. Проверяете crontab и понимаете, что одно задание запланировано на полночь: резервное копирование. Конечно, резервное копирование занимает двенадцать часов и приводит к перегрузке базы данных, вызывая значительное замедление работы сайта.

Затем вспоминаете: у вас же нет подчинённой базы данных, поэтому её нужно создать. Вы читали об этом раньше — и решаете запускать резервные копии в подчинённой БД (slave). Создаёте два новых сервера: один для базы данных master и один для базы данных slave. Не имеет большого смысла запускать базу данных slave на том же сервере, поэтому вы решаете расширяться. Изменяете резервное копирование для работы с подчинённой БД.

4
Рис.

Некоторое время всё идёт гладко. Проходят месяцы. Вы нанимаете разработчиков. Один из новичков вносит баг, который валит производственный сервер. Разработчик обвиняет среду разработки, которая отличается от продакшна. В его словах есть доля правды. Поскольку вы разумный человек с хорошим характером, то воспринимаете это событие как урок.

К счастью, вы с первого дня автоматизировали создание инфраструктуры, так что всё проходит гладко и просто. Пришло время создать дополнительные окружения: промежуточное (staging), QA и продакшн. У вас также с первого дня налажены хорошие практики непрерывной доставки, поэтому вы легко собираете конвейер из новых веток.

0. Отдел маркетинга настаивает на выпуске версии 2. 0, но соглашаетесь. Вы не совсем понимаете, что значит 2. Вы уже близки к пику на текущем сервере, так что пришло время для балансировки нагрузки. Пора готовиться к очередному всплеску трафика. Примерно в это время вы замечаете, что многоуровневые диаграммы в этой статье должны показывать слои сверху вниз, а не слева направо. Amazon ELB легко делает это.

5
Рис.

О чудо, он выдерживает трафик. Уверенный в том, что вы справитесь с нагрузкой, вы снова упоминаете свой сайт на Хабре. Большой успех!

На проверку 12 серверов ушёл час (по четыре сервера в каждом окружении). Всё вроде шло хорошо, пока вы не пошли проверять логи. К счастью, денег хватает на покупку стека ELK (ElasticSearch, LogStash, Kibana). Настоящая нервотрёпка. Вы развёртываете его и направляете туда серверы со всех окружений.

6
Рис.

Они полны таких записей: Теперь, можно снова обратиться к логам, вы смотрите их — и замечаете что-то странное.

GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1
GET /wp-login.php HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1

Вы не используете PHP или WordPress, так что это довольно странно. Вы замечаете похожие подозрительные записи в логах серверов БД и удивляетесь, как они вообще подключились к интернету. Пришло время внедрять публичные и частные подсети.

7
Рис.

Попытки взлома остались, но теперь они ограничены портом 80 на балансировщике нагрузки, что немного утешает, потому что серверы приложений, серверы БД и стек ELK больше не в открытом доступе. Ещё раз проверьте логи.

Через Amazon CloudWatch вы настраиваете оповещения по электронной почте, когда диск, CPU и сеть достигают 80% утилизации. Несмотря на централизованные логи, вам надоело искать даунтаймы, проверяя логи вручную. Отлично!

Просто шучу! В программном обеспечении нет такого понятия, как бесперебойная работа. Что-то обязательно сломается. К счастью, теперь у вас много инструментов, чтобы справиться с ситуацией.

Дальнейшее масштабирование, как правило, зависит от конкретных потребностей приложения. Мы создали масштабируемое веб-приложение с бэкапами, откатами (с использованием синих/зелёных деплоев между продакшном и промежуточным этапом), централизованные логи, мониторинг и оповещение.

Вместо самостоятельной разработки вы можете положиться на Beanstalk, AppEngine, GKE, ECS и т. На рынке много вариантов хостинга, которые берут на себя бóльшую часть упомянутых задач. Большинство этих сервисов автоматически настраивают разумные разрешения, подсистемы балансировки нагрузки, подсети и т. д. д. Это устраняет существенную часть нервотрёпки при запуске веб-приложения на быстром и надёжном бэкенде, который работает в течение длительного времени.

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

В этой статье опущено много деталей. В ней не описывается, как автоматизировать создание инфраструктуры, как подготовить и настроить серверы. Не рассматривается создание сред разработки, настройка конвейеров непрерывной доставки, а также выполнение развёртываний и откатов. Мы не затронули сетевую безопасность, разделение ключей и принцип минимальных привилегий. Не рассказали о важности неизменной (immutable) инфраструктуры, stateless-серверов и миграций. Каждая из тем требует отдельной статьи.

Будущие статьи могут ссылаться сюда и расширять тему. Цель этого поста — общий обзор, как должно выглядеть разумное веб-приложение в продакшне.

На данный момент это всё.

Спасибо за чтение и удачного кодирования!

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

Теги
Показать больше

Похожие статьи

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

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

Кнопка «Наверх»
Закрыть