именно одной причины не было. если прям супер коротко, то:
система не стартовала, потому что кэши базы не могли все вгрузить
рассылка пушей была первопричиной, начавшей все падение
наша архитектура с одной базой раньше держала пиковые нагрузки, а к моменту падения перестала держать. Додо растет, заказов в пики прилетает все больше. мы проиграли гонку по распилу монолита в части приема заказа
Мониторинг был, но был точно недостаточен. Например, текущий используемый размер кэша базы не использовали.
В самом начале была перезагрузка базы. И была она именно потому, что мы туда ресурсов накидали. Дальше по нашему мониторингу в базе, мы не могли задетектить детально проблемы.
Рестарт базы нам точно не помог. Мы фактически задестроили систему.
Да, это хорошее дополнение. Действительно, уже позже мы стали разбираться в соответсвии профиля нагрузки реальному проду и стало понятно, что актуальность там хромает. Часто что-то меняется в сценариях(как в примере с пушами), а это мы пропускаем. Надо улучшать
Сам постмортем мы писали около 3х недель. 1 неделя после сбоя ушла на отработку гипотезы с "косячным" релизом, потом подбивали детали, еще гоняли нагрузку, определили проблемы с кэшом в базе. Долго переносил в статью.
Ога, DBA нет. Тоже проблема. Я не написал, но мы в конце года как раз нашли именно DBA себе.
Закрыли в конце декабря,
Не написал тоже(слишком длинно выходило уже), но все верно. Например, в единой монолитной базе находятся промоакции и хранение додокоинов(программа лояльности), находятся данные о зонах доставки. Мы это сейчас выносим, но результаты будут позже. Уверен, ребята напишут об этом отдельно.
Тут все просто. RMQ у нас уже был к этому моменту, мы его пробовали в предрасчетах и реализации CQRS на учете. Там надо было обрабатывать расход и списания ингредиентов. Я об этом не упоминал, чтобы не усложнять. Тогда показалось, что он вполне неплох. Кафку мы не хотели дополнительно привносить, она еще тогда не была в Azure как managed service.
MySql был с самого начала, выбор в пользу массовой, простой и условно бесплатной базы. Отсюда такое странное сочетание .net + mysql.
Да. При продуманной реализации такой распределенной архитектуры(а она оказалась по факту продуманной), проблемы нагрузки на базу ушли. Разработка между разными сервисами стала сложнее, но разработка внутри сервиса скорее упростилась и даже ускорилась.
Ваши проблемы были и есть не в монолите, как таковом, а в его качестве архитектуры и реализации.
Для меня они были и там и там. Монолит(а скорее единая база) сам по себе стопорил и не позволял развиваться.
Например, использование одной большой базы приводит к сложностям в обслуживании. Недавно мы перетаскивали монолитную базу в полностью managed mysql(т.е. как saas, вместо iaas) и это заняло более 6 месяцев, причем большая часть работы была по устранению различных плохо написанных и старых вещей. Когда их писали, причем, они вполне могли не быть плохо написанными.
Еще одна большая база приводила к тому, что вертикально ее масштабировать мы в какой-то момент просто не могли. Стоимость сервера была слишком большая для нас.
Сейчас монолитная база, которая остается, тоже вызывает проблемы. Происходят вынужденные даунтаймы системы из-за обслуживания при рестартах. При отдельных хранилищах у сервисов локальные даунтаймы не сказываются на работе всей системы.
Зачем в БД хранить все поля заказа в одной таблице? Что мешает разделить их по таблицам и джойнить в нужных сервисах нужные таблицы?
Дополнительные расходы на создание заказа. При чтение придется делать джойны, которые замедлят риды. Всем не угодишь и кому-то удобна одна структура, кому-то другая. На самом деле там уже были дополнительные таблицы, в которых раскладывалась часть информации по заказу(не упоминал об этом, чтобы не усложнять), получалось много джойнов, а с ними и запросы, требующие вычислительных ресурсов.
большинство проблем с БД решаются увеличением RAM на СУБД. Делается партишенинг, нужный партишен должен быть полностью в оперативной памяти
Уперлись в размеры базы. В какой-то момент стоимость следующего по мощности сервера была бы выше месячных трат на разработку в IT. Партишенинг пробовали, как раз по заказу. В MySql он не дал ожидаемого эффекта. Производительность базы не изменилась. Тогда мы сидели на 5.6, может сейчас что-то лучше стало, не могу сказать. ForeighKey тоже не использовали.
EF не было, писали запросы сами на sql и маппили их через простые мапперы.
Если у вас с десяток локальных хранилищ заказов, то нужно их синхронизировать. Чтобы их синхронизировать, нужны очереди. Очереди должны быть отказоустойчивыми с гарантией доставки
Да, в итоге так и сделали. Не сразу догадались до этого, но сейчас эта система работает надежно. Потребовала использования паттерна локальных очередей. Т.е. перед отправкой события мы его сохраняем в таблиц local_queue, а если в rmq событие не отправилось, то у нас оно прикопано в своей базе. В rmq же очереди с durable все. Есть еще механика redelivery, если подписчик не готов принять событие. Когда это все сделали, то поняли, что какая-нибудь Кафка для такого подходил лучше. Ну чтож, пока живем на RMQ.
Напоследок про облака. Находясь там мы резко снижаем проблему «нужно админить», поэтому дальше только в облаке, никакого своего железа не планируем делать.
Наверное не стоило начинать не с начала, а где-то с середины. Отсюда тема проблем не совсем раскрыта, согласен. Я постараюсь в следующих статьях эту тему объяснить более подробно.
Пока вот примерно так:
Сначала была именно база редиса, она была маленькая и оттуда весь трекер считывал. Потом по надежности редис нам не подошел. Отказались от него в пользу реляционной базы.
Кэш в памяти есть и используется для редко меняющихся данных, типа справочников. Данные по состоянию заказа должны быть максимально актуальны. Еще до выделения отдельной базы мы проводили работы по созданию кэшей и по выделению реплик(они были на рисунках). Это сильно помогло, но данные трекера по статусам заказа нельзя было перевести на на кэш, не обеспечив его инвалидацию. А это не тривиальная задача. При этом у нас балансировка идет на N серверов, никаких sticky session нет и не хотелось делать
В целом, отдельные хранилища и синхронизация через RMQ вполне хорошо работает. Все плюсы не буду расписывать, напишу только минусы:
Работать разработчикам с этим стало сложнее. И дело не в понимании общих концепций, в в том, что все эндпойнты должны быть коммутативны и идемпотентны. Это трубует хорошей проработки взаимосвязи событий между собой. Удлинняет разработку, приводит в сложным ошибкам
Избыточность хранения данных. Да, тот же Заказ хранится в нескольких базах и от этого он независим и удобен в использовании по месту. Но как только надо сделать новый сервис сразу встает вопрос про хранение этого Заказа в нем. А есть мелкие сервисы, которые даже не модифицируют особо Заказ, а просто должны его корректно отобразить, обогатив теми или иными данными. Это приводит к созданию хранилищ, в дополнительным тратам времени и денег на них.
Локальные проблемы: использование RMQ не позволит масштабироваться по количеству подписчиков и паблишеров. При росте этого количества, надо будет больше мощности. Redis в Azure оказался проблемным и мы его теперь не используем. Это скорее конкретные сервисы и тулы, не особо влияющие на архитектуру
Получается хорошо юнит-тестировать при использовании высокоуровневых языков. И та часть инфраструктуры, которая сервисы имеет такие тесты. Но большая часть есть конфигурация или ее разновидности(DSL, templaters), а это не удается проверить качественно тестами. Мы не особо пробовали, но выглядит как много работы при малом выхлопе.
Например, нам надо иметь кол на jsonnet, который генерит терраформ-конфигурацию. Это для поддержки параметров и множества окружений. Там поднимается машинка, в ней при старте выполняется скрипт, который подтягивает скрипты инициализации(скрипт протестирован). И еще при старте начинают работать демоны на машине.
Вот это все проверяется поднятием реального ресурса. Т.е. это интеграционный тест.
Изначально в группу обучения вступили все равно те разработчики, кто занимался близкой тематикой последнее время. К примеру я до этого 2 года занимался так или иначе техническими задачами, а они непременно связаны. Остальные примерно так же.
Еще участие добровольное и те, кто не захотят остаться в инфраструктуре могут выйти.
Плюс прорекламирую непосредственно доклад на эту тему еще от одного члена команды. devopsconf.io/moscow/2019/abstracts/5575
Спасибо! В итоге мы стали писать тесты, поднимающие отдельный терраформ модуль, проверяющие, что там все поднялось корректно и все данные на машине прошли. Мы стали использовать питон, т.к. на нем пишутся скрипты-склейки, так что он уже был в части инфраструктуры.
И пока полет нормальный. Вот что прям не вызывает проблем — так это тесты на питоне и сам питон
Я еще пойму, что риски работы в России накладывают определенные ограничения
Такой риск существует и это одна из причин.
Также, как я уже говорил, часть функций находится в других облаках. Например, на google functions у нас бот для ScaleFT или бот, создающий карточки при инциденте.
Еще один риск — это ценовая политика. Деньги в клауде могут улететь очень быстро, а цены могут отличаться в разы.
т.е. непосредственно тебе идут оповещения от системы мониторинга?
Сейчас мы в процессе онбординга, но уже скоро пойдут. В этом одна из целей — чтобы увеличить пул дежурных.
т.е. если я разработчик и у меня крепкий сон, так что я не услышу звонок, полстраны лишаться пиццы?
Разработчик в команде инфраструктуры должен дежурить, быть на пейджере. Есть расписание, есть процесс дневных вечерних дежурств. Кстати, можно было бы и рассказать про то, как это подробно работает.
Обычные разработчики не дежурят(за исключением некоторых праздников).
Тут скорее про то, что вот есть разработчики(мы) и нас надо подготовить к дежурствам в инфраструктуре, в которых мы не знаем как вести себя, не обладаем изначально нужными знаниями.
При дежурствах ты становишься уже первой линией, должен первым реагировать на инциденты и если необходимо, то уже подключать аналитиков или непосредственно разработчиков, которые и ответственны за сервис.
Мы изначально выбирали именно решение с возможностью работы с несколькими cloud providers. Есть у нас сервисы не только в ажуре, причем в основном именно наши, инфраструктурные.
Про поддержку плагинов — мы частично используем плагин от Jetbrains и соответственно Rider.
именно одной причины не было. если прям супер коротко, то:
система не стартовала, потому что кэши базы не могли все вгрузить
рассылка пушей была первопричиной, начавшей все падение
наша архитектура с одной базой раньше держала пиковые нагрузки, а к моменту падения перестала держать. Додо растет, заказов в пики прилетает все больше. мы проиграли гонку по распилу монолита в части приема заказа
Тут много тем.
Мониторинг был, но был точно недостаточен. Например, текущий используемый размер кэша базы не использовали.
В самом начале была перезагрузка базы. И была она именно потому, что мы туда ресурсов накидали. Дальше по нашему мониторингу в базе, мы не могли задетектить детально проблемы.
Рестарт базы нам точно не помог. Мы фактически задестроили систему.
Он никак в итоге и не помог. Просто к моменту полного отката спал трафик. И фактически откат просто перезапустил всю систему с дефолтными настройками.
Да, это хорошее дополнение. Действительно, уже позже мы стали разбираться в соответсвии профиля нагрузки реальному проду и стало понятно, что актуальность там хромает. Часто что-то меняется в сценариях(как в примере с пушами), а это мы пропускаем. Надо улучшать
Сам постмортем мы писали около 3х недель. 1 неделя после сбоя ушла на отработку гипотезы с "косячным" релизом, потом подбивали детали, еще гоняли нагрузку, определили проблемы с кэшом в базе. Долго переносил в статью.
Ога, DBA нет. Тоже проблема. Я не написал, но мы в конце года как раз нашли именно DBA себе.
Закрыли в конце декабря,
Не написал тоже(слишком длинно выходило уже), но все верно. Например, в единой монолитной базе находятся промоакции и хранение додокоинов(программа лояльности), находятся данные о зонах доставки. Мы это сейчас выносим, но результаты будут позже. Уверен, ребята напишут об этом отдельно.
MySql был с самого начала, выбор в пользу массовой, простой и условно бесплатной базы. Отсюда такое странное сочетание .net + mysql.
Да. При продуманной реализации такой распределенной архитектуры(а она оказалась по факту продуманной), проблемы нагрузки на базу ушли. Разработка между разными сервисами стала сложнее, но разработка внутри сервиса скорее упростилась и даже ускорилась.
Для меня они были и там и там. Монолит(а скорее единая база) сам по себе стопорил и не позволял развиваться.
Например, использование одной большой базы приводит к сложностям в обслуживании. Недавно мы перетаскивали монолитную базу в полностью managed mysql(т.е. как saas, вместо iaas) и это заняло более 6 месяцев, причем большая часть работы была по устранению различных плохо написанных и старых вещей. Когда их писали, причем, они вполне могли не быть плохо написанными.
Еще одна большая база приводила к тому, что вертикально ее масштабировать мы в какой-то момент просто не могли. Стоимость сервера была слишком большая для нас.
Сейчас монолитная база, которая остается, тоже вызывает проблемы. Происходят вынужденные даунтаймы системы из-за обслуживания при рестартах. При отдельных хранилищах у сервисов локальные даунтаймы не сказываются на работе всей системы.
Дополнительные расходы на создание заказа. При чтение придется делать джойны, которые замедлят риды. Всем не угодишь и кому-то удобна одна структура, кому-то другая. На самом деле там уже были дополнительные таблицы, в которых раскладывалась часть информации по заказу(не упоминал об этом, чтобы не усложнять), получалось много джойнов, а с ними и запросы, требующие вычислительных ресурсов.
Уперлись в размеры базы. В какой-то момент стоимость следующего по мощности сервера была бы выше месячных трат на разработку в IT. Партишенинг пробовали, как раз по заказу. В MySql он не дал ожидаемого эффекта. Производительность базы не изменилась. Тогда мы сидели на 5.6, может сейчас что-то лучше стало, не могу сказать. ForeighKey тоже не использовали.
EF не было, писали запросы сами на sql и маппили их через простые мапперы.
Да, в итоге так и сделали. Не сразу догадались до этого, но сейчас эта система работает надежно. Потребовала использования паттерна локальных очередей. Т.е. перед отправкой события мы его сохраняем в таблиц local_queue, а если в rmq событие не отправилось, то у нас оно прикопано в своей базе. В rmq же очереди с durable все. Есть еще механика redelivery, если подписчик не готов принять событие. Когда это все сделали, то поняли, что какая-нибудь Кафка для такого подходил лучше. Ну чтож, пока живем на RMQ.
Напоследок про облака. Находясь там мы резко снижаем проблему «нужно админить», поэтому дальше только в облаке, никакого своего железа не планируем делать.
Пока вот примерно так:
Получается хорошо юнит-тестировать при использовании высокоуровневых языков. И та часть инфраструктуры, которая сервисы имеет такие тесты. Но большая часть есть конфигурация или ее разновидности(DSL, templaters), а это не удается проверить качественно тестами. Мы не особо пробовали, но выглядит как много работы при малом выхлопе.
Например, нам надо иметь кол на jsonnet, который генерит терраформ-конфигурацию. Это для поддержки параметров и множества окружений. Там поднимается машинка, в ней при старте выполняется скрипт, который подтягивает скрипты инициализации(скрипт протестирован). И еще при старте начинают работать демоны на машине.
Вот это все проверяется поднятием реального ресурса. Т.е. это интеграционный тест.
Спасибо. Но отчаяния-то и нет. То, что описано выше работает и помогает. А дальше только пробовать еще и еще
Еще участие добровольное и те, кто не захотят остаться в инфраструктуре могут выйти.
Плюс прорекламирую непосредственно доклад на эту тему еще от одного члена команды. devopsconf.io/moscow/2019/abstracts/5575
И пока полет нормальный. Вот что прям не вызывает проблем — так это тесты на питоне и сам питон
Такой риск существует и это одна из причин.
Также, как я уже говорил, часть функций находится в других облаках. Например, на google functions у нас бот для ScaleFT или бот, создающий карточки при инциденте.
Еще один риск — это ценовая политика. Деньги в клауде могут улететь очень быстро, а цены могут отличаться в разы.
Сейчас мы в процессе онбординга, но уже скоро пойдут. В этом одна из целей — чтобы увеличить пул дежурных.
Разработчик в команде инфраструктуры должен дежурить, быть на пейджере. Есть расписание, есть процесс дневных вечерних дежурств. Кстати, можно было бы и рассказать про то, как это подробно работает.
Обычные разработчики не дежурят(за исключением некоторых праздников).
При дежурствах ты становишься уже первой линией, должен первым реагировать на инциденты и если необходимо, то уже подключать аналитиков или непосредственно разработчиков, которые и ответственны за сервис.
Про поддержку плагинов — мы частично используем плагин от Jetbrains и соответственно Rider.