Microservices Thoughts
7.76K subscribers
32 photos
56 links
Вопросы и авторские статьи по микросервисам, архитектуре, БД

Сотрудничество: t.iss.one/qsqnk
Download Telegram
Зачем нужны многоколоночные foreign key

Представь, тебе нужно описать граф в реляционной модели

Скорее всего получится приблизительно такое:

create table graph (
id bigserial primary key
);

create table node (
id bigserial primary key,
graph_id bigint
);

create table edge (
id bigserial primary key,
from_id bigint,
to_id bigint
);


Далее добавим внешние ключи, чтобы гарантировать целостность

node (graph_id) -> graph (id)
edge (from_id) -> node (id)
edge (to_id) -> node (id)


И на этом в целом можно закончить

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

graph(id = 1)
graph(id = 2)

node(id = 1, graph_id = 1)
node(id = 2, graph_id = 2)

edge(id = 1, from_id = 1, to_id = 2) // no error


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

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

1. Добавляем в таблицу edge колонку graph_id
2. Для ребер многоколоночные внешние ключи:

node (graph_id) -> graph (id)
edge (graph_id, from_id) -> node (graph_id, id)
edge (graph_id, to_id) -> node (graph_id, id)


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

p.s.: для того чтобы сделать многоколоночный внешний ключ, на целевой таблице этот набор колонок должен быть уникальным — в нашем случае должен быть primary key / unique index на node (graph_id, id)
2👍32🤔11🔥3💅11
Microservices Thoughts
И немного детокса от менеджмента На работе мне давеча пришлось разбираться с function calling в LLM Что это такое? Наверняка уже все видели агентов, которым даешь какое-то задание, они ходят по каким-то сайтам/апишкам, что-то собирают, что-то делают, и отдают…
В продолжение: как связаны function calling и MCP

function calling — функциональность модели, которая:
- позволяет клиенту вместе с промтом передать список тулзов, которые модель может "использовать"
- модель отвечает, какие тулзы и с какими параметрами нужно вызвать
- и далее клиент совершает вызовы и передает результаты обратно в модель

MCP server же в свою очередь выполняет две фукнции:
- говорит, какие тулзы вообще есть (и не только тулзы)
- позволяет через себя вызывать эти тулзы

Чуть строже: mcp — это протокол, который описывает, как должен выглядеть mcp client и mcp server: то есть буквально, какое API у mcp сервера, и как mcp клиент в это API должен долбиться

Такая стандартизация довольно удобна, тк позволяет наклепать mcp клиента на одном языке, mcp сервер на другом, и все будет работать, тк и тот и тот соблюдают протокол

Также это позволяет каждый раз не задавать вручную, какие тулзы есть у очередного ai-приложения, а просто один раз их описать в mcp сервере. Например, есть mcp сервер гитхаба, и к нему можно подключиться хоть из курсора, хоть из claude code, хоть из какого-то своего приложения

---

На практике — чтобы создать свой mcp сервер, берешь какую-то готовую либу, описываешь какие у тебя есть тулзы (человекочитаемое описание + спека параметров), описываешь как тул должен исполняться. Готово

Для клиента аналогично — берешь готовую либу, вставляешь урл mcp сервера, токен авторизации. Готово

---

И если суммаризировать — как связаны function calling и MCP:


app -> mcp: запрос на получение списка тулзов
app <- mcp: список тулзов

app -> llm: запрос со списком тулзов (function calling)
app <- llm: какие тулзы надо вызвать

app -> mcp: вызов тулзов
app <- mcp: результаты вызова

app -> llm: финальный запрос с результатами вызова
app <- llm: финальный ответ


👍 — если осознали
👍47🔥5😁22💅1
Немного чувствую вину, что в исконно бэкендовый канал практически ничего не пишу про бэкенд))

Поэтому буду признателен, если в комментах поделитесь темами/практическими задачами/etc, про которые было бы интересно почитать

p.s.: если чето интересно про мльку или управление командой, тоже пишите
😁10👍2
и небольшой опросник для понимания общей картины

мне интересны посты про:
Anonymous Poll
95%
бэкенд
22%
мл
24%
менеджмент
Как разобраться в новой кодовой базе

По просьбе https://t.iss.one/MicroservicesThoughts/213?comment=2217

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

Думаю с опытом у каждого вырабатывается свой подход, поэтому ниже субъективщина, как разбираюсь в новом сервисе я (зачастую неосознанно)

1. Посмотреть что снаружи

Обычно сервис живет в рамках какого-то bounded context-а, где он закрывает определенную задачу

Например:
- есть pricing-service
- выясняем, что он живет в рамках контекста checkout (оформление заказа). Там есть checkout-service, cart-service, pricing-service
- pricing-service закрывает собой задачу ценообразования: хранит в себе правила расчета итоговой цены с учетом скидок, промокодов и доставки

Артефакты:
- контекст
- задача, которую закрывает сервис

2. Модель данных

На этом этапе хочется понять, какие основные сущности есть внутри сервиса, и какие между ними связи

Здесь удобно сгенерить ER-диаграмму по сущностям БД (делается за пару кликов в ide/dbeaver/...), и на основе нее подопрашивать коллег

Артефакты:
- ER диаграмма

3. Инварианты

Самые основные бизнес правила, которые в себе инкапсулирует сервис. Например, в pricing-service могло бы быть что-то такое:
- Итоговая цена = базовая цена + надбавки – скидки
- Итоговая цена всегда неотрицательна

Артефакты:
- Список инвариантов

4. Посмотреть на основные сценарии

И только тут начинаем детально копаться в коде

Зачастую есть 4-5 основных апишек, благодаря которым происходит вся основная работа

Нужно их взять и детально раскрутить, как по коду происходят вызовы: что вызывается и в какой последовательности

Только ради бога в 2025 не занимайтесь этим полностью вручную, когда есть Cursor и ask mode))

Артефакты:
- Основные сценарии и их цепочки вызовов

5. Разобрать пару баг репортов

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

Также багрепорты зачастую подсвечивают херовые места в коде (без них скорее всего баг бы не произошел)

---

Overall после такого появляется понимание
- общего контекста и задачи сервиса
- как устроены данные
- как в коде реализованы основные сценарии, по каким компонентам они проходят
- в каких местах находили баги

И делитесь в комментах, если у вас другой подход:)
👍39🔥22
Внезапный пост — ищу разработчика

https://yandex.ru/jobs/vacancies/razrabotchik-bekenda-v-infrastrukturu-klientskogo-servisa-yandex-crowd-40028

Без автоматизации не получить эффективный клиентский сервис. Мы как раз занимаемся разработкой low-code платформы для автоматизации поддержки: тысячи workflow, миллионы запусков в день, ML-классификаторы, RAG и вот это всё

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

Стек: kotlin, spring, postgresql + экспериментируем с langchain4j

По всем вопросам можно писать мне напрямую: @qsqnk

p.s.: если у вас есть знакомые, кому было бы интересно, смело рекомендуйте
🔥15😁12👍33
Делать ли систему масштабируемой заранее

В ответ на https://t.iss.one/MicroservicesThoughts/213?comment=2233

Это вопрос управления рисками. Можно пользоваться простой ментальной моделью:

- cost_prepare — стоимость подготовки
Сколько нам будет стоить сделать систему масштабируемой заранее

- growth_probability — вероятность роста нагрузки
Каков шанс, что нагрузка повысится до такого уровня, что текущая архитектура не вывезет

- cost_failure — стоимость фейла при внезапном росте нагрузки
Сколько нам будет стоить экстренно масштабировать систему + стоимость репутационных потерь, инцидентов, срочных фиксов и т.д.

Если мы заранее подготовим систему, то стоимость риска = cost_prepare

Если мы заранее не подготовим систему, то стоимость риска = growth_probability * cost_failure

cost_prepare > growth_probability * cost_failure => забиваем на преждевременное масштабирование

cost_prepare < growth_probability * cost_failure => заранее масштабируемся

---

Пример:
Текущая нагрузка 100rps, 1000 клиентов, сервис нормально работает

Допустим:
Стоимость доработать, чтобы сервис выдерживал 1000 rps = 100 человекочасов
Вероятность, что кол-во пользователей увеличится в 10 раз = 0.1
Стоимость экстренных доработок = 200 человекочасов

Если мы заранее подготовим систему, то стоимость риска = 100 человекочасов

Если мы заранее не подготовим систему, то стоимость риска = 0.1 * 200 человекочасов = 20 человекочасов

Значит заранее оптимизировать не очень осмысленно

---

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

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

Как завещал Клеппман
An architecture that is appropriate for one level of load is unlikely to cope with 10 times that load. If you are working on a fast-growing service, it is therefore likely that you will need to rethink your architecture on every order of magnitude load increase or perhaps even more often than that.
1👍39🔥122🤯2💅1
Рандомный пример применения ллмок в жизни:

1. Скачиваем весь контент тг канала через @ToCsvBot

2. Закидываем csv-шку в chatgpt и просим проанализировать контент


Я автор телеграм канал про бэкенд. Прикрепляю csv файл с контентом канала и метриками постов

Твоя задача:

1. Выделить названия постов. Название поста обычно находится в первом абзаце и выделено жирным шрифтом (окружено символами "**")

2. На основе названий с помощью LLM выделить набор тематик

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


3. Агент внутри чат гпт запускает питон, рассуждает и с помощью pandas-а делает разные срезы по данным и что-то считает

А мы получаем кайфовые графики
1👍43🔥8
Про Стратоплан и менеджмент pt.2

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

Поэтому я все сильнее склоняюсь к мысли, что сами концепции менеджмента максимально простые, понятные и даже очевидные, а основной скилл — это уметь не забывать про эти концепции на практике + аккуратно учитывать человеческий/организацонный/политический контекст. Из этого простой вывод — голое изучение теории даст примерно 0 пользы (в отличие от инженерки). Поэтому что-то изучили => опиздюлились на практике => поняли как надо => прокачались

Про очередные 4 занятия:
- Бизнес-процессы
- Оптимизация бизнес-процессов
- Метрики и KPI
- Внедрение изменений

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

Делегирование через бизнес-процесс

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

И хз почему, но тут многие упускают мысль, что задачу в общем-то не обязательно делать как единое целое

1. Декомпозируй задачу на понятные этапы, каждый из которых осилит кто-то из подчиненных
2. Построй из этих этапов бизнес-процесс, и дай ответственность за выполнение каждого отдельного этапа разным людям
3. Ты становишься просто "окателем" результата каждого этапа

Это как понятный мысленный фреймворк, что делать, если на тебе какие-то сложные задачи, которые пока хрен знает как делегировать

Про внедрение изменений и матрицу стейкхолдеров

Особенно релевантная для меня часть, потому что прямо сейчас на работе делаем большой реорг

У любого изменения есть стейкхолдеры. С разными стейкхолдерами нужно работать сильно по разному. И для этого предлагается простой фреймворк:

1. Разобьем стейкхолдеров по влиянию/заинтересованности
2. Получим 4 группы. Со всеми членами определенной группы можно работать +- одинаково:
- низкое влияние + низкая заинтересованность => информируем
- низкое влияние + высокая заинтересованность => собираем данные вовлекаем
- высокое влияние + низкая заинтересованность => держим в курсе, согласуем ключевые вещи
- выосокое влияние + высокая заинтересованность => активно сотрудничаем

Это как раз мысль из серии "супер очевидно, но легко продолбать на практике"

---

Как-то так прошел очередной месяц обучения. Задавайте вопросы и делитесь мнением в комментах:)

Предыдущая часть
👍29🔥163🤯21
Предновогодний пост

Хочу поделиться одной из наиболее релевантных тем для меня за этот год — как не загнуться в новой роли

На работе за этот год я побывал в 4х ролях (или почему посты выходят раз в месяц)

1. Лид одной команды бэкендеров

2. Лид всего бэкенда (несколько команд)

3. Лид всего бэкенда + лид vteam по внедрению ml в клиентскую поддержку

*происходит реорг, который функциональные структуры превращает в кросс-функциональные команды + гильдии*

4. Лид гильдии бэкенда + лид vteam + зам своего рук-ля

---

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

Хорошая новость — с этим можно что-то делать

Страх, что не получится

Но что такое "не получится"? Это значит кто-то тобой недоволен => ты нарушил чьи-то ожидания => а были какие-то ожидания?

Были. И очень важно в явном виде сформулировать взаимные ожидания со всеми ключевыми стейколдерами, с которыми тебе надо будет взаимодействовать

По крайней мере, это даст понимание, хорошо или плохо ты справляешься

Непонимание, а с чего начать

Из предыдущих разговоров у тебя скорее всего появится список актуальных проблем в твоей текущей зоне ответственности

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

---

Если подытожить в трех пунктах, то алгоритм выглядит так:
1. Сформировать ожидания с ключевыми стейкхолдерами
2. Набрать список текущих проблем
3. Показать какие-то quick wins

После этого дальше двигаться будет сильно проще

---

И в заключение хочу вас поздравить с наступающим Новым годом! Пусть вас окружают близкие по духу люди, поражения не ломают, а победы вдохновляют)
2👍97🔥30🤔6💅1
Yet another пост про то, как победить неопределенность

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

Мне помогает такой способ:
1. Взять пункт, который точно придется делать
2. Подумать, что должно быть до него
3. Подумать, что должно быть после него

Пример: нужно сделать гайдлайны по написанию тестов в нашей системе

Что точно нужно сделать?
- написать пример теста

Что мне нужно для выполнения этого пункта?
- определиться, какого типа будет этот тест (unit / integration / ...)
- определиться, на что писать этот тест
- определиться, как будет выглядить этот тест

Что надо сделать после?
- добавить этот пример в доку
- презентовать команде

И из этого вырисовывается вполне понятный список дел:
1. определиться, какого типа хотим тесты
2. определиться, на что пишем тесты
3. определиться с кодстайлом
4. написать пример теста
5. написать доку
6. презентовать команде

И таким образом из размытой непонятной задачи сформировали вполне понятный план. Пользуйтесь!
2👍67🔥17
Про Стратоплан и менеджмент pt.3

На новогодних закрываю долги по курсу. Очередные 4 занятия:
• Основы финансового менеджмента
• Построение финмоделей
• Бюджетирование
• Управление ресурсами

Первые два занятия — введение в финансы: как двигаются деньги в компании, основные отчеты (PnL, Cash Flow, Баланс), коэффициенты рентабельности и т.п.

Еще из интересного: в эксельке посмотрели на реальные финмодели из прошлой практики преподавателя и попробовали оценить целесообразность в них инвестировать с помощью NPV, IRR, PP, DPP

Как считать NPV (Net Present Value): берем прогноз денежных потоков (поступления и выплаты), берем некоторую ставку дисконтирования r — ставку, позволяющая перевести будущие денежные потоки в текущую стоимость, может быть %-ом инфляции, ставкой кредитования, WACC, ...

И далее считаем сумму денежных потоков (CF) с учетом ставки дисконтирования (r) и из нее вычитаем начальные инвестиции

NPV = Σ (CFₜ / (1 + r)ᵗ) − CF₀

Если NPV > 0 за некоторый период, то с учетом данной ставки дисконтирования проект окупится

IRR (Internal Rate of Return) — связанная вещь, где в формуле выше ставка дисконтирования берется за переменную, и считается при какой ставке дисконтирования проект сможет окупить инвестиции

PP (Payback Period), DPP (Discounted Payback Period) — всё та же формула. Только уже считаем за какой срок окупятся инвестиции в проект без учета/с учетом ставки дисконтирования

Это всё конечно занимательно, но хороший вопрос — где это прямо сейчас применять. Скорее это пока из серии "через месяц забуду и вернусь к ним, когда понадобится"



Третье и четвертое занятия в этом смысле более прикладные

Третье — про процесс работы с бюджетами: финансовый и операционный бюджеты; как планировать, защищать, контролировать и т.д. Отдельно порадовали кулстори из жизни про то, как можно защитить бюджет, если начальство не согласно (иногда не меняя общую сумму)

И последнее в этом блоке занятие — про планирование ресурсов. Тут мне понравился алгоритм, так что даже поделюсь:

Задача — запланировать проекты на квартал/полугодие/...

1. Делаем карту компетенций по сотрудникам команды. Если не требуется чего-то особенного, зачастую компетенции будут уровня back, front, qa, аналитика и т.п.

2. Делаем табличку "team capacity" — сколько ресурсов определенной компетенции есть в рамках команды. И здесь хороший вопрос — в каких единицах измерения оценивать: можно в обычных человекочасах, это простой способ, но одновременно крайне неточный. Можно в "идеальных человекочасах" — это когда мы берем условного разработчика, откидываем от него ~10% времени на поддержку, ~20% времени на техдолг, ~10% на "срочные влеты", ~15% на встречи, и получаем скудные ~35-40% времени на написание новых фичей — именно это называется идеальными человекочасами, которые у разработчика будут на делание проекта

3. Делаем табличку "спрос" — сколько ресурсов определенной компетенции нужно для завершения проектов X, Y, Z

4. И сводя "team capacity" и "спрос" мы можем получить, сколько % ресурсов определенной компетенции у нас есть для закрытия всех проектов. Например back - 52%, front - 56%, qa - 39%. Именно это нам позволяет понять узкое место команды

5. И далее наша цель — максимально нагрузить узкое место, поскольку оно определяет мощность команды, выбрав при этом проекты с максимальными эффектами

К слову этот алгоритм очень матчится с тем, что написано в "Цели" Голдратта. Может в будущем запилю отдельный пост по этой книге

Пишите мнение в комментариях, задавайте вопросы
👍21🔥15