Здравствуйте, gandjustas, Вы писали:
G>·>Реальные физические акторы физически разделены и физически невозможно обеспечить 100% надёжную коммуникацию между ними. G>Как связаны реальны акторы и информационная система?
Информационная система — это модель реальных акторов. Чем модель точнее, тем лучше работает.
G>·>Поэтому в CAP будет присутствовать компонента P, хочется тебе того или нет. G>Как связаны реальные акторы и CAP?
Вот там тебе писали пример: "Потому что с утра жахнули при разгрузке два холодоса об асфальт, а списать еще не списали".
G>>>О какой проблеме идет речь? G>·>"задачу, которая откатывает незавершенные резервы". G>Эта проблема решается транзакциями в БД. G>Если ты уверен что нет, то наверное можешь показать пример как СУБД с ACID гарантиями не откатывает незавершенные транзакции.
Читай внимательно: "незавершенные резервы" != "незавершенные транзакции".
G>>>И что? Нам поэтому нужно сделать отдельные базы для Заказа, Склада и Пользователя, чтобы соответствовало существительным? G>·>Не чтобы соответствовало существительным, а чтобы сабж. G>А зачем это? Самоцель сделать микросервисы? Потребителю пофиг сколько у вас сервисов.
Цель: правильно спроектировать.
G>>>А как в 1С конфигурации УНФ это все в одной базе существует? Оно как-то неправильно работает? G>>>В 1С вообще это все решалось в рамках одной базы задолго до появления термина "микросервисы". В чем они неправы? G>·>Хреново 1С работает. Не знаю как оно изменилось с тех пор, но раньше это был просто ад — все ломятся через RDP на один гигасервер и простейшие операции работают минуты. И если что-то где-то упало, то всё и сразу лежит. G>Показывает уровень понимания 1С...
Наверное. Но никогда не слышал, что 1С отличалась скоростью работы и стабильностью. Десяток пользователей, как правило, уложат любой крутой 1С сервак.
G>Давай проще, я в статье описал пример кода, который в одной базе сохраняет заказы и меняет остатки транзакционно https://habr.com/ru/articles/955714/ Без RDP работает.
Ну честно говоря в ретейле я давно не работал. А для трейдинга это какие-то смешные показатели перформанса.
Вот недавно как раз завершили decomission старой системы с субд, acid и прочим. Время отклика уменьшилось с 300мс до 3мс.
G>Можешь прям в коде показать где там проблемы, которые я игнорирую?
Честно говоря, всё читать лень, но вот эту, например: "резерв полностью прошел но оплата не прошла".
G>>>Важно. В монолите это все не нужно. Монобаза тебе обеспечивает атомарность, вообще всегда. G>·>Если после 2-го пункта произойдёт какая-либо ошибка, как тебе поможет твоя атомаронсть? G>Про какой второй пункт речь?
Второй из этих: G>>>·>1. Пользователь создаёт заказ G>>>·>2. Склад резервирует заказ G>>>·>3. Пользователь завершает заказ
Пользователь завершает заказ после оформления доставки, оплаты и прочего. Обычно может длиться от нескольких минут до нескольких месяцев.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Sinclair, Вы писали:
G>>Все проще, пользователь просто закрыл страницу когда не дождался ответа или интернет ему выключили. В любом случае сервер увидел потерю соединения и запустил отмену через CancellationToken, который из контроллера прокидывается во всю БЛ. S>Нет конечно, сервер ничего не "увидел", и никакую "отмену" он не запустил. S>Сервер может заметить потерю клиента только в тот момент, когда он начинает отправлять клиенту респонс — после того, как все транзакции уже уехали в durable log.
Даже как-то странно это читать.
Есть tcp keepalives (вряд ли применимо в нашем сценарии), есть HTTP2 Ping, есть просто таймаут браузера примерно 60-90 сек если не получен ответ.
S>Наоборот делать ни в коем случае нельзя — иначе клиент получит ответ, который может исчезнуть после перезагрузки сервиса. S>Более того — сервер может так и не увидеть отвала клиента даже после отправки ответа.
Тем не менее рекомендуемый способ в asp.net — использовать CancellationToken в запросе.
S>Например, между клиентом и сервером стоит прокси, который в любом случае вычитает ответ до конца и вежливо дождётся закрытия соединения со стороны сервера.
Вот тут я вообще не уверен.
Потому что буквально на днях мне показали багу, которая возникала при отключении клиента. Как в раз в сценарии, когда надо было в базу записать в и очередь отправить. И обе операции должны были быть выполнены атомарно.
Клиент отключался, соединение разрывалось, CancellationToken взводился, запрос прерывался там где должен был отправить в очередь, но отправка произойти не успела.
Продовый сервер в кубере за nginx ingress.
Но это в целом неважно. Веб-сервер тоже может упасть между двумя операциями. Просто по OOM будет убит по какой-то причине.
G>>И это событие по счастливой случайности происходит ровно в момент между тем как А ответил подтверждением, а на сервер Б еще не отправлена команда на изменение статуса заказа. S>Вы по-прежнему пишете какие-то непонятные мне вещи. Никакой "команды на изменение статуса заказа" на сервер Б не отправляется. S>В этой архитектуре ....
То есть в П7 на сервере А мы сохраняем полную копию заказа, как на сервере Б. В одной атомарной транзакции.
На этом можно заканчивать. без МСА было бы достаточно одного действия в П7. Insert вполне можно заменить на update без потери остальных свойств.
G>>В описанном выше сценарии пользователь перезагрузивший страницу\приложение увидит что заказ все еще в статусе "резервируется". S>Можно и так написать, но зачем делать плохое решение, когда есть хорошее?
Полностью согласен.
Хорошее решение я увидел из детального описания сценария, оно полностью содержится в п7. Все остальное не нужно, как и разделение баз.
G>>Мне кажется дальнейшее пока рано обсуждать, потому что мы пока не достигли единого понимания сценария фейла для "транзакции" из двух таблиц. Когда поймем эти сценарии и поймем как их можно компенсировать за счет кода можно обсуждать все остальное. S>Ок, давайте достигнем. Есть какие-то моменты, непонятные в схеме выше?
Спасибо, теперь стало понятно о чем речь.
Кстати примерно как-то так и реализовано у Озона, но не от больших архитектурных талантов, а от того, что 3к разработчиков должны хоть как-то пилить систему не мешая друг другу.
Надо понимать что далеко не все мы делаем Озон. По сути кроме озона никто не делает Озон
Re[33]: Помогите правильно спроектировать микросервисное при
Здравствуйте, ·, Вы писали:
·>Здравствуйте, gandjustas, Вы писали:
G>>·>Реальные физические акторы физически разделены и физически невозможно обеспечить 100% надёжную коммуникацию между ними. G>>Как связаны реальны акторы и информационная система? ·>Информационная система — это модель реальных акторов.
кто это придумал вообще?
·>Чем модель точнее, тем лучше работает.
Есть какие-то доказательства этом тезису?
G>>·>Поэтому в CAP будет присутствовать компонента P, хочется тебе того или нет. G>>Как связаны реальные акторы и CAP? ·>Вот там тебе писали пример: "Потому что с утра жахнули при разгрузке два холодоса об асфальт, а списать еще не списали".
Как это связано с обсуждаемым вопросом?
G>>>>И что? Нам поэтому нужно сделать отдельные базы для Заказа, Склада и Пользователя, чтобы соответствовало существительным? G>>·>Не чтобы соответствовало существительным, а чтобы сабж. G>>А зачем это? Самоцель сделать микросервисы? Потребителю пофиг сколько у вас сервисов. ·>Цель: правильно спроектировать.
Если "правильно" это "точная модель реальных акторов", то вы в чем-то правы.
В реальности "правильно", это "удовлетворяя функциональные и нефункциональные требования с минимальными затратами"
не видел я доказательств что "точная модель реальных акторов" как-то уменьшает затраты.
G>>>>А как в 1С конфигурации УНФ это все в одной базе существует? Оно как-то неправильно работает? G>>>>В 1С вообще это все решалось в рамках одной базы задолго до появления термина "микросервисы". В чем они неправы? G>>·>Хреново 1С работает. Не знаю как оно изменилось с тех пор, но раньше это был просто ад — все ломятся через RDP на один гигасервер и простейшие операции работают минуты. И если что-то где-то упало, то всё и сразу лежит. G>>Показывает уровень понимания 1С... ·>Наверное. Но никогда не слышал, что 1С отличалась скоростью работы и стабильностью. Десяток пользователей, как правило, уложат любой крутой 1С сервак.
1С сервак может и уложат, а вот базе будет пофиг.
Глазами видел как посгрес держал 10 эквивалентных по ресурсам серверов 1С и еще запас был. Примерно 2000 tps приходило, на быстродействии 1С это незаметно сказывалось.
При этом 1С умудряется работать в монобазах.
G>>Давай проще, я в статье описал пример кода, который в одной базе сохраняет заказы и меняет остатки транзакционно https://habr.com/ru/articles/955714/ Без RDP работает. ·>Ну честно говоря в ретейле я давно не работал. А для трейдинга это какие-то смешные показатели перформанса. ·>Вот недавно как раз завершили decomission старой системы с субд, acid и прочим. Время отклика уменьшилось с 300мс до 3мс.
Писать в dev/null можно еще быстрее.
G>>Можешь прям в коде показать где там проблемы, которые я игнорирую? ·>Честно говоря, всё читать лень, но вот эту, например: "резерв полностью прошел но оплата не прошла".
Да мы еще резерв не прошли
Давай вернемся к нему.
напиши как сделать резерв заказа, чтобы:
1) не продать больше чем есть на складе
2) если остатка недостаточно для резерве, то состояние заказа не меняется
3) все это должно переживать внезапные отключения клиента, падения серверов и прочие катаклизмы
4) так чтобы это было эффективнее монобазы (в любом смысле)
Re[34]: Помогите правильно спроектировать микросервисное при
Здравствуйте, gandjustas, Вы писали:
G>Даже как-то странно это читать. G>Есть tcp keepalives (вряд ли применимо в нашем сценарии), есть HTTP2 Ping, есть просто таймаут браузера примерно 60-90 сек если не получен ответ.
А можете привести пример кода REST-сервиса, который использует что-то из перечисленного для проверки "наличия клиента"?
G>Тем не менее рекомендуемый способ в asp.net — использовать CancellationToken в запросе.
Возможно, мы с вами по-разному читаем эти рекомендации. Можете набросать схему использования CancellationToken в запросе резервирования товаров?
G>Потому что буквально на днях мне показали багу, которая возникала при отключении клиента. Как в раз в сценарии, когда надо было в базу записать в и очередь отправить. И обе операции должны были быть выполнены атомарно. G>Клиент отключался, соединение разрывалось, CancellationToken взводился, запрос прерывался там где должен был отправить в очередь, но отправка произойти не успела.
Скорее всего причина баги — как раз в том, что кто-то неверно трактовал рекомендации ASP.NET. Насколько я знаю, ClientDisconnectedToken предназначен для сценариев потоковой отправки — например, тех самых /orders/42/events. Применение его внутри атомарных запросов — лучший способ обеспечить себя багами для починки.
G>Но это в целом неважно. Веб-сервер тоже может упасть между двумя операциями. Просто по OOM будет убит по какой-то причине.
Именно. Поэтому мы делаем так, как я написал.
G>То есть в П7 на сервере А мы сохраняем полную копию заказа, как на сервере Б. В одной атомарной транзакции.
Процитирую то, что я написал три поста назад:
Да, объекты, пересекающие границы сервисов, в МСА должны храниться на обеих сторонах. Это не обязательно одни и те же объекты, но у них должна быть общая проекция. В данном случае сторону склада не интересуют никакие подробности про способы доставки товара, розничные цены, или там демографию покупателя, но вот список артикулов и количеств, снабжённый уникальным ID, ей необходим. Ровно для того, чтобы когда к нему в следующий раз стукнутся с просьбой зарезервировать корзинку №42342342 он мог не делать повторный резерв, а сразу отдать 200 ok.
Проекция в данном случае — это как раз те items, которые мы передаём на удалённую сторону. В сервисе Б там может быть гораздо больше всяких данных — про доставку, про способ оплаты, про подарочную упаковку, и так далее.
Ничего этого складскому сервису не надо, поэтому речь идёт не о "полной копии". Заодно это изолирует наш складской сервис от изменений в сервисе заказов — например, добавление опции "упаковать как подарок" изменит схему БД сервиса Б, никак не трогая сервис А. Что позволяет нам, к примеру, накатывать изменение на сервис Б, не приостанавливая операции в сервисе А (скажем, отгрузки уже оплаченных заказов).
G>На этом можно заканчивать. без МСА было бы достаточно одного действия в П7. Insert вполне можно заменить на update без потери остальных свойств.
Конечно. Если всё лежит в одной базе, можно обойтись без хранения "лишних" проекций.
G>Хорошее решение я увидел из детального описания сценария, оно полностью содержится в п7. Все остальное не нужно, как и разделение баз.
G>Надо понимать что далеко не все мы делаем Озон. По сути кроме озона никто не делает Озон
Ну почему же. Кроме озона, Озон делает вайлдберриз, яндекс, сбер, т-системы, и ещё с десяток игроков поменьше.
И да, административные границы тут первичны. Не обязательно из-за отсутствия техлида или ещё каких-то прямо фатальных дефектов.
Страшнее всего — совмещение разных уровней разработчиков в одном продукте. Криворукий джун, который неровно добавил баннеры в наш монолит, может положить всю систему. У нас конечно CI/CD, но перетестирование монолита — это прогон всех интеграционных тестов перед релизом. Что в мало-мальски большой системе занимает столько времени, что очень много усилий тратится на изобретение способов обойтись без них.
Понятно, что можно пытаться изолировать компоненты — но всё это упирается в разработчицкую дисциплину, которую, опять же, легко поддерживать в команде из 10 человек, и трудно — в команде из 3000 человек.
И даже при самой полной изоляции кода нет уверенности в том, что дурацкая баннерокрутилка не засрёт логами диск так, что весь постгрес ляжет с диагностикой insufficient disk space, парализовав вообще всё.
Недостатки монолита хорошо видны в той же самой винде, когда explorer.exe до сих пор иногда зависает в самый неподходящий момент из-за очередного криво написанного COM Extension, а обновление Tortoise Git требует перезагрузки всей машины.
В остальном — повторюсь: да, я согласен. YAGNI в полный рост — при нормальной архитектуре монолита хватает очень надолго. А к моменту, когда он перестаёт справляться, уже есть более-менее реальная статистика использования, благодаря которой можно пилить систему на сервисы осознанным образом. А не так, что "нам надо трудоустроить 39 начальников отделов — давайте напилим 39 микросервисов и дадим всем сестрам по серьгам".
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[32]: Помогите правильно спроектировать микросервисное при
Здравствуйте, gandjustas, Вы писали:
G>По сути для pg есть готовый модуль автопартицирования. Ему даешь в ход таблицу и ключи и он автоматм управляет всеми партициями. Правда входит этот модуль в PostgresPro Enterprise, но если вы дожили до необходимости партицирования, то денег на него хватит. Там еще будет и BiHa прилагаться, и мультмастер кластеры и много чего еще хорошего. И только когда ресурсы в одного мастера уже не будут закрывать все потребности, тогда можно и пробовать шардировать базу.
У меня личного опыта администрирования продакшн постгреса нет, поэтому не могу с вами поддержать беседу на должном уровне.
Но ПостгресПро работают географически близко от меня, поэтому есть возможность смотреть "через плечо" на их ресёрч.
Так вот, судя по ресёрчу, все эти BiHa и прочие адвансед вещи (начиная от репликации) там, скажем так, далеки от идеала. Рекламные проспекты стараются тактично умалчивать о всяких интересных особенностях, которые приходится активно пилить. Возможно, если бы у меня был доступ к R&D MS SQL, то у меня было бы меньше иллюзий про откатанность аналогичных сценариев у них.
В целом у меня нет ощущения, что подобные решения делаются в реляционках по щелчку пальцев.
Основная разница, имхо — в том, что MSA заставляет инвестировать в распиливание заранее, а не в том, что она какие-то усилия экономит или какой-то перформанс улучшает в моменте. G>А что мешает навалить ресурсов на монолит? G>Я в яндексе могу постгрес поднять с 4 ядер до 96 в 4 клика. И также пропорционально прирастет память на сервере. До 2 млн активных пользователей выдержит я думаю.
А IOPS вы тоже в 20 раз в 4 клика ему подымете?
G>А если дойдет до шардирования, то затраты на репликацию общих таблиц окажутся в разы меньше чем на обеспечение кросс-сервисной коммуникации.
Лично мне механика кросс-сервисной коммуникации понятна от и до. Что создаёт иллюзию контроля.
А репликация в том же постгре для меня выглядит так: "Иногда, если слейв слишком сильно отстал от мастера, то ему не удаётся нащупать нужный LSN при репликации". Или "в некоторых сценариях TSN на мастере и слейве может разьехаться так, что у них нет общей предыстории". Или там "в процессе восстановления после сбоя постгрес не принимает никаких соединений; в некоторых сценариях он может подолгу ничего не писать в лог. Поэтому проблема надёжного детектирования сбоя рекавери является актуальной".
Это я по памяти пересказываю темы ВКР стажирующихся в постгресе студентов. На защитах про это слушать прикольно; но когда я думаю про возможность нарваться на такое в проде, у меня шевелятся остатки волос на голове.
G>Ровно та часть, которой это требуется.
Ну, лично в вас я уверен. К сожалению, как только мы переходим с разработчицкой стороны на менеджерскую, то выясняется, что даже те немногие бэкендеры, которые вообще владеют SQL, в большинстве не понимают смысла уровней изоляции. Ещё меньше таких, кто умеет их корректно применять G>Мне к сожалению сейчас проект достался с МСА и кучей багов неконсистентности. За последние 3 месяца была пара сценариев, которые я непосредственно ревьювил, где нужен был уровень serializable, в остальных справлялись read committed.
Ок, согласен. Сравнивая "компетентные разработчики в МСА" с "некомпететнными разработчиками в монолите" выиграет МСА. Но "некомпетентные разработчики в МСА" напорют, наверное, больше, чем "компетентные разработчики в монолите" S>>Это интересно. Я так не умею. Есть какой-то авторитетный источник, который описывает механизм этого чуда для невежд вроде меня? G>https://kubernetes.io/docs/tutorials/kubernetes-basics/update/update-intro/
Не-не-не. Меня не команды Кубера интересуют. Как вы сделаете роллинг апдейт так, что у вас половина подов в версии 3, половина в версии 2, и все при этом работают, при том что схема базы у нас где-то между версиями 2 и 3?
S>>Потому что мне непонятно, как это у нас делаются роллинг апдейты, задействующие схему базы, с учётом того, что она у нас в единственном экземпляре. G>Достаточно придерживаться простых правил: G>1) В схему только добавляем таблицы и колонки (кроме access exclusive на таблицу ничего не надо). G>2) Удаляем таблицы колонки только если если они нигде не используются в проде (на момент создания ветки из мастера нет ни одной ссылки из БЛ). такие апдейты накатываем в периоды низкой активности.
Не вижу, как бы этого было достаточно.
S>>>>И количество серверов СУБД в HA-кластере вас не спасёт от того, что апдейт схемы плохо совместим с data-level блокировками. G>>>А как тут разделение поможет? Если вам нужен access exclusive на таблицу для обновления, то какая разница сколько всего у вас баз? S>>Большая. Эксклюзивность-то мне нужна не на все базы, а только на вот эту конкретную, в которой я меняю схему. А остальные как ехали, так и едут — их вообще это обновление не касается. G>Если миграции ограничить только добавлением колонок, таблиц и индексов, то лочить всю базу им не надо. Им надо лочить отдельные таблицы.
Ок, поясняю свое беспокойство. Вот мы идём и апгрейдим базу.
Начали добавлять колонки в таблицу Т1. Получили на неё access exclusive, добавили, перешли к таблице T2. А в это время прикладная транзакция делает что-то невинное, например — пишет в T2, и собирается писать в T1.
Значит, она не даёт нам получить access exclusive на T2, а мы не даём ей получить блокировку на T1.
Кто-то из нас будет выбран жертвой дедлока.
G>Монопольного режима к одной таблице, а не к базе целиком. Не надо путать.
Почему к одной-то? Ко всем задействованным, а лучше — ко всем, которые косвенно связаны с изменяемыми таблицами (могут быть изменены в одной транзакции с нашей).
G>Партицирование делается один раз если что.
Сразу всей базы?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[33]: Помогите правильно спроектировать микросервисное при
Кстати, вовсе необязательно делать все строки заказа в одной БД-транзакции. Их можно делать поштучно или разбивать на батчи, шарды и т.п. с целью чтобы транзакции были меньшего размера. Это позволит сильнее параллелить и меньше крутиться на локах.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[34]: Помогите правильно спроектировать микросервисное при
Здравствуйте, gandjustas, Вы писали:
G>кто это придумал вообще? G>Есть какие-то доказательства этом тезису?
Лень доказывать. Можешь вычеркнуть, на результат не влияет. Я надеялся, что так проще объяснить.
G>>>Как связаны реальные акторы и CAP? G>·>Вот там тебе писали пример: "Потому что с утра жахнули при разгрузке два холодоса об асфальт, а списать еще не списали". G>Как это связано с обсуждаемым вопросом?
Чтобы спроектировать правильно — надо учитывать и такие сценарии.
G>·>Цель: правильно спроектировать. G>Если "правильно" это "точная модель реальных акторов", то вы в чем-то правы. G>В реальности "правильно", это "удовлетворяя функциональные и нефункциональные требования с минимальными затратами" G>не видел я доказательств что "точная модель реальных акторов" как-то уменьшает затраты.
Чем точнее модель, тем бОльшее число сценариев она поддерживает в штатном режиме. Это когда тебе не требуется вручную апдейтить таблицы на проде, т.к. "жахнули два холодоса", а всё работает само.
G>>>·>Хреново 1С работает. Не знаю как оно изменилось с тех пор, но раньше это был просто ад — все ломятся через RDP на один гигасервер и простейшие операции работают минуты. И если что-то где-то упало, то всё и сразу лежит. G>>>Показывает уровень понимания 1С... G>·>Наверное. Но никогда не слышал, что 1С отличалась скоростью работы и стабильностью. Десяток пользователей, как правило, уложат любой крутой 1С сервак. G>1С сервак может и уложат, а вот базе будет пофиг. А мне пофиг на базу. Юзерам важнее работу работать, а не о самочувствии базы беспокоиться.
G>·>Ну честно говоря в ретейле я давно не работал. А для трейдинга это какие-то смешные показатели перформанса. G>·>Вот недавно как раз завершили decomission старой системы с субд, acid и прочим. Время отклика уменьшилось с 300мс до 3мс. G>Писать в dev/null можно еще быстрее.
А в лежачий сервер можно хоть за 0мс писать!
G>·>Честно говоря, всё читать лень, но вот эту, например: "резерв полностью прошел но оплата не прошла". G>Да мы еще резерв не прошли G>Давай вернемся к нему.
На десятый круг заходим?
G>напиши как сделать резерв заказа, чтобы: G>1) не продать больше чем есть на складе
Уже раз 10 тебе написали несколько разных людей.
G>2) если остатка недостаточно для резерве, то состояние заказа не меняется
Это ещё зачем? Если всё зарезервировано, надо поменять состояние заказа на "зарезервировано". Если что-то не смогли, то действуем по обстоятельствам, например, просто начинаем отмену заказа.
G>3) все это должно переживать внезапные отключения клиента, падения серверов и прочие катаклизмы G>4) так чтобы это было эффективнее монобазы (в любом смысле)
Разделять на мелкие порции и иметь workflow. Писали же тебе уже.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[34]: Помогите правильно спроектировать микросервисное при
Здравствуйте, gandjustas, Вы писали:
G>напиши как сделать резерв заказа, чтобы: G>1) не продать больше чем есть на складе G>2) если остатка недостаточно для резерве, то состояние заказа не меняется G>3) все это должно переживать внезапные отключения клиента, падения серверов и прочие катаклизмы
С такими формулировками системы не проектируют.
Надо перечислить какие именно катаклизмы и как Система должна переживать, прикинуть стоимость и сроки разработки, и уже потом принимать решения.
G>4) так чтобы это было эффективнее монобазы (в любом смысле)
Это бессмысленное и бесполезное занятие.
Переход к МСА имеет смысл только если есть существенные нефункциональные требования, которые в монолите невозможно или трудно реализовать.
Поэтому имеет смысл только сравнение конкретных методов реализации конкретных требований.
Re[34]: Помогите правильно спроектировать микросервисное при
·>Кстати, вовсе необязательно делать все строки заказа в одной БД-транзакции. Их можно делать поштучно или разбивать на батчи, шарды и т.п. с целью чтобы транзакции были меньшего размера. Это позволит сильнее параллелить и меньше крутиться на локах.
Как бы так ответить на простой тезис в сложном контексте...
Нулевое приближение: всё зависит от бизнес-задачи. Если партия сказала "есть контакт", то народ будет есть контакт. А если бизнес сказал "нам нужна атомарность", то разработчики будут есть атомарность. И вот как мы её обеспечиваем. "Я же не советую вам, сколько табов нужно ставить перед фигурной скобкой. Так и вы не учите меня торговать неликвидом".
И в обратную сторону: разработке похрену, сколько там покупателей отваливаются по таймауту в час пик, потому как "мы сделали всё, как в техзадании. Последствия — на вас".
В рамках этого подхода мы не имеем права произвольно менять постановку задачи. "Мы сделали всё, как вы сказали, только не миллион, а сто рублей, и не выиграл, а проиграл, и не атомарно, а частично, и не зарезервировал, а оплатил" и так далее. Надо уметь делать то, что требуется, а не то, что удобно.
Недостатки подхода понятны.
Поэтому Первое приближение: общий успех достигается тогда, когда бизнес и разработка не пытаются прогнуть друг друга терминами "а это не мои проблемы", а совместно вырабатывают более хороший подход.
Например, частичное резервирование позволяет не послать покупателя нахрен потому, что какая-то не особо нужная ему фитюлина закончилась на складе, а пока он разбирался с тем, что именно и как надо выкинуть из корзины для завершения заказа, уже разобрали и то, что он точно хотел взять. И заодно это уменьшение гранулярности транзакций снижает lock contention и увеличивает общий throughput на том же железе.
Недостаток подхода — нужно тратить много усилий на торг и согласование требований.
Поэтому, Второе приближение: лучше всего, когда понимание нужд бизнеса и особенностей архитектуры сосредоточено в одной голове. Это сильно ускоряет переход к продуктивным решениям
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[35]: Помогите правильно спроектировать микросервисное при
Здравствуйте, Sinclair, Вы писали:
S>·>Кстати, вовсе необязательно делать все строки заказа в одной БД-транзакции. Их можно делать поштучно или разбивать на батчи, шарды и т.п. с целью чтобы транзакции были меньшего размера. Это позволит сильнее параллелить и меньше крутиться на локах. S>Как бы так ответить на простой тезис в сложном контексте... S>Нулевое приближение: всё зависит от бизнес-задачи. Если партия сказала "есть контакт", то народ будет есть контакт. А если бизнес сказал "нам нужна атомарность", то разработчики будут есть атомарность. И вот как мы её обеспечиваем. "Я же не советую вам, сколько табов нужно ставить перед фигурной скобкой. Так и вы не учите меня торговать неликвидом". S>И в обратную сторону: разработке похрену, сколько там покупателей отваливаются по таймауту в час пик, потому как "мы сделали всё, как в техзадании. Последствия — на вас". S>В рамках этого подхода мы не имеем права произвольно менять постановку задачи. "Мы сделали всё, как вы сказали, только не миллион, а сто рублей, и не выиграл, а проиграл, и не атомарно, а частично, и не зарезервировал, а оплатил" и так далее. Надо уметь делать то, что требуется, а не то, что удобно.
Я не предлагаю менять постановку задачи, а менять реализацию. Если нам нужен AoN режим (all-or-nothing) мы просто реализуем откат зарезервированных позиций при отмене зарезервированного (частично или нет, неважно) заказа.
Суть в том, что размер транзакции разумно ограничен, а не зависит от размера заказа.
Я согласен, что это требует бОльших усилий. Но если изначально закладываться на МСА-подход и понятие workflow уже есть, это практически бесплатно.
А в случае если у нас был изначально монолит, то дело плохо, конечно. Распилить код, рассчитывающий на acid-транзакции ничем неограниченной сложности — очень трудозатратно.
S>Первое приближение: общий успех достигается тогда, когда бизнес и разработка не пытаются прогнуть друг друга терминами "а это не мои проблемы", а совместно вырабатывают более хороший подход. S>Например, частичное резервирование позволяет не послать покупателя нахрен потому, что какая-то не особо нужная ему фитюлина закончилась на складе, а пока он разбирался с тем, что именно и как надо выкинуть из корзины для завершения заказа, уже разобрали и то, что он точно хотел взять. И заодно это уменьшение гранулярности транзакций снижает lock contention и увеличивает общий throughput на том же железе. S>Недостаток подхода — нужно тратить много усилий на торг и согласование требований.
Это уже шаг второй — как именно workflow будет реагировать на событие "item resevation failed" — инициировать отмену AoN или переходить в Partial Fill Negotiation.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ·, Вы писали:
·>Я не предлагаю менять постановку задачи, а менять реализацию. Если нам нужен AoN режим (all-or-nothing) мы просто реализуем откат зарезервированных позиций при отмене зарезервированного (частично или нет, неважно) заказа. ·>Суть в том, что размер транзакции разумно ограничен, а не зависит от размера заказа.
К сожалению, у этого подхода есть семантические последствия.
Например, если два пользователя заказали товары А и Б, причём первый успел зарезервировать последний А, а второй успел зарезервировать последний Б, то в ACID один из них получит отказ, а другой заберёт всё.
А в вашем подходе оба заказа будут откачены, и мы получим двух недовольных кастомеров плюс непроданный товар на складе.
·>Я согласен, что это требует бОльших усилий. Но если изначально закладываться на МСА-подход и понятие workflow уже есть, это практически бесплатно. ·>А в случае если у нас был изначально монолит, то дело плохо, конечно. Распилить код, рассчитывающий на acid-транзакции ничем неограниченной сложности — очень трудозатратно.
·>Это уже шаг второй — как именно workflow будет реагировать на событие "item resevation failed" — инициировать отмену AoN или переходить в Partial Fill Negotiation.
Ну с моей точки зрения делить транзакцию на ещё более мелкие гранулы, чем по границам (микро)сервисов — уже оверкилл, если только это не обосновывается бизнес-необходимостью.
Кстати, современные маркетплейсы типа Озона, емнип, при оформлении заказа запросто делят его на части типа "это уже зарезервировали, а вот это внезапно кончилось — мы переложили его обратно в корзину. Сообщить вам, когда оно появится в продаже"?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[37]: Помогите правильно спроектировать микросервисное при
Здравствуйте, Sinclair, Вы писали:
S>·>Я не предлагаю менять постановку задачи, а менять реализацию. Если нам нужен AoN режим (all-or-nothing) мы просто реализуем откат зарезервированных позиций при отмене зарезервированного (частично или нет, неважно) заказа. S>·>Суть в том, что размер транзакции разумно ограничен, а не зависит от размера заказа. S>К сожалению, у этого подхода есть семантические последствия. S>Например, если два пользователя заказали товары А и Б, причём первый успел зарезервировать последний А, а второй успел зарезервировать последний Б, то в ACID один из них получит отказ, а другой заберёт всё. S>А в вашем подходе оба заказа будут откачены, и мы получим двух недовольных кастомеров плюс непроданный товар на складе.
Так обычная сортировка по идентификатору товара — типичный приём обхода взаимоблокировок. Это, кстати, must have и при формировании твоей мегатранзакции.
Ну или retry логика.
S>·>Я согласен, что это требует бОльших усилий. Но если изначально закладываться на МСА-подход и понятие workflow уже есть, это практически бесплатно. S>·>А в случае если у нас был изначально монолит, то дело плохо, конечно. Распилить код, рассчитывающий на acid-транзакции ничем неограниченной сложности — очень трудозатратно. S>·>Это уже шаг второй — как именно workflow будет реагировать на событие "item resevation failed" — инициировать отмену AoN или переходить в Partial Fill Negotiation. S>Ну с моей точки зрения делить транзакцию на ещё более мелкие гранулы, чем по границам (микро)сервисов — уже оверкилл, если только это не обосновывается бизнес-необходимостью.
Я, наверное, испорчен hft и прочим. Как-то само собой разумеющееся — атомарная транзакция должна быть минимальной.
S>Кстати, современные маркетплейсы типа Озона, емнип, при оформлении заказа запросто делят его на части типа "это уже зарезервировали, а вот это внезапно кончилось — мы переложили его обратно в корзину. Сообщить вам, когда оно появится в продаже"?
Угу. Оно. Partial Negotiation. Как такое уложить в мегатразнакцию
begin transaction;
update stock
update stock
commit transaction;
мне неясно.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
S>>Кстати, современные маркетплейсы типа Озона, емнип, при оформлении заказа запросто делят его на части типа "это уже зарезервировали, а вот это внезапно кончилось — мы переложили его обратно в корзину. Сообщить вам, когда оно появится в продаже"? ·>Угу. Оно. Partial Negotiation. Как такое уложить в мегатразнакцию ·>begin transaction; ·>update stock ·>update stock ·>commit transaction; ·>мне неясно.
Там ничего неясного нет — просто добавляется ещё один предикат во where, а заказ распадается на reserved и residual.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[39]: Помогите правильно спроектировать микросервисное при
Здравствуйте, Sinclair, Вы писали:
S>·>мне неясно. S>Там ничего неясного нет — просто добавляется ещё один предикат во where, а заказ распадается на reserved и residual.
Т.е. в одной транзакции будут roundtrips между субд и приложением для каждого товара?
Мне кажется, что
begin transaction;
update stock ...;
insert into reservationItems(orderId, productId, quantity) values(42, 17, 10);
commit transaction;//constraint checked
begin transaction;
update stock ...;
insert into reservationItems(orderId, productId, quantity) values(42, 5, 1);
commit transaction;//constraint checked
будет выполняться быстрее, чем
begin transaction;
update stock ... where available>0;
//check UpdateCount?
update stock ... where available>0;
//check UpdateCount?
insert into reservationItems(orderId, productId, quantity) values(42, 17, 10);
insert into reservationItems(orderId, productId, quantity) values(42, 5, 1);
commit transaction
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ·, Вы писали: S>>Там ничего неясного нет — просто добавляется ещё один предикат во where, а заказ распадается на reserved и residual. ·>Т.е. в одной транзакции будут roundtrips между субд и приложением для каждого товара?
Нет, это всё можно записать двумя стейтментами на весь заказ, вообще без раундтрипов.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[35]: Помогите правильно спроектировать микросервисное при
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, gandjustas, Вы писали:
G>>Даже как-то странно это читать. G>>Есть tcp keepalives (вряд ли применимо в нашем сценарии), есть HTTP2 Ping, есть просто таймаут браузера примерно 60-90 сек если не получен ответ. S>А можете привести пример кода REST-сервиса, который использует что-то из перечисленного для проверки "наличия клиента"?
Любой сервис asp.net, использующий cancellation token
G>>Тем не менее рекомендуемый способ в asp.net — использовать CancellationToken в запросе. S>Возможно, мы с вами по-разному читаем эти рекомендации. Можете набросать схему использования CancellationToken в запросе резервирования товаров?
Тут все есть https://github.com/gandjustas/habr-post-stock-api
Везде в методы сохранения передается CancellationToken, не мешает сделать acid в одной базе, даже если клиенты отваливаются.
G>>То есть в П7 на сервере А мы сохраняем полную копию заказа, как на сервере Б. В одной атомарной транзакции. S>Процитирую то, что я написал три поста назад: S>
S>Да, объекты, пересекающие границы сервисов, в МСА должны храниться на обеих сторонах. Это не обязательно одни и те же объекты, но у них должна быть общая проекция. В данном случае сторону склада не интересуют никакие подробности про способы доставки товара, розничные цены, или там демографию покупателя, но вот список артикулов и количеств, снабжённый уникальным ID, ей необходим. Ровно для того, чтобы когда к нему в следующий раз стукнутся с просьбой зарезервировать корзинку №42342342 он мог не делать повторный резерв, а сразу отдать 200 ok.
S>Проекция в данном случае — это как раз те items, которые мы передаём на удалённую сторону. В сервисе Б там может быть гораздо больше всяких данных — про доставку, про способ оплаты, про подарочную упаковку, и так далее.
Все равно по итогу нам надо в одной транзакции писать оба объекта "заказ" и "резерв" в одной базе. Все остальное уже надстройка.
S>Ничего этого складскому сервису не надо, поэтому речь идёт не о "полной копии". Заодно это изолирует наш складской сервис от изменений в сервисе заказов — например, добавление опции "упаковать как подарок" изменит схему БД сервиса Б, никак не трогая сервис А. Что позволяет нам, к примеру, накатывать изменение на сервис Б, не приостанавливая операции в сервисе А (скажем, отгрузки уже оплаченных заказов).
Кто же мешает в в одной базе сделать несколько таблиц для "оплаты" и "доставки", ссылающихся на "заказ"? Тогда суммарный объем записываемых данных все равно уменьшится, а суммарный объем кода сократится в разы.
Точно также обновление "оплаты" и "доставки" не потребуют никаких блокировок на "заказ".
G>>На этом можно заканчивать. без МСА было бы достаточно одного действия в П7. Insert вполне можно заменить на update без потери остальных свойств. S>Конечно. Если всё лежит в одной базе, можно обойтись без хранения "лишних" проекций.
Мы уже несколько раз вернулись к ситуации, то без МСА мы можем получить такое же поведение, только дешевле.
Я повторю тезис: МСА не решает никаких технических проблем, которые нельзя решить другим способом дешевле. Пока ни у кого не нашлось обратного примера.
G>>Надо понимать что далеко не все мы делаем Озон. По сути кроме озона никто не делает Озон S>Ну почему же. Кроме озона, Озон делает вайлдберриз, яндекс, сбер, т-системы, и ещё с десяток игроков поменьше.
"десяток" это перебор.
Ozon и WB это почти уникальные случаи: у них относительно небольшой фронт, очень тяжелый бек, сервисы связаны друг с другом (там именно такой каскад как в примере), высокие требования консистнетности, при этом могут быть громадные нагрузки в периоды праздников и распродаж. И у них тысячи разработчиков, которых надо чем-то занять.
У банков сервисы гораздо менее связаны друг с другом. Пока процессинг работает все остальное может отвалиться, начиная от вкладов\кредитов, партнерскими скидочными сервисами.
на каждый отдельный сервис не такая большая нагрузка, многие сервисы не требуют перманентной согласованности.
А процессинг платежей как раз без каким либо МСА работает примерно у всех банков.
S>В остальном — повторюсь: да, я согласен. YAGNI в полный рост — при нормальной архитектуре монолита хватает очень надолго. А к моменту, когда он перестаёт справляться, уже есть более-менее реальная статистика использования, благодаря которой можно пилить систему на сервисы осознанным образом. А не так, что "нам надо трудоустроить 39 начальников отделов — давайте напилим 39 микросервисов и дадим всем сестрам по серьгам".
Re[41]: Помогите правильно спроектировать микросервисное при
Здравствуйте, Sinclair, Вы писали:
S>>>Там ничего неясного нет — просто добавляется ещё один предикат во where, а заказ распадается на reserved и residual. S>·>Т.е. в одной транзакции будут roundtrips между субд и приложением для каждого товара? S>Нет, это всё можно записать двумя стейтментами на весь заказ, вообще без раундтрипов.
Интересно, как это выглядит?
И что если кто-то закинет заказ на тысячу позиций?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[33]: Помогите правильно спроектировать микросервисное при
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, gandjustas, Вы писали:
G>>По сути для pg есть готовый модуль автопартицирования. Ему даешь в ход таблицу и ключи и он автоматм управляет всеми партициями. Правда входит этот модуль в PostgresPro Enterprise, но если вы дожили до необходимости партицирования, то денег на него хватит. Там еще будет и BiHa прилагаться, и мультмастер кластеры и много чего еще хорошего. И только когда ресурсы в одного мастера уже не будут закрывать все потребности, тогда можно и пробовать шардировать базу. S>У меня личного опыта администрирования продакшн постгреса нет, поэтому не могу с вами поддержать беседу на должном уровне. S>Но ПостгресПро работают географически близко от меня, поэтому есть возможность смотреть "через плечо" на их ресёрч. S>Так вот, судя по ресёрчу, все эти BiHa и прочие адвансед вещи (начиная от репликации) там, скажем так, далеки от идеала.
Они, к сожалению, все далеки, но все равно это работает лучше чем любой самопал на МСА.
S>Рекламные проспекты стараются тактично умалчивать о всяких интересных особенностях, которые приходится активно пилить. Возможно, если бы у меня был доступ к R&D MS SQL, то у меня было бы меньше иллюзий про откатанность аналогичных сценариев у них.
У меня доступа к R&D не было, но был и есть опыт пром эксплуатации отказоустойчивых кластеров на MS SQL, то же самое все.
То есть при внезапном отказе мастера мастер может просто не переехать на реплику по тысяче причини. Но внезапный отказ это редкое явление. 99% остановок мастера — запланированные, тут обычно переезд мастера происходит ровно даже в бесплатных решениях. Только 1% — проблемы в ДЦ, тут результат может быть любым.
S>В целом у меня нет ощущения, что подобные решения делаются в реляционках по щелчку пальцев.
у меня один инженер с нуля (до этого не знал ничего, в том числе PG) настроил PG + etcd + Patroni кластер за одну ночь с пятницы на понедельник. Кластер этот выдерживал переезд мастера по команде прямо во время нагрузочного теста с нулем потерянных данных.
Это несопоставимо с затратами команды разработки на создание и поддержку МСА.
S>Основная разница, имхо — в том, что MSA заставляет инвестировать в распиливание заранее, а не в том, что она какие-то усилия экономит или какой-то перформанс улучшает в моменте. G>>А что мешает навалить ресурсов на монолит? G>>Я в яндексе могу постгрес поднять с 4 ядер до 96 в 4 клика. И также пропорционально прирастет память на сервере. До 2 млн активных пользователей выдержит я думаю. S>А IOPS вы тоже в 20 раз в 4 клика ему подымете?
Да Яндекс.Облаке потолок IOPS зависит от размера хранилища в Managed Postgres.
G>>А если дойдет до шардирования, то затраты на репликацию общих таблиц окажутся в разы меньше чем на обеспечение кросс-сервисной коммуникации. S>Лично мне механика кросс-сервисной коммуникации понятна от и до. Что создаёт иллюзию контроля.
Некоторые до сих пор джоинов и индексов в базе избегают, так как не понимают их.
S>А репликация в том же постгре для меня выглядит так: "Иногда, если слейв слишком сильно отстал от мастера, то ему не удаётся нащупать нужный LSN при репликации". Или "в некоторых сценариях TSN на мастере и слейве может разьехаться так, что у них нет общей предыстории". Или там "в процессе восстановления после сбоя постгрес не принимает никаких соединений; в некоторых сценариях он может подолгу ничего не писать в лог. Поэтому проблема надёжного детектирования сбоя рекавери является актуальной". S>Это я по памяти пересказываю темы ВКР стажирующихся в постгресе студентов. На защитах про это слушать прикольно; но когда я думаю про возможность нарваться на такое в проде, у меня шевелятся остатки волос на голове.
Как-то же managed postgres в ЯО работает? Да и OpenAI умудряются до 800млн пользователей обслуживать на одном кластере.
G>>Ровно та часть, которой это требуется. S>Ну, лично в вас я уверен. К сожалению, как только мы переходим с разработчицкой стороны на менеджерскую, то выясняется, что даже те немногие бэкендеры, которые вообще владеют SQL, в большинстве не понимают смысла уровней изоляции. Ещё меньше таких, кто умеет их корректно применять
Я их учу, постоянно.
По сути последние 9 лет на всех проектах только и занимаюсь тем, чтобы сделать нормальную работу с БД: запросы, фильтры, проекции, индексы, транзакции, уровни изоляции. Постоянно приходится обучать людей этому.
И каждый раз (не утрирую) оказывается, что если с базой работа построена нормально (как предполагается разработчиками БД), то и сложная архитектура для обеспечения надежности и быстродействия не нужна, даже кэши иногда выкидываем за ненадобностью.
Причем все это не зависит от языка: был и дотнет, и typescript, и python, и 1С.
G>>Мне к сожалению сейчас проект достался с МСА и кучей багов неконсистентности. За последние 3 месяца была пара сценариев, которые я непосредственно ревьювил, где нужен был уровень serializable, в остальных справлялись read committed. S>Ок, согласен. Сравнивая "компетентные разработчики в МСА" с "некомпететнными разработчиками в монолите" выиграет МСА. Но "некомпетентные разработчики в МСА" напорют, наверное, больше, чем "компетентные разработчики в монолите"
При этом МСА имеет больше сложности, особенно при взаимодействии между сервисами.
S>>>Это интересно. Я так не умею. Есть какой-то авторитетный источник, который описывает механизм этого чуда для невежд вроде меня? G>>https://kubernetes.io/docs/tutorials/kubernetes-basics/update/update-intro/ S>Не-не-не. Меня не команды Кубера интересуют. Как вы сделаете роллинг апдейт так, что у вас половина подов в версии 3, половина в версии 2, и все при этом работают, при том что схема базы у нас где-то между версиями 2 и 3?
Варианта два:
1) при накате первого же пода обновляется база тупо миграциями. Все остальные поды после этого быстро перезапускаются и работают уже на новой схеме.
2) если нужна миграция долгая, то запускается команда миграции, а потом kubectl apply. Как завершится первая, так пойдет вторая. Может часы занимать, нам без разницы, это unattended процесс.
rolling update не обновляет более одного пода за раз
S>>>Потому что мне непонятно, как это у нас делаются роллинг апдейты, задействующие схему базы, с учётом того, что она у нас в единственном экземпляре. G>>Достаточно придерживаться простых правил: G>>1) В схему только добавляем таблицы и колонки (кроме access exclusive на таблицу ничего не надо). G>>2) Удаляем таблицы колонки только если если они нигде не используются в проде (на момент создания ветки из мастера нет ни одной ссылки из БЛ). такие апдейты накатываем в периоды низкой активности. S>Не вижу, как бы этого было достаточно.
Эти правила дают нам гарантии, что под версии N заработает с базой версии N+1
Включение новых фич на проде управляется через фич-флаги.
S>Кто-то из нас будет выбран жертвой дедлока.
Я выше описал почему так не получится.
G>>Монопольного режима к одной таблице, а не к базе целиком. Не надо путать. S>Почему к одной-то? Ко всем задействованным, а лучше — ко всем, которые косвенно связаны с изменяемыми таблицами (могут быть изменены в одной транзакции с нашей).
Так не надо писать миграции, которые сразу все таблицы хотят лочить.
G>>Партицирование делается один раз если что. S>Сразу всей базы?
Только тех таблиц, для которых это актуально.
Re[35]: Помогите правильно спроектировать микросервисное при
Здравствуйте, TG, Вы писали:
TG>С такими формулировками системы не проектируют. TG>Надо перечислить какие именно катаклизмы и как Система должна переживать, прикинуть стоимость и сроки разработки, и уже потом принимать решения.
Стандартная софистика — если не знаем как реализовать требования, то надо доказать что требования плохие.
G>>4) так чтобы это было эффективнее монобазы (в любом смысле) TG>Это бессмысленное и бесполезное занятие. TG>Переход к МСА имеет смысл только если есть существенные нефункциональные требования, которые в монолите невозможно или трудно реализовать.
Каких например?
TG>Поэтому имеет смысл только сравнение конкретных методов реализации конкретных требований.
Приведите пример конкретных требований, при которых МСА имеет смысл. Так чтобы это касалось больше 10 компаний в РФ и больше 100 в мире.
Здравствуйте, busk, Вы писали:
B>Привет всем. B>Как-то только в теории читал про микросервисы, но вот новый проект планируется небольшой и хотел как раз попробовать микросервисы тут.
C ci/cd нужно начинать иначе быстро отподет охота этим заниматься. Можно сделать как у меня: репо и пейпланы в на гитлаб в облаке, раннер установлен на рабочем компьютере. Делаю мерж — и у меня на компьютере поднимаются сервисы в докере.