Как стать автором
Обновить
134.35
Рейтинг
Plesk
Plesk – панель управления хостингом

Как мы в Plesk в 2 раза снизили стоимость инфраструктуры AWS для нагруженного сервиса

Блог компании Plesk Анализ и проектирование систем *Проектирование и рефакторинг *Amazon Web Services *

Иногда добиться значительного эффекта можно используя совсем незамысловатые средства. Стоит лишь взглянуть на текущее положение дел под другим углом или свежим взглядом.

Я расскажу, как мы в Plesk сократили расходы на AWS-инфраструктуру одного из наших сервисов без применения уличной магии.

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

КДПВ
КДПВ

Итак, меня зовут Андрей. Я работаю в компании Plesk техническим лидером команды веб-сервисов. Около трех лет назад мы начали развивать это направление для расширения функциональности нашей панели управления хостингом.

Веб-сервис позволяет выйти за рамки сервера клиента и предоставить такие функции, как внешний мониторинг, управление конфигурацией, раскатку обновлений и другие.

Shots

Есть у нас сервис для создания скриншотов сайтов — для краткости я буду называть его Shots. Эти скриншоты мы используем для отображения превью сайтов и WordPress-блогов, хостящихся нашей панелью.

Ещё одна важная функция — это Smart Upgrade для блога. Она работает следующим образом: делаются скриншоты всех страниц, затем в отдельном окружении раскатывается апгрейд, и скриншоты делаются снова. Пользователь визуально оценивает успешность операции. Если всё хорошо, то апгрейд применяется. Эта функция входит в наш пакет WordPress Toolkit (далее WPT) и пользуется популярностью у веб-мастеров.

Архитектура

Мы используем AWS для работы наших сервисов. Чаще всего это Elastic Container Service (ECS) Fargate Task. Shots в этом плане — типичный представитель. Это одноконтейнерное Node.js приложение. По большому счёту, это обвязка вокруг Puppeteer с REST API и кешем на S3.

Каждый такой docker контейнер является воркером. У нас настроена Auto Scaling Group (ASG), позволяющая масштабировать сервис горизонтально. Снаружи стоит стандартный AWS балансировщик (ELB), который и распределяет задачи между воркерами. Масштабирование происходит по достижении кластером 80% загрузки процессора.

Когда сервис только запускался, мы начинали с 2 воркеров. Позже, по мере релиза клиентов, нагрузка росла, и мы пришли сначала к 8 воркерам, а потом и к 14. Затраты на работающий в таком режиме сервис стали достигать 2000$ в месяц, и мы задумались, оптимально ли мы тратим деньги.

Гипотеза #1: Сервис потребляет много CPU. Возьмём дешёвую мощность на Spot рынке.

В голове мы держали очевидный фокус для AWS — вместо on-demand instances взять spot instances.

Spot instances — это негарантированные мощности, «опилки» от ставших ненужными on-demand, или простаивающие мощности AWS. Это аукцион, где можно получить вычислительные мощности до 50-90% дешевле гарантированных. Но есть и особенность — облако может в любой момент потребовать этот ресурс вернуть. Приложение получает unix-сигнал SIGTERM  и должно завершиться за 2 минуты. Если не успеет, то будет принудительно завершено сигналом SIGKILL.

Проблема была в том, что AWS на тот момент поддерживал Spot тариф только для виртуальных машин EC2, и чтобы нам их использовать, пришлось бы отказаться от ECS Fargate и полностью переделать инфраструктуру приложения. Поэтому мы откладывали эту оптимизацию.

Но однажды к середине 2020 года звёзды сошлись, и Spot provider появился для ECS Fargate Tasks, а потом и стал поддерживаться модулем Fargate в Terraform. Мы используем Terraform для описания нашей инфраструктуры.

Terraform — это инструмент фирмы HashiCorp для декларативного описания инфраструктуры приложения с помощью языка HCL. Для него есть провайдеры для огромного числа облачных и хостинговых провайдеров. 

При деплое Terraform сохраняет состояние вашей инфраструктуры в state файле. При следующих развёртываниях он сравнивает его с новым описанием и производит изменения на инфраструктуре точечно только для нужных ресурсов.

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

Другой серьёзной проблемой Terraform является то, что он только недавно достиг первой стабильной версии, а до этого синтаксис несколько раз сильно менялся.

С появлением поддержки переход на Spot тариф оказался практически тривиальным:

resource "aws_ecs_service" "main" {
...
  capacity_provider_strategy {
    capacity_provider = "FARGATE_SPOT"
    weight            = 100
  }
}

Казалось бы, вот он профит! Мы покупаем CPU со скидкой в 50%. Но оказалось, что мы упустили из виду важную статью расходов.

AWS Cost Explorer

У AWS есть прекрасный инструмент для анализа расходов: Cost Explorer. Он наглядно представляет затраты на различные AWS ресурсы и имеет гибкие настройки фильтрации и группировки.

Интерфейс AWS Cost Explorer
Интерфейс AWS Cost Explorer

Очень хорошо, что наши скрипты деплоя помечают все создаваемые нами AWS ресурсы тегами. Мы указываем название сервиса, тип окружения, и другие параметры. Поэтому всё, что относится к сервису Shots имеет тег Application = shots. Этим фильтром я и воспользовался.

Результат за месяц получился следующий:

Component

Price

ECS (CPU power)

900$

ELB (outgoing traffic)

770$

S3 (image cache)

100$

CloudWatch (logs & metrics)

50$

Total:

1830$

Как мы могли забыть про трафик! ​ Ведь мы рассылаем сотни тысяч скриншотов в день, а исходящий трафик оплачивается.

Кстати, входящий трафик в облаке бесплатен. AWS с радостью примет от вас любые объемы данных для обработки. Но вот забрать их так просто не получится.

Сеть

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

Библиотека Puppeteer может отдавать скриншот в PNG и JPG форматах. Когда сервис проектировался, был выбран формат без потерь — PNG. Я решил разобраться, почему был выбран именно он, и можно ли его сменить на формат с потерями — JPG. Интуитивно представлялось, что это позволит сократить размер скриншотов раза в 2 минимум.

PNG vs JPEG
PNG vs JPEG

Я начал с определения списка текущих клиентов сервиса и параметров, которые они нам передают. Для этого я посмотрел в логах типичные запросы к сервису, сгруппировав их по API key. Получилась следующая таблица:

Client

% queries / day

End-user needs

Filetype

Plesk

19%

thumbnail

Explicit PNG

WPT common

63%

thumbnail

Implicit PNG

WPT SU

18%

full-size

Implicit PNG

Результаты меня удивили. Во-первых, главным потребителем оказалась не функция Smart Updates (которая по дизайну делает массу скриншотов), а функция генерации превью блога в WordPress Toolkit. Я ожидал, что их будет на уровне превью сайтов Plesk.

Второе открытие — двум из трех клиентов вообще не нужны полноразмерные скриншоты. Они их используют только для превью небольшого размера, примерно 250×150 пикселей. Это хороший задел на будущее. Если сделать дополнительный параметр для отдачи именно превью, трафик можно вовсе свести на нет.

Третье наблюдение — только Plesk отправляет явное требование типа скриншота PNG. WPT полагается на тип параметра по умолчанию, а значит, сменив эти умолчания на стороне сервиса, мы сможем одним махом получить большой эффект. Также не придётся тревожить команду разработки расширения WPT.

Гипотеза #2. Сервис генерирует много трафика. Перейдём с PNG на JPG и сэкономим половину.

Когда в Плеске необходимо провести изменения в нескольких сервисах, инициатор отправляет свою идею в специальный список рассылки Plesk Review, где к обсуждению может присоединиться каждый. Так как мне было необходимо внести изменения как минимум в сам Plesk, а возможно, и в WPT, я пошёл именно этим путём.

Первое, что я хотел выяснить, — хватит ли качества стандартного в Puppeteer JPG для функции Smart Updates. Если бы там использовалось автоматическое сравнение скриншотов, то артефакты JPG на контрастных областях и шрифтах сбивали бы его с толку. Но Program Manager WPT рассказал, что пока не планируется переходить на автоматику — скриншоты сравнивает владелец сайта. Это снижает требования к качеству и играет нам на руку. Он подтвердил, что качества стандартного JPG на выходе Puppeteer достаточно.

Второе, скорее на будущее, нужно было выяснить, всегда ли для WPT common использует именно превью скриншота или иногда нужен полный размер. И опять удача — полный скриншот если и понадобится в будущем, то не скоро.

Обсуждения в Plesk Review мне нравятся тем, что можно получить вопрос, о котором ты даже не задумывался. Было высказано сомнение: во всех ли случаях JPG будет дешевле PNG. Казалось бы, ответ очевиден. Но я решил всё же проверить. Быстрее всего было сравнить скриншоты граничных случаев веб-страниц: страница с фотографиями, обычный сайт с текстом, пустая страница HTTP ошибки.

Кейс

PNG

JPG

Результат

Много фото

7.8 МБ

1.05 МБ

13%

Сайт с тектом

500 КБ

170 КБ

34%

HTTP ошибка

19.3 КБ

20.5 КБ

106%

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

Я решил оценить долю маленьких скриншотов. Так за сутки было отдано 265 Гб трафика, успешно сделано 640 тыс. скриншотов, что даёт средний размер скриншота 426 КБ — это уже наводит на мысли. Я решил пойти дальше и построил в Kibana график распределения размера скриншота и вклада в общий трафик.

Графики распределения скриншотов по размеру и трафику
Графики распределения скриншотов по размеру и трафику

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

Другое предложение было использовать формат WebP, чтобы ещё больше уменьшить размер скриншота. Этот формат уже отлично поддерживают браузеры https://caniuse.com/?search=webp. Но Puppeteer не умеет сразу отдать скриншот в этом формате, а это значит, что будет необходима перекодировка, что съест всю экономию CPU. По этой же причине не подходят и средства для  оптимизации PNG (типа OptiPNG) — они потребляют очень много CPU в обмен на лучший размер файла. Для нас это слишком.

Внедрение формата JPG

Решено, меняем default формат на JPG! Выкатываем на внутренний стейджинг, с которым взаимодействуют все внутренние клиенты. И оказывается, что WPT Smart Updates были заточены под работу только с PNG — был захардкожен MIME-type. Мечты о быстрой победе рухнули — придётся вносить изменения в каждый клиент в отдельности.

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

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

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

Количество скриншотов формата JPG vs PNG по дате
Количество скриншотов формата JPG vs PNG по дате

На деле, после релиза WPT с использованием JPG сжатия обновилось достаточно клиентов для того, чтобы мы получили желанное уменьшение трафика в 2 раза. На графике видно момент релиза новой версии. Количество JPG файлов резко заняло значительную часть.

Результат

Перед началом этого проекта я ставил себе цель получить хотя бы двукратное снижение расходов на сервис.

Мы применили две оптимизации:

  • Переход на Spot инстансы,

  • Смена формата ответа с PNG на JPG.

Каждый из этих пунктов принёс двукратное уменьшение стоимости каждому из наших основных потребляемых ресурсов. В сумме это позволило достигнуть нашей цели.

Результат оптимизации стоимости инфраструктуры
Результат оптимизации стоимости инфраструктуры

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

Момент для внедрения был очень важный, т.к. уже через месяц мы выпустили WordPress Toolkit для cPanel. Это принесло огромное число новых пользователей, и нам снова пришлось значительно масштабировать сервис.

Взрывной рост установок WPT cPanel
Взрывной рост установок WPT cPanel

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

Теги: awsterraformnode.jsweb-servicejpegpngspotscreenshotоптимизацияplesk
Хабы: Блог компании Plesk Анализ и проектирование систем Проектирование и рефакторинг Amazon Web Services
Всего голосов 20: ↑19 и ↓1 +18
Комментарии 12
Комментарии Комментарии 12

Похожие публикации

Лучшие публикации за сутки