Как Мы Пережили Резкое Увеличение Нагрузки Х10 Удаленно И Какие Выводы Сделали

Привет, Хабр! Последние пару месяцев мы живем в очень интересной ситуации, и мне хотелось бы поделиться нашей историей масштабирования инфраструктуры.

За это время СберМаркет вырос в заказах в 4 раза и запустил сервис в 17 новых городах.

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

О самых интересных и полезных выводах читайте под катом.



Как мы пережили резкое увеличение нагрузки х10 удаленно и какие выводы сделали

Меня зовут Дима Бобылёв, я технический директор СберМаркета.

Поскольку это первая запись в нашем блоге, скажу пару слов о себе и компании.

Осенью прошлого года я принял участие в конкурсе молодых лидеров Рунета.

На конкурс я написал короткий рассказ о том, как мы в СберМаркете видим внутреннюю культуру и подход к развитию сервиса.

И хотя выиграть конкурс мне не удалось, я сформулировал для себя основные принципы развития ИТ-экосистемы.

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

Сейчас СберМаркет ежегодно растет в 13 раз, и это влияет на продукт, требуя от него постоянного увеличения объемов и темпов разработки.

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

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

В результате такого роста СберМаркет уже стал лидером среди сервисов доставки продуктов: ежедневно мы доставляем около 18 тысяч заказов, хотя в начале февраля их было около 3500.

Как мы пережили резкое увеличение нагрузки х10 удаленно и какие выводы сделали

Однажды клиент попросил курьера СберМаркета доставить ему продукты бесконтактно - прямо на балкон.

Но перейдем к конкретике.

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

Эта необходимость объяснялась внешними и внутренними факторами.

Вместе с расширением клиентской базы количество подключенных магазинов выросло с 90 в начале года до более чем 200 к середине мая.

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

Однако практика показала: «Все, что может пойти не так, пойдет не так».

И сегодня я хочу поделиться самыми интересными ситуациями, произошедшими за эти недели.

Надеюсь, наш опыт будет вам полезен.



Ведомый находится в полной боевой готовности.

Еще до начала пандемии мы столкнулись с увеличением количества запросов к нашим бэкэнд-серверам.

Тенденция заказа продуктов с доставкой на дом начала набирать обороты, а с введением первых мер самоизоляции из-за COVID-19 нагрузка в течение дня резко возросла.

Возникла необходимость быстро разгрузить мастер-серверы основной базы данных и передать часть запросов на чтение на серверы-реплики (подчиненные).

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

В основном они использовались для пакетных задач по формированию информационных потоков для обмена данными с партнерами.

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

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

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

До определенного уровня нагрузки нам хватало мастера как на запись, так и на чтение при обработке http-запросов.

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

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

Производительности «мастера» уже не хватало, поэтому некоторые самые тяжелые запросы на чтение мы начали передавать на реплику.

Чтобы прозрачно маршрутизировать запросы на запись к мастеру и запросы на чтение к слейву, мы использовали рубиновый гем " Осьминог «Мы создали специального пользователя с постфиксом _readonly без прав на запись.

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

Проблема проявилась не сразу, потому что.

возросшая нагрузка увеличила отставание слейвов.

Несоответствие данных было обнаружено утром, когда после ночного импорта слейвы не «догнали» мастера.

Мы объяснили это высокой нагрузкой на сам сервис и импортом, связанным с запуском новых магазинов.

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

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

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

Но поскольку мы сделали не только дамп базы данных (восстановление на тот момент занимало около 5 часов), но и снимок мастер-сервера, то реплику удалось запустить в течение 2 часов.

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

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

При таком подходе нет никаких сомнений в том, что реплики будут доступны в критические моменты.



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

Хотя мы постоянно обновляем каталог на сайте, запросы, которые мы отправляли на Подчиненные сервера, допускали небольшое отставание от Мастера.

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

В результате сайт работал медленно.

но, по крайней мере, работал.

И пока «Slave» восстанавливался, нам ничего не оставалось, кроме оптимизации.

Пока Слейв-серверы восстанавливались, минуты медленно шли, Мастер оставался перегруженным, и мы бросили все силы на оптимизацию активных задач по «Правилу Парето»: выбрали ТОП запросов, генерирующих большую часть нагрузки, и приступили к настройке .

Это было сделано прямо на ходу.

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

Оптимизация пары запросов, которые давали всего 5% от общей нагрузки, уже показала заметную загрузку процессора.

В результате нам удалось обеспечить приемлемый запас ресурсов Мастеру для работы с базой данных и получить необходимое время для восстановления реплик.

Заключение: Даже небольшая оптимизация позволяет «выжить» под перегрузкой несколько часов.

Этого нам хватило как раз для восстановления серверов с репликами.

Кстати, о технической стороне оптимизации запросов мы поговорим в одном из следующих постов.

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



Организовать мониторинг работы партнерских сервисов

Мы обрабатываем заказы от клиентов, поэтому наши сервисы постоянно взаимодействуют со сторонними API — это шлюзы для отправки СМС, платежные платформы, системы маршрутизации, геокодер, ФНС и многие другие системы.

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

Неожиданное превышение квот партнерских сервисов может привести к простою собственных.

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

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

В результате оказалось, что заказы были сделаны, но сервис, создавший маршрут, не работал.

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

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

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

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

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

Но в конце месяца мы получили кругленькую сумму почти на 2 миллиона рублей.

После этого решили быстро его заменить.

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



Как мы пережили резкое увеличение нагрузки х10 удаленно и какие выводы сделали

Заключение: Обязательно следить за условиями работы всех партнерских сервисов и иметь их в виду.

Даже если сегодня кажется, что они для вас «с большим запасом», это не значит, что завтра они не станут препятствием для роста.

И, конечно, финансовые условия повышенных запросов на услугу лучше согласовать заранее.



Иногда оказывается, что " Нужно больше золота "(с) не помогает

Мы привыкли «затыкать» в основной базе данных или на серверах приложений, но при масштабировании неприятности могут появиться там, где их не ждали.

Для полнотекстового поиска по сайту мы используем движок Apache Solr. По мере увеличения нагрузки мы отмечали уменьшение времени отклика, а загрузка процессора сервера уже достигла 100%.

Что может быть проще — дадим контейнеру с Solr больше ресурсов.

Вместо ожидаемого прироста производительности сервер просто «умер».

Он сразу загрузился на 100% и реагировал еще медленнее.

Изначально у нас было 2 ядра и 2 ГБ ОЗУ.

Мы решили сделать то, что обычно помогает — дали серверу 8 ядер и 32 ГБ.

Все стало гораздо хуже (как и почему мы расскажем в отдельном посте).

В течение нескольких дней мы разобрались в тонкостях этого вопроса и добились оптимальной производительности с 8 ядрами и 32 ГБ.

Такая конфигурация позволяет нам продолжать увеличивать нагрузку и сегодня, что очень важно, ведь рост идет не только по клиентам, но и по количеству подключенных магазинов – за 2 месяца их число увеличилось вдвое.

Заключение: Стандартные методы типа «добавь еще железа» не всегда работают. Итак, при масштабировании любого сервиса нужно хорошо понимать, как он использует ресурсы, и заранее протестировать его работу в новых условиях.



Безгражданство — ключ к простому горизонтальному масштабированию

В целом наша команда придерживается известного подхода: сервисы не должны иметь внутреннего состояния (stateless) и должны быть независимы от среды выполнения.

Это позволило нам справиться с ростом нагрузки за счет простого горизонтального масштабирования.

Но у нас был один сервис исключений — обработчик длительных фоновых задач.

Он занимался отправкой электронной почты и SMS, обработкой событий, созданием каналов, импортом цен и акций и обработкой изображений.

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

Когда количество задач в очереди процессора увеличивалось (а это, естественно, происходило с увеличением количества заказов), ограничивающим фактором становилась производительность хоста, на котором располагались процессор и файловое хранилище.

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

Команда Ops быстро перенесла файловое хранилище в сетевое хранилище типа S3, и это позволило нам собрать несколько мощных машин для масштабирования процессора фоновых задач.

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

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



7 принципов интенсивного роста

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

За это время количество заказов увеличилось более чем в 4 раза.

Сейчас мы уже доставляем более 17 000 заказов в день в 62 города и планируем расширять географию еще больше — в первой половине 2020 года сервис планируется запустить по всей России.

Чтобы справиться с растущей нагрузкой, учитывая наши и без того полные шишки, мы разработали 7 основных принципов работы в условиях постоянного роста:

  1. Управление происшествиями .

    Мы создали доску в Jira, где каждый инцидент отражается в виде тикета.

    Это поможет расставить приоритеты и выполнить задачи, связанные с инцидентами.

    Ведь, по сути, не страшно ошибаться, а страшно ошибиться дважды по одному и тому же поводу.

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

  2. Мониторинг требуется для всех без исключения элементов инфраструктуры.

    Именно благодаря ему мы смогли спрогнозировать рост нагрузки и правильно выбрать «узкие места» для приоритетного устранения.

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

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

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

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

  4. Приложения должны быть без сохранения состояния.

    Мы убеждены, что из этого правила не должно быть исключений.

    Нам нужна полная независимость от среды выполнения.

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

    https://12factor.net .

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

  5. Квоты и производительность внешних сервисов.

    При быстром росте проблема может возникнуть не только в вашей инфраструктуре, но и во внешнем сервисе.

    Самое обидное, когда это происходит не из-за сбоя, а из-за достижения квот или лимитов.

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

  6. Разделяйте процессы и очереди.

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

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

    И было бы легче увеличить количество рабочих, если бы они работали отдельно.

  7. Финансовые реалии.

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

    Но о них нужно помнить, особенно если вы небольшая компания.

    Владелец любого API, как и ваш хостинг-провайдер, может понести крупный счет. Поэтому нужно внимательно читать договоры.



Заключение

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

В следующих постах мы поделимся опытом расследования деградации производительности в Apache Solr, а также поговорим об оптимизации запросов и о том, как взаимодействие с ФНС помогает компании экономить деньги.

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



Как мы пережили резкое увеличение нагрузки х10 удаленно и какие выводы сделали

В опросе могут участвовать только зарегистрированные пользователи.

Войти , Пожалуйста.

Сталкивались ли вы когда-нибудь с замедлением/падением сервиса при резком увеличении нагрузки из-за: 50% Невозможности быстрого добавления вычислительных ресурсов 12 16,67% Ограничений инфраструктуры хостинг-провайдера 4 33,33% Ограничений сторонних API 8 25% Нарушений принципов сохранения состояния ваши приложения 6 87,5% Неоптимальный код собственных сервисов 21 Проголосовали 24 пользователя.

15 пользователей воздержались.

Теги: #Оптимизация серверов #it-инфраструктура #Высокая производительность #электронная коммерция #Разработка для электронной коммерции #масштабирование #сбермаркет #сбермаркет #сбермаркет #нагруженные системы #12фактор #октопус

Вместе с данным постом часто просматривают: