IT Tech Log
986 subscribers
18 photos
21 links
Журнал логов выполнения инженера в IT-продакшене

Контакт: @futusio
Download Telegram
Channel created
>_ Hello World 💬

Приветствую!
Меня зовут Алексей. Я Backend разработчик с 6 годами опыта, последние 1.5 года руковожу командой в позиции Team Lead

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

Когда я только начинал свой путь в IT, меня вдохновляла и мотивировала возможности учиться абсолютно бесплатно. Главное - вовлеченность, горящие глаза и время. Индустрия дала мне все необходимое, чтобы строить свою карьеру: от решений редких кейсов в дальних углах интернета до ответов опытных коллег на StackOverflow и Habr. Буду постепенно выкладывать застоявщиеся мысли, оформлять их в посты и делиться с вами. Рассказывать об опыте построение карьеры в IT. И параллельно с вами учиться новому

На этом канале я буду писать о том, что считаю важным для инженеров и лидеров:
• Архитектура Backend: устойчивость и нагрузка
• Управление командами и процессами
• Развитие хард- и софт-скиллов в IT
• Практические разборы из своей работы
• Использование AI в командах, процессах и продуктах


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

Подписывайтесь - впереди много интересного!
Please open Telegram to view this post
VIEW IN TELEGRAM
32😁2💯2🤯1
Навигация по каналу:


Серии постов:
➡️» Переход »
Теги:
#ADR #PROCESS #MINDSET #NOTES
Please open Telegram to view this post
VIEW IN TELEGRAM
1🤔1🤯1
Серии постов:

Django Blue Green:
- Blue Green №1
- Blue Green №2
- Blue Green №3

Saga Pattern:
- Saga №1
- Saga №2
- Saga №3
1👍1🤔1🤯1
Буду постепенно запускать серии постов, наполняя контентом этот канал и параллельно изучая механизмы навигации между постами в Телеграм. Начну с темы, по которой сейчас веду работы подготовки к докладу Moscow Python MeetUp - Django Blue Green Deployment

Blue-Green деплоймент — это подход, который позволяет выкатывать новую версию сервиса без простоя и риска «положить» прод. Суть проста: одновременно существует два окружения — Blue и Green. Одно обслуживает пользователей, другое — готовится к релизу. В нужный момент трафик переключается между ними.


В серии постов я хочу рассказать, как мы внедряем BG в большой Django-монолит, какие ограничения упираются в СУБД, какие в процессы, а какие вообще в Django. И о том, как мы постепенно решаем эти проблемы...

Как всё началось:

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

Мы сравнили канареечные релизы и BG. Для нас критичным было быстрое переключение между окружениями — значит BG.

И сразу столкнулись о главный вопрос:
- Как поддерживать две версии кода с разными моделями в БД, при этом имея всего одну БД?

Идея:

Мы решили, что схема БД должна временно удовлетворять требованиям _обоих_ окружений. Для этого стандартные Django-команды makemigrations и migrate мы разделили на две фазы — Blue и Green.

Все миграции мы классифицировали на три группы:

- Конструктивные
(CreateModel, AddField, AddConstraint, AddIndex)
— те, что расширяют схему и безопасны для обеих версий кода.

- Деструктивные
(RemoveField, DeleteModel и т.п.)
— операции, которые ломают совместимость.

- Невозможные для BG
(AlterField, критичные AlterTable и т.п.)
— операции, при которых единая схема не может одновременно поддерживать обе версии.


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

В следующих постах я покажу техническую сторону — как мы адаптировали DevOps-процессы, патчили Django и перестраивали миграции под две фазы. Если вам интересна инженерная кухня BG на большом монолите — будет полезно.
1🤔1🤯1💯1
Всем привет! Начинаю заметки о том, как мы работаем над архитектурными практиками в компании - как принимаем технические решения на уровне компании, и чем чреват локальный подход к разработке. В этом посте — про то, как у нас появились архитектурные комитеты и ADR.

➡️ Зачем это вообще понадобилось

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

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

В какой-то момент стало понятно: проблема не в конкретных решениях, а в отсутствии общего архитектурного контура.

ℹ️ Появление архитектора как точки перелома

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

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

Так у нас и появился формат ADR.

ℹ️ Что такое ADR у нас

ADR (Architecture Decision Records) — это единый формат, который позволяет быстро погрузить всех участников архитектурного комитета в контекст обсуждаемой проблемыю

Важно: для нас ADR — это не столько документ, сколько процесс согласования архитектурных изменений
• Команда приносит контекст проблемы, варианты решений и ограничения системы
• Вместе обсуждаем риски и влияние на другие сервисы
• Фиксируем контракт изменений и итоговое решение


Комитет собирается два раза в неделю, встречи длятся 1...3 часа в зависимости от количества тем. Участвуют разработчики, лиды, архитектор, CTO — все, кому интересно обсудить проблему, важно найти решение.

↗️ Почему это оказалось полезным

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

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

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

Теги: #ADR
1🤯1💯1
Всем привет! Продолжаю серию постов про Blue Green Django Deployment
В этом посте хочу разобрать, из каких этапов реально состояла реализация BG - со стороны DevOps и со стороны разработки - и к каким выводам мы начали приходить ещё в процессе внедрения

1️⃣ Инфраструктура

Со стороны DevOps задача сначала выглядела относительно прямолинейно:
• два полноценных prod-окружения: Blue и Green
• один ingress и переключение трафика «по кнопке»
• единая СУБД
• возможность деплоить и тестировать неактивное окружение независимо от активного


Но довольно быстро стало ясно, что application-core - не единственный участник релиза:
Во время деплоя мы также выкатываем набор сервисов, которые:
• шарят конфигурацию с монолитом
• имеют собственный lifecycle
• не должны перезапускаться синхронно с core


Поэтому, чтобы разрешить эту проблему пришлось:
• жёстко отделить core от сервисов
• описать их entrypoint.sh и поведение при старте/остановке
• сформировать правило:
- core деплоится отдельно и независимо от всех сервисов


В CI/CD это вылилось в раздельные пайплайны.
В итоге релиз-инженер не “деплоит”, а нажимает кнопку вида activate {color} - за которой стоит цепочка из 8–9 job, которые:
• Корректно завершают "shared resources"
• переключение ingress на новый application-core
• healthcheck
• И только потом: поочерёдный подъём зависимостей


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

2️⃣ Django и двухфазные миграции

А вот со стороны разработки всё было сильно менее линейно.

Идея патчинга Django-механизма миграций сначала выглядела как чистый инженерный челлендж:
1. Написать команду, аналог makemigrations, которая делит миграции на Blue (конструктивные) и Green (деструктивные)
2. Пропатчить migrate, чтобы он принимал флаги migrate --blue / --green и выполнял отфильтрованный набор миграций

Технически это означало:
• повторить большую часть логики makemigrations
• переопределить MigrationWriter → PatchedMigrationWriter
• на этапе записи миграции разделять операции
• добавить две стратегии:
- определение типа операции
- определение конкретной операции (с нюансами)


Немного сахара вокруг Django internals, немного monkey-patching’а —
и прототип действительно заработал

ℹ️ Но…
Чем дальше мы углублялись, тем отчётливее становилось несколько вещей:
• Django migration operations - это не контракт с СУБД, а декларация намерений
• одна и та же операция может транслироваться в SQL по-разному
• порядок операций иногда важнее их формального типа
• зависимости между миграциями начинают жить своей жизнью


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


⏸️ И в какой-то момент вопрос перестал быть техническим:
Мы правда делаем систему надёжнее -
или просто строим очень умный костыль,
который однажды станет нашей главной точкой отказа?


В следующем посте - момент, когда этот вопрос перестал быть философским
и стал причиной отказа от решения, в которое уже было вложено слишком много
👍1😁1🤯1
Всем привет!
Этим постом запускаю серию про паттерн Saga - не в теории, а через реальный путь: от сломанной консистентности в распределенной системе до решения, поселившегося в продакшене. И к выводам, которые мы смогли вынести из этого опыта

В этой серии:
• как я вообще на него наткнулся
• почему «простые» решения перестают работать
• как сохранять консистентность в распределённых системах


ℹ️ Контекст:

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

Работает это так:
• пользователь сканирует QR-код на столе
• видит заказ в мобильном приложении
• применяет карту - копит бонусы или списывает уже накопленные


Пользовательский флоу элементарный.
Системный - нет

➡️ Решение “в лоб”:

Когда мы реализовывали этот флоу, о паттерне Saga мы ещё не знали.

Решение выглядело логично:
• холдируем бонусы в CRM
• последовательно выполняем операции на кассе
• фиксируем результат
• при ошибке - откатываем все


Никакой магии,
никакой надёжности,
никакой согласованности 🙂

🧪 Тестирование:

На тестовом стенде всё работало как надо! Иногда всплывали редкие аномалии - примерно один случай из ста.

Мы списывали это на:
• ограниченные ресурсы стейджа
• нестабильность окружения
• тестовые данные

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


🛑 Продакшен:

Продакшен очень быстро показал,
насколько сильно мы ошибались.
И за эту ошибку пришлось заплатить кратно

С ростом нагрузки редкие сбои
превратились в поток инцидентов

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


Стало совершенно ясно:
• это не единичные баги
• и не «особенности окружения»

❗️Это - системная проблема в реализации сервиса

⏯️ В следующий раз я расскажу:
• как мы начали разбирать эти инциденты
• какие закономерности нашли
• и почему в итоге упёрлись в вопрос консистентности
в распределенной системе
1😁1🤯1
Blue Green №3
1👍1🤯1
Продолжение серии статей про паттерн Saga. В прошлый раз мы остановились на том, что после релиза стало понятно - что проблема системная. И что проблема сама по себе никуда не денетеся. Но еще непонятно, в чем собственно проблема

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


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

🔍 Что мы сделали:
• усилили логирование
• добавили трейсы
• начали группировать инциденты


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


Сценарии разные, последствия разные - но эффект всегда один

❗️Нарушена консинстентность данных в системе

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

Мы не могли точно ответить:
• что сейчас происходит с заказом
• какие действия уже применены
• и что именно нужно откатить


Ключевой вопрос:

В какой-то момент вопрос стал предельно конкретным:
Как сохранять консистентность в распределённой системе
без общей транзакции?


С этим вопросом я пошёл искать ответы, тогда еще с поисковиком. Были же времена...

▶️ И тут появляется Saga

Через несколько статей я наткнулся на упоминание паттерна Saga, а затем — на его классическое описание на microservices.io

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

▶️ В следующих постах я расскажу:
• Как мы реализовывали Saga технически
• Почему выбрали режим оркестрации
• С какими граблями столкнулись в продакшене
😁1🤔1🤯1🥴1
Заканчиваю серию постов про паттерн Saga. В прошлый раз я остановился на моменте, когда стало понятно, что без управления распределенной транзакцией проблему консистентности не решить.

В этом посте - подробнее о реализации Saga в системе

➡️ Выбор подхода:

Saga можно реализовать через:
• хореографию
• оркестрацию

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

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


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

⚜️ Базовая идея реализации:

Главное ограничение - пользовательский флоу нельзя менять.
То есть имплементация Saga в проект должна быть бесшовной

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


Это позволило:
• безопасно выполнять откаты
• избежать полусломанных состояний
• понимать текущее состояние транзакции


🧩 Типы Saga в системе:

В системе выделены три основных сценария:
COMMIT - применение карты в заказ или досписание бонусов
CANCEL - отмена применённой карты
SUBSCRIBE - изменения заказа, инициированные кассой

Каждый сценарий разбит на атомарные шаги
с компенсирующими действиями: блокировка заказа, выполнение бизнес-условий в CRM и на кассе, разблокировка заказа

🛑 Broken Saga:

Если во время отката что-то пошло не так - Saga помечается как Broken

Дальше:
• сага уходит в фоновую обработку
• выполняются повторные попытки отката
• при неудаче требуется ручное вмешательство

Это не идеальное решение, но понятное и лёгкое в поддержке.

🚨 Продакшен-грабли:

После релиза система работала стабильно.
Ровно до первого серьёзного пика нагрузки.

Из-за задержек на стороне кассовых демонов:
• шаги перестали укладываться в TTL
• Saga начали падать на этапе блокировки заказа
• для обработки Broken Saga первый шаг всё ещё пытался заблокировать заказ
• задержка на кассе спровоцировала лавинообразное создание саг, приведя систему к отказу
• в отдельных случаях на один заказ создавались сотни Saga

Проблему пришлось решать экстренно:
🔸 Усиливали демонов
🔸 Переезжали на новые топики
🔸 Принудительно откатывали активные Saga

После переработки флоу обработки Broken Saga эти проблемы нас больше не беспокоили.

Итоги:

Saga не упростила систему. Она сделала её управляемой, но при этом значительно сложнее

Что изменилось:
🔹 Восстановилась консистентность
🔹 Пользовательский флоу стал стабильным
🔹 Поддержка перестала вручную разруливать зависшие списания

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

🔄 Промежуточный вывод:

Я однозначно напишу отдельный пост-рефлексию об этом опыте, но, завершая серию, хочу зафиксировать:
Saga свою задачу решила - она позволила взять под контроль состояния системы и управлять откатами на разных этапах. Однако цена этого решения оказалась высокой: архитектура усложнилась, требования к поддержке выросли, а жесткий контракт, сформированный уже после выхода в продакшен, заметно ограничил дальнейшее развитие сервиса.
👍3💯32🤯1🥴1
📝 Новый год - новый дневник!

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

Первый дневник, в 2024 году, я купил по простой причине: мысли перестали умещаться в голове. Их было много, структуры не было никакой. Работа, решения, ответственность, постоянный внутренний диалог - всё это не затихало ни на минуту. Мне нужно было место, куда я могу все это выгрузить

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

✔️ Неожиданно - это сработало!

Уже через несколько месяцев, впервые перечитывая записи, я заметил сразу несколько вещей: у меня сформировалась привычка, появился свой формат, а вместе со структурой в письме - структура начала появляться в моей жизни

⏺️ Дополню: мне действительно нравится свобода своего формата письма. А еще мне нравится мой почерк - когда я не спешу, он доставляет мне почти эстетическое удовольствие. Это, безусловно, сыграло положительную роль для формирования привычки

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


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


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

В следующий раз немного расскажу о формате своих ежедневных записей и об отслеживание целей с помощью дневника
Please open Telegram to view this post
VIEW IN TELEGRAM
3🤔1🤯1🥴1
❗️ Конец Blue-Green: мы выбрали процесс вместо костыля

В прошлой части остановился на вопросе: «строим систему надёжнее или умный костыль, который однажды станет нашей главной точкой отказа?»
Сегодня - ответ. И он не тот, который я планировал

➡️ Куда мы пришли технически
К моменту ревью всё почти работало:
DevOps выкатили Blue-Green в продакшен: два окружения, единый ingress, переключение трафика по кнопке activate {color}
Со стороны Django: пропатченная команда makemigrations, разделение операций на конструктивные и деструктивные, тулинг для двухфазных миграций
На горизонте - переход на дневные релизы. Цель, ради которой всё затевалось

Оставалось пройти код-ревью и описать процесс работы с новой схемой
🛑 Тех.лид пришёл с альтернативой
На ревью пришёл наш тех.лид - назовём его Серёга. И принёс ссылку на статью про паттерн Expand & Contract. По его мнению - вот правильный способ решать совместимость схемы БД. А моя реализация ему «не нравится»
Я уперся рогами. Двухфазные миграции работали, корнер-кейсы отрабатывали - я готов был защищать решение до последнего

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

💡 Кто потребитель схемы БД
Озарение пришло на одном из таких ADR. Простой вопрос: на кого вообще рассчитан этот механизм совместимости?
Я строил систему, которая поддерживает консистентность для двух потребителей - Blue и Green. То есть для двух версий бэкенда
Но у схемы БД потребителей сильно больше: смежные сервисы, отчёты, аналитика, фоновые задачи, внешние интеграции. Технология даёт контракт ровно для двух клиентов. Для всех - нужны бесконечные деньги и ресурсы, которыми мы, к сожалению, не обладаем
А корректно работающий процесс - покрывает 100% случаев. Не в вакууме, а в реальной жизни. Это не так элегантно, как техническое решение в идеальных условиях. Но несоизмеримо эффективнее

Финал
Я сдался. Признал капитуляцию, отпустил рога и пошёл внедрять процесс
Цель осталась той же - Zero Downtime и дневные релизы. Изменились только средства. Через неделю после последнего архкома мы выкатили первый релиз в дневное время. Без костыля, только на процессе
Эта история длиной в 3.5 года потом легла в основу моего доклада на Moscow Python №107. Финальный тезис серии и доклада совпадает:
Не пишите костыли, процессы рулят


А Серёга оказался единственным голосом разума на всю компанию. Я слишком долго не верил, что проблему нельзя решить технически. В итоге пришёл к тому, что можно - но не полностью
👍2😁1🤯1