Как стать автором
Поиск
Написать публикацию
Обновить

Комментарии 46

НЛО прилетело и опубликовало эту надпись здесь
В монолитах свои проблемы с API. Текущие абстракции (leaky abstractions). Спинлоки, торчащие из интерфейсов, для производительности. Переменные с разделяемым доступом. Неструктурированные, но такие уютные и привычно-домашние интерфейсы, в которых любой посторонний ногу сломит.
Я нежно люблю монолиты за их скорость, но программный интерфейс между подсистемами внутри монолита нельзя называть сильной стороной этого паттерна
НЛО прилетело и опубликовало эту надпись здесь

Не думали, что придется делать для третьих лиц апишки)

Интересно, не придумал ли кто-то способа энфорсить слабо связанную архитектуру, не заставляя маршалить данные и взаимодействовать по сети?

Мне кажется, или это называется «подключить библиотеку пакетным менеджером»?
Понятное дело, что очень ограниченно работает для компонент на разных языках программирования, но там без сериализации данных в любом случае не обойтись.

Если ты на одном вычислительном узле и сервисы на одном и том же языке, можно и без сериализации.

Я так понимаю, что в микросервисах огранисения типа агрегатов DDD — нельзя например передавать ссылки, на что-то внутренне а только value object. Пакеты это никак не ограничивают.

Придумали. Через ipc.

Интересно, не придумал ли кто-то способа энфорсить слабо связанную архитектуру, не заставляя маршалить данные и взаимодействовать по сети?

Бить монолит на модули и следить за границами.

нельзя например передавать ссылки, на что-то внутренне а только value object. Пакеты это никак не ограничивают.

Код ревью. Микросервисы слабо связанную архитектуру то не обеспечивают. Это просто более явные границы которые люди всё равно нарушают/проводят неправильно. Чем больше мода на них и проще их становится пилить, тем больше людей появляется у которых всё это дело деплоится как единый связанный монолит.
и следить за границами

следить за соблюдением каких правил?


Код ревью.

А что-то автоматическое?

ИМХО проблемы с RESTAPI: его документирования, консистентности и совместимости это другая плоскость и RESTAPI в микросервисы/монолитах имеют одини и теже проблемы.
Разве что в микросервисной архитектуре добавляется необзодимость собирать документацию из нескольких проектов которые могут быть разработаны на разных языках программирования.

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

Думаю, под «нерешаемой» проблемой скалирования/масштабирования вы имели ввиду «ограниченно решаемую»? Ведь наплодить потоков со своими дубликатами данных в рамках одного адресного пространства — дело несложное, но возникает ограничение размерами физической ноды.
Микросервисы – это «кирпичики», из которых разработчики создают современные приложения.

Как потом деплоится такое приложение?

А то вкупе с многочисленными упоминаниями «общения микросервисов», причём по http, возникает мысль что речь идёт про распределённый монолит взаимодействующий по сети, а не независимые микросервисы.
7 бед — один кубернет. И с ним уже 8 бед.
Но обычно история про deploy отделена от истории про API.
7 бед — один кубернет. И с ним уже 8 бед.

Намекаете на то что мысль выше — верна? Ок, спасибо.

Но обычно история про deploy отделена от истории про API.

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

И утверждения, процитированное в предыдущем комментарии, и:
Де факто есть два способа взаимодействия микросервисов – HTTP Rest и gRPC от компании Google

Показались сомнительными, и как мне показалось, говорят о зависимых друг от друга сервисов(это норма, вопрос лишь в количестве зависимостей).
>>7 бед — один кубернет. И с ним уже 8 бед.
Намекаете на то что мысль выше — верна? Ок, спасибо.

kubernetes как ответ на вопрос «как потом деплоится такое приложение?». под «распределённый монолит взаимодействующий по сети» Вы имеете в виду сильную связность сервисов?

я бы сказал что история про deploy перекликается с историей про обратную совместимость

Безусловно, чтобы обновить API нужно раздеплоить новую версию компонента. Но, Евгений, кажется, я не улавливаю Выше мысль. Развернете?
Вы имеете в виду сильную связность сервисов?

Да. Интересно было бы узнать, независимый ли у микросервисов цикл релизов друг от друга, и сколько сил/времени занимает координация релизов, она ведь всё-равно нужна иногда.

Безусловно, чтобы обновить API нужно раздеплоить новую версию компонента. Но, Евгений, кажется, я не улавливаю Выше мысль. Развернете?

Всё так, наверное не очень корректно было спрашивать именно про деплой в первом коммментарии.
Если происходит поломка обратной совместимости API сервиса, которое используется другими сервисами, нужно править их, а это коммуникации между командами и ожидание обновления от них(=время, деньги, медленнее деливери).

Вы ранее назвали HTTP/gRpc стандартом общения микросервисов, а это значит что общение происходит синхронно(request/response), хотя для поддержания низкой связности всякие event-driven подходы считаются предпочтительнее.

Есть два варианта, как быть с обратной совместимостью апи:


  1. Поддерживать разные версии АПИ в одном сервисе.
  2. Поддерживать в продакшне разные версии самих сервисов, а на апи распределять уровнем выше на входе.

Второй вариант, ИМХО, проще, но может быть чреват проблемами безопасности из-за необновляемости, либо же нужно будет поддерживания несколько версий сразу.


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

оба варианта, как мне кажется, имеют одинаковую сложность. Но в одном случае сложность имплементируется в коде, а во втором — в deployment схеме. Помните знаменитую картинку про микросверисы: сложность в коде vs сложность в связях?

Не понял, а что сложного в deployment во втором варианте?

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

База данных — это частный случай, я вообще его не рассматривал. У нас большинство сервисов stateless.

Интересно было бы узнать, независимый ли у микросервисов цикл релизов друг от друга, и сколько сил/времени занимает координация релизов, она ведь всё-равно нужна иногда.


В Acronis сложная модель deploy-я в том смысле, что кроме облака, которым оперируем мы сами, есть еще on-premise deployment, когда наше облако разворачивают customer-ы для своих личных нужд. Поэтому модель «поправили (микро)сервис, залили в прод» у нас не применима. Мы выпускаем целостные релизы Acronis Cyber Cloud где фиксированы версии каждого сервиса
Вы ранее назвали HTTP/gRpc стандартом общения микросервисов, а это значит что общение происходит синхронно(request/response), хотя для поддержания низкой связности всякие event-driven подходы считаются предпочтительнее.


В архитектуре, чисто философски, все компромисс. Иногда ведь и Вы, как архитектор, наверняка отказываетесь от более мощных решений (дающих лучшее масштабирование или производительность) в пользу более понятных решений (дающих более быстрый кодинг, ниже стоимость сопровождения). Cинхронное общение с одной стороны более понятное (простое с точки зрения отладки), с другой стороны более быстрое (все-таки проход через очередь дает много накладных расходов, хотя и добавляет гарантий). Поэтому, как мне кажется, в целом http/gRPC более широко используются чем общение через очереди. Ну и на http можно асинхронное имплементировать (202 и в путь).
Но я согласна с Вами, что event-driven подход имеет свои преимущества
Cинхронное общение с одной стороны более понятное (простое с точки зрения отладки), с другой стороны более быстрое (все-таки проход через очередь дает много накладных расходов, хотя и добавляет гарантий). Поэтому, как мне кажется, в целом http/gRPC более широко используются чем общение через очереди. Ну и на http можно асинхронное имплементировать (202 и в путь).

Так суть как раз в том чтобы не рассматривать http vs queue как две разных реализации транспорта, а делать меньше запросов за данными, получая и сохраняя информацию заранее у себя через всякие Event Notification и Event-Carried State Transfer.

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

Маркетинговая политика облачных провайдеров, которая сейчас "прикармливает" клиентов и спикеров на использование кубернетиса а посему на использование микросервисов к сожалению оставляет в тени другие заслуживающие внимания решения например j2ee, wamp. Однако стандарты как показывает опыт побеждают в долгосрочной перспективе.

J2ee, кажется, ограничено Java-ой? А задачи Wamp-а не соответствуют задачам Kubernetes?
В общем, здесь можно идти в долгий философский диспут. Я далеко не фанат kubernetes, но, как Вы правильно сказали, стандарты побеждают в долгосрочной перспективе. А из нескольких альтернативных стандартов выживает не всегда самый лучший с технической точки зрения.

Не возникало ли у Вас в процессе мысли о том что проблем было бы меньше если бы использовалось не RESTAPI а более строгая спецификация? А если RESTAPI, то в ее модификации купно с HATEOAS?

А если RESTAPI, то в ее модификации купно с HATEOAS?

Те сервисы Акронис, которые используют мультимедиа контент, следуют рекомендациям HATEOAS. Если у Вас есть позитивный опыт применения HATEOAS в других паттернах, буду рада услышать

Опыта нет. Я бы вообще не применял RESTAPI если бы мобильные разработчики не были сильно против

Не возникало ли у Вас в процессе мысли о том что проблем было бы меньше если бы использовалось не RESTAPI а более строгая спецификация?

Мысли что-то улучшить рождаются постоянно. Ограничивает обычно время, ресурсы и здравый смысл про лучшее враг хорошего. Но давайте обсудим про более строгие спецификации. Вы имеете в виду GraphQL или что-то другое? И какие плюсы Вы сами в них видите?

GraphQL — да получаем документацию тождественную коду по крайней мере по входным и выходным параметрам и гибкость. Отрицательные моменты — обработка ошибок и проблема SELECT N + 1


Старый добрый SOAP — его правильно редко используют так как сложно. Все дело в том что без VisualStudio генерировать сигнатуры сервисов очень сложно — практически невозможно.


Но не только это. Например WAMP-протокол, JSON-RPC, JSON-API и oData (последние два собственно RESTAPI с попыткой внести систематизацию в формирование запросов)

Как решаете проблему с синхронными операциями, если они у вас есть? Или сервисы ведут кросс общение по REST? Спрашиваю, потому что, в нашем случае пришлось уйти на websocket и jsonrpc.

Не кажется ли вам, что микросервисы через REST api жестко связаны? Почему не использованы очереди вроде Rabbit?

На rabbit можно получить ту же связанность, только ещё и не очевидную.

Есть сценарии, в которых используем очереди. Но это глубоко внутренние сценарии. С моей точки зрения, общение по REST проще в сопровождении и быстрее. Кроме того, простота REST для нас критична как для платформенного решения — представьте семинар по пользованию АПИ, где вы объясняете через POSTMAN collection, и семинар, где вы объясните асинхронную модель и работу с очередями. :) Если что-то для внешних пользователей можно упростить, то это всегда нужно упростить.
Общение с внешними пользователями конечно по REST (или другому общепринятому протоколу). Я думал, что REST предлагается и для внутренних взаимодействий сервисов.
В целом внутри тоже REST. Ибо внутренние разработчики — они тоже разработчики. HTTP проще отлаживать, проще кодить. Синхронное взаимодействие в целом легче понимать. Но, конечно, есть обстоятельства, когда гарантии доставки (от использования очередей) оказываются более значимыми чем удобство использования.
Тестирование аннотации против имплементации. Для этого мы генерируем из аннотации (RAML/swagger) клиента, который бомбит сервис запросами. Если ответы будут соответствовать аннотации, а сам сервис не будет падать, значит все хорошо.


Зависит от требований в проекте, но обычно тестирования позитивных сценариев недостаточно.

Остановимся подробнее на тестировании. Подобная полностью автоматическая генерация запросов – сложная задача.


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

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

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

Тем не менее генерация невалидных данных у нас в плане на ближайшие пару месяцев
Не рассматривали PACT как альтернативу для тестирования АПИ контрактов?
Rust — это хорошая история, но, кажется, тогда всю серверную разработку прийдется переводить с Go на Rust, а это достаточно трудоемко. Вы используете Rust у себя? Можете поделиться опытом?
Зарегистрируйтесь на Хабре, чтобы оставить комментарий