Pull to refresh

Comments 31

TL;DR

В этой статье речь о том что балансировщик нагрузки должен знать сколько ресурсов у сервера и так запускать микросервисы чтобы они меньше общались по сети

То есть ничего нового

И не марайте термин cell-based architecture

Устоявшегося применения термина нет, но есть варианты и получше

Например, умное шардирование БД с зеркалированием

https://habr.com/ru/companies/vk/articles/807685/

Вопрос про производительность и наподумать:

Если содержимое одной клетки существует изолированно и при крэшах и т.п. восстановление идёт целой клетки, то возможно ли ускорить взаимодействие в микросервисах, используя менее изолированные механизмы?

Как предел такой гранулярностив клетки: переход от микросервисов к монолитным "клеткам", в которых вместо сетевого взаимодействия и других (огромных) накладных расходов будут использоваться существенно быстрые механизмы: прямой вызов функций и т.п.

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

В общем: при наличии клеток, нужны ли микросервисы?

Я так и не понял из статьи - чем все-таки это отличается от обычных микросервисов? Микросервисы точно так же изолированы в отдельных процессах/контейнерах, самодостаточны, т.к. не используют никакие общие данные и общаются между собой только через свои API, что касается балансировки - так для этого везде используются API gateway. Что нового-то? Если для них придумали свое название, значит что-то есть, но, что именно - из статьи это вообще непонятно.

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

Т.е. разница в том, что в микросервисах "один сервис -> одна БД", а у клеток "один instance сервиса -> одна БД", так, что ли?

Можно так сказать

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

Вечный миф "модных" архитектур :) Ну как вы это можете решить, если он клетка ЛОГИЧЕСКИ зависит от другой?

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

Что увеличивает накладные расходы

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

Вечный миф "модных" архитектур :) Ну как вы это можете решить, если он клетка ЛОГИЧЕСКИ зависит от другой?

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

Так и я про это

В монолите запилить аналогичную логику без проблем, да и вообще - в любом варианте "компоновки кода"

Большой шкаф монолит громче падает :) Монолит-то как раз если и упадет, то целиком. Хорошо еще если это будет какой-то "случайный" сбой, например со стороны железа - от этого можно еще заранее подстраховаться сделав кластер из монолитов (хотя опять-таки есть вещи, например БД, если реляционная, которые либо вообще не шардируются, либо шардируются с какими-то оговорками, ограничениями и костылями). А если сбой от того что задеплоили какой-то кривой код? Откатывать весь полностью кластер? Тут как-то совершенно правильно кто-то писал, что вопрос "монолит или микросервис" он лежит больше не в технической, а в административной плоскости, т.е. в плоскости организации процессов разработки, тестирования, развертывания и сопровождения.

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

Согласен, для меня главное и чуть ли не единственное преимущество микросервисов - это CI/CD и все, что с этим связано

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

монолит также отлично растягивается горизонтально и в кластера

Да, я об этом упомянул. Но, монолит надо растягивать полностью, а в микро- можно выборочно что-то, что нужно растянуть, а что не нужно - наоборот укоротить. И опять-таки всё еще остаётся проблема "растягивания" БД, если это не NoSql.

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

Есть ядра и память, реальные. Ядра потребляются не задоплоенными сервисами, а реальными вызовами. Т.е. есть к примеру монолит презентует два сервиса, один вызвали один раз, второй - 1000 раз, но реальное маштабирование произошло внутри монолита, в котором было инциировано создание 1001 потока. Каждый из них взял чуток памяти и проца для обоработки. Если вы не уперлись в пул запросов, и хватило ресурсов - все обработается. В случае микросервисов все тоже самое.Что интересно. если ситуация поменяется, и первый вызовую 1000 раз, а второй - один: то монолиту будет по фиг

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

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

--------------------------

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

--------------------------

База - все упирается в транзакционность и распределенность. Если у вас "вторая нода" далеко, то все равно вы делаете выбор между "гарантированными транзакциями" либо "скоростью в обмен на провисание RPO". NoSQL никакого чуда не дает, так как скорость передачи данных по сети для всех одинакова

Насчет масштабирования это да, но микросервисам ведь можно и самих физических ресурсов выделять гранулировано - кому надо побольше, кому не надо - поменьше. Про БД, полноценное шардирование это еще и надежность. Выход из строя одного узла все равно оставляет доступной всю базу целиком. "Обычную" БД на каком RAIDе не размести - все равно, выйдет из строя узел с эти рейдом и вся база недоступна. Монолит, конечно, по любому проще во всех отношениях и надо сто раз подумать перед тем как от него в пользу микро- отказываться. На опыте уже пройденная тема, когда берут люди монолит, распихают его частями по паре дюжин контейнеров, внутрипроцессные вызовы заменят на service bus - "Йоу, смотрите все - у нас теперь все на микросервисах", а на деле все это тот же монолит, только еще и со всеми сложностями микро- связанными с распределенностью.

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

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

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

А гранулированно нарезать физические ресурсы как правило не выйдет, так как их добавлять долго + все равно нужен запас на "пик" либо отказ "ноды" (чтобы остальные подхватили ее нагрузку)

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

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

NoSQL делает все ровно тоже самое, записывая изменения на несколько нод. Никакой магии нет :)

-------------------

В целом любое решение вы растягиваете:

  • ноды исполнения в кластер для обеспечения отказоустойчивости сервиса + балансер для раздачи нагрузки (который в свою очередь либо в кластере, либо часть клиента)

  • места хранения данных на несколько "дисков" с записбю в несколько мест (с балансом между скорострельностью и "непотерей данных")

Плюс доавляется "обсервер" для предотвращения split brain и обеспечения "кворума" (там где он есть)

Понятно не все технологии в реальной жизни работают так, как обещают, но это чисто вопрос технологии и все

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

Лично я беру микросервисы, так как не хочу "писать против ветра" ну и все таки в части CI/CD микросервисы имеют объективные преимущества, которые на монолите недостижимы

И их недостатки - ну мне как архитектору куда интереснее. Монолит в целом скушно и успешно :) А тут поработать надо :)

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

Ну так ведь не бывает к сожалению :(

Бизнес логика все таки связана и эти связи код также должен поддерживать

-----------------

А шардирование - это по сути "вишенка" на торте. Вы его можете применить когда для этого есть возможности и имеет смысл

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

Так это никак не связано с "клеточной архитектурой". В данном случае, весь функционал остается, просто в приложении, которое уже поддерживает multi-tenancy прикручивают еще один "фильтр"

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

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

Ну, не обязательно. К примеру, базовое решение - row level security на уровне базы и все. Недорого и эффективно.

Общие сервисы - ну, тут я не понял ... сервисы они либо есть, либо нет. На крайний случай "провайдеры" могут ввести пакеты и что-то делать доступным, а что-то нет. Но RBAC и прочим концепциям уже 100500 лет в обед. И не важно, это на уровне конкретного end user записи, или целого account, от которого набежало куча "пользователей"

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

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

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

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

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

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

Да и вообще, условно если вы работаете в парадигме code-first - это чисто вопрос деплоймента, так как апликухе настолько "все равно", как там будет, что она даже не в курсе, где и что живет

Хотите - делите. Не хотите - не делите

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

Проблемы начинаются, когда запись очень большая и нужны сотни тысяч или миллионы rps. Тогда подход "провод в стену" и не важно что там за база, начинает порождать уйму проблем. Как раз становится проще поддерживать множество не сильно загруженных клеток, каждая из которых переваривает, например, 10к RPS, что вполне щадящее.

Ну и повторюсь, что этой "моде" уже лет 15, так точно, а может и побольше.

Ну тогда шардинг + редис :) Или по отдельности

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

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

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

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

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

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

Ну тогда первую "клетку" я видел еще лет 20 назад, когда бизнес логика жила в базе на хранимках и разные модули и не только сидели в своих схемах :) Шучу, просто в целом подход не нов, даже для приложений двух-уровневой архитектуры. также логично домены разносить по разным схемам и т.д.

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

Ну так может упасть что угодно. Ну так же нельзя. Кеш упал и все "умерло". А если message broker упал? Ну представьте, вы живете на стеке, который по сути упрощенно набор технологий. И тут одна из них "падает". Ясно что все сломается

Тут если технология имеет "врожденную" недостаточность - тогда да. Но оснований считать, что редис более "падучий", чем условно постгре наверное нет (ну у меня).

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

  • старта на фоне отложенной нагрузки

  • старта после обширного фейла

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

Кеш может пропадать не только и не столько из-за падучести, а скорее из-за каких-либо работ на серверах, не знаю там, переездах между ЦОДами, да банального рестарта или холодно старта сервиса. Система должна всегда быть готова держать нагрузку, иначе, какая-нибудь ошибка с кешем и у вас начнёт падать вся инфраструктура, которая за ним.

Ещё раз повторю, я не против редиса, когда речь о снижении лэтенси идёт, но не стоит на него полагаться, что в хайлоаде он снизит нагрузку, не снизит.

банального рестарта или холодно старта сервиса

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

что в хайлоаде он снизит нагрузку, не снизит.

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

На запись ... я лично никогда не делал, но теоретически проектировал. Но тут уже откровенно стремно. Разве что для event-based архитектур, где "накат" изменений заложен идеологически

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

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

Поэтому запускаем по чуть-чуть, кеш наполниться как раз :)

Тут надо со сценарием определиться. Если запуск после продолжительного даунтайма - то отложенный спрос может оказаться покруче "черной" пятницы, а зачем оно вам?

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

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

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

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

Sign up to leave a comment.