Обновить
40

Пользователь

30
Подписчики
Отправить сообщение

Вообще, реально пейджинг в API нужен крайне-крайне редко и всегда вызван недостаточным анализом предметной области. Человек все равно не может проанализировать более сотни строк, ему нужны инструменты для уточнения поиска, поэтому пейджинг на API для клиента обычно бесполезен. Для межсервисных взаимодействий пейджинг тоже не нужен, так как эффективнее отдать все данные одним потоком (или пересмотреть взаимодействие сервисов так, чтобы не было сверхбольших выборок).
Обычно наличие пейджинга, тем более в указанном в статье виде - признак плохого проектирования и плохой реализации, совсем не про идеальность.

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

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

Хуже сложностью развития и уходом от реальных бизнес-задач. В рамках REST ты не можешь сделать метод "закрыть инцидент", в лучшем случае сделать patch на какое-то поле. И так далее.
Собственно, поэтому RPC проще позволяет реализовывать ООП (который про сокрытие стейта и явный набор имеющих бизнес-смысл сообщений к объекту). В RPC ты можешь добавить специфические create, убрать patch (которые, обычно, не соответствуют реальным бизнес-задачам), разделить close и archive (два разных действия с тем же инцедентом).

Но тут вообще проблема подхода в статье. Хороший API идет от конкретных ФТ и НФТ, от конкретных бизнес-сценариев. А в статье даже user stories не описаны, не говоря уж о выделении реальных методов, о выделении пользовательских сценариях - т.е. про все то, что реально нужно для проектирования API.

Хм, гипермедиа системы - это про очень специфический набор систем, при чем тут инциденты, где есть просто задачи на базовые работы с сущностями? И наличие вложений или изображений не делает систему "гипермедиа", там нет про набор внутренних связей. Даже не всякий документооборот является гипермедиа.
REST проектировался для очень узкого класса систем, к которым да, относится статический web на html, но к которому никак не относится отдельный сервис в распределенной системе.
И да, поэтому в рамках данной статьи выбор REST - явная архитектурная ошибка (впрочем, их в этой статье вообще довольно много). И ошибочный выбор стиля API - не может быть про "идеальное",

Если бы статья называлась "как быстро сделать хоть какой-нибудь API" - не было бы вопросов. Но вот "идеальным" результат назвать никак нельзя.

Причем Филдинг говорил, что REST подходит для гипер-медиа систем, к которым работа с инцидентами никак не относится. И зачем использовать недоREST вместо RPC - не понятно.
При том, что RPC нормально накладывается на OOP (в отличии от REST-style, который с ООП очень плохо соотносится).
Так что в данном сценарии выбор REST-style - является явной ошибкой дизайна и категорически "неидеальным" API.

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

И да и нет.
Асинхронное взаимодействие с состоянием более хрупкое (проще сломать) и сложнее в администрировании. Синхронное в современных условиях, при наличии оркестрации в стиле Temporal - самый простой способ работы в современных распределенных системах.

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

  1. Хм, зависит в любом случае и дело тут не в слоях. В любом случае если сервис A и сервис B как-то взаимодействуют, то они зависят друг от друга. И в асинхронном взаимодействии эта зависимость гораздо больше (так как нет возможности нормально поддерживать версионирование).
    Ну и Event Sourcing не обязательно про асинхронное взаимодействие. И торможение на, например, чтение (которое синхронное) никак и никто не компенсирует.
    Так что это все легенды и мифы, в реальности автономность для раздельных сервисов получить очень сложно и, в реальности, не нужно.

  2. Язык не содержит слова create или update. Но issueCard или там changeName - это как раз вполне себе CRUD операции (create и update). Исключение - команды, меняющие множество агрегатов, но это вообще отдельная тема и в CRUD и в DDD.

    И пара разных create могут быть в одном агрегате, не говоря уж про один BC (в котором может быть много агрегатов). Например создание разных вариантов одной сущности, типа createRectangle и createSquare на агрегате геометрических фигур.

Не, не противоречат. Просто книжки надо читать внимательно.

1. В рамках МСА можно говорить о выделении сервисов по бизнес-функциям. Но далеко не всегда МСА является подходящим стилем для конкретного продукта, более того, часто гораздо удобнее использовать другие распределенные стили (от других вариантов SOA и до каких-нибудь pipes-and-filters). И да, большая часть компаний, говорящих об использовании МСА - использует что-то другое. Кстати, даже у Ньюмана в определении МСА - нет ничего про "around business capabilities". И, да, business capability - не то же, что и business function. Хотя разница там достаточно тонкая, да.

2. Угу. Но в реальности для МСА не получается ни индивидуального деплоя (так как сервисы зависят по API и не могут выкладываться полностью независимо) ни индивидуального масштабирования (так как сервисы зависят друг от друга и один тормозящий сервис авторизации убивает масштабирование всех прочих). Фаулер пишет не про априорное свойство МСА, а про стремление к выполнению этого свойства. В реальности, увы, это свойство крайне редко достижимо.

3. И каким образом из определения Problem space вылезли business functions (которые, вообще говоря, несколько про другое).

4. Я Эванса читал. И да, у тебя методы идут из языка. Поэтому для Create будет пара глаголов (по созданию агрегата), для Update еще с пяток (по разным изменениям агрегата, для Select - тоже несколько. Но это вообще не какое-то свойство DDD, это вообще база ООП. И в любом CRUD у тебя тоже будут разные методы для разных задач, но эти методы будут сводится к одному из 4х типов. Только не надо путать CRUD и дурно-понятный REST.

Эээ, меньше читайте разные кривые ссылки.
Микросервисы никак не лучше в масштабировании, нежели монолиты. Даже наоборот, в МСА больше взаимодействий, так что масштабирование в МСА сложнее, чем горизонтальное масштабирование монолита (тем более модульного монолита). И да, я много раз масштабировал монолит, никаких проблем с этим нет.

Business function - это не DDD, это просто про "бизнес-функции". Да и выделение сервисов по бизнес-функциям - довольно спорная идея, работающая, опять-таки, при отсутствии НФТ. И да, про " developed, deployed, and scaled independently" - это рекламная агитка, в реальности ничего из этого не получается (по вполне очевидным причинам).

Хм, вот чем комады в DDD - не CRUD? Или путаете CRUD с плохо понятым REST? Или CRUD - это когда у объекта ровно 4 метода? Но это все никак не про CRUD. В ссылке на SO - написано что-то очень странное, зачем такое читать?

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

Охх. DDD категорически не про масштабирование (так как работает только если нет существенных нефункциональных требований), впрочем и микросервисы не про масштабирование (по крайней мере - не про масштабирование решения, но может про масштабирование по числу команд разработки). CQRS тоже редко помогает при масштабировании, а уж Event Sourcing скорее мешает. И у Вернона и Ричардсона (остальных, увы, не читал) очень часто написаны довольно спорные утверждения.

Хм, пока не видно никаких поводов уходить от БД. Так что не понятно, с чего бы тут упоминать Мартина.

DDD - да, разработка, ориентированная на домен (перевод как "предметно-ориентированная" довольно сомнителен). CRUD - это как раз описание конкретных операций с элементами домена (агрегатами). CRUD - это просто четыре типа команд DDD (и, кстати, уже разделены command и query). И DDD - как раз про метод реализации CRUD (т.е. как именно реализовывать различные варианты create-read-update-delete). Не понятно, как можно вообще противопоставлять CRUD и DDD.

Ну, я бы не назвал event sourcing хорошей практикой, это крайне редко когда полезный подход, в очень, очень специфических условиях. CQRS, впрочем, тоже. И к DDD эти паттерны не имеют особого отношения, просто очередная попса. Впрочем, и микросервисы в большинстве случаев будут неудачным решением.
Луковая архитектура тоже никак не помогает уйти от БД, с чего бы это? Там точно так же нужно работать с сущностями и точно так же реляционки с этим справляются проще других подходов (а использование монги - вообще характерный признак проблем с архитектурой проекта).
Не понял, что значит фраза "в случае crud DDD избыточен"? Это бессмысленное утверждение, весь тактический DDD - про реализацию CRUD.

Ну, сам Вернон к DDD относится, ээ, не очень, лучше уж Эванса читать.
Но вообще DDD ни в коем случае не про "против СУБД" или "против join". DDD - просто по подход к работе с предметной областью (иерархия доменов, использование словаря для выделения контестов, описание методов взаимодействия доменов) и некоторая терминология для реализации (агрегаты, value object, доменные события).
Никаких реальных технических паттернов ни в стратегии, ни в тактике нет (хотя в книжке и используется слово паттерн - это совсем не в смысле Банды Четырех или там Фаулера), есть только некоторый набор именованных концепций.
Ну и nosql, конечно, никак не связан с DDD (да и вообще слово без содержания). Ну и CRUD никак не противоречит DDD, собственно для круд-проектов DDD и применим лучше всего (для более сложных систем в DDD возникают проблемы).
Ну и надо еще помнить про DDD Trilema (т.е. DDD применим только для продуктов без существенных НФТ).

Увы, но то, что вы описали как DDD - никак в Domain Driven Development не соотносится, это какие-то странные фантазии на тему скорее Вернона, нежели Эванса.

А зачем давать "свой код"? Можно делать regexp по stacktrace или вообще по логгеру (методу), обычно для кластеризации ошибок этого хватает.
И даже если сообщение поменяется - то это значит, что события до деплоя и после деплоя попадут в два разных issue - но это, кажется, не так часто и не так страшно.

Хм, все равно не понятно, откуда появилось 5000 IOPS даже для неравномерной нагрузки со средним в 30rps? При этом 5000 - странное число, для HDD слишком много, для SSD слишком мало.

Ну и вставки даже в 100 записей не сильно увеличивают требования по памяти (совсем не увеличивают), а производительность улучшают многократно. Я уж не говорю про bulk insert, который работает много эффективнее простого insert.

Т.е. интересно, во что точно вы упирались - но это не память и не IOPSы, а что-то совсем другое. И вряд ли тут проблема в MS SQL.

1) Ага, тут проблема не в числе событий, а в их объеме. К сожалению, не знаю специфики, если эти 5-7 мегбайт хорошо пакуются (json/xml/etc), то в том же CH будут храниться довольно экономно, так что можно и на дешевом железе все сохранить. Впрочем, могут быть и другие варианты, когда крупные блобы с ответами вообще живут не в общей системе логирования, а отдельно (я такое встречал). Тогда задача про структурирование всех остальных записей.

2) Насколько помню, в OpenTelemetry предполагается отправлять логи по факту окончания обработки запроса (внутри спана), а это лишает нужной информации в самых противных случаях (падение сервиса или потеря связи). Ну и как хранилище otlp очень, ээ, неторопливый. Описание архитектуры не нашел, но бенчмарки очень разочаровывают, типа 10k rps на ядро, это очень мало (у меня некоторые сервисы больше rps на ядро обрабатывают).

Это вообще проблема современных популярных инструментов логирования (ELK стек и т.п.) - они работают гораздо медленнее, чем современные решения на java/go/c#. Потому и возникает желание "писать только info, делать сэмплинг" и прочие попытки маскировать проблемы инструментов "лучшими практиками".
Но в тот же Clikhouse я легко получал что-то около 100k string-per-second на ядро на шпиндельных дисках, на vector.io тоже около десятка тысяч rps на полядра в режиме сайдкара.

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

Не совсем понял арифметику. 200rps * 20 строк - это всего 4000 строк в секунду, до 50k строк нужно писать 2500 строк на запрос. Впрочем, если взять Clickhouse вместо ELK-стека, то это достаточно нормальные объемы, ничего страшного.

Sentry - это инструмент, в первую очередь, для аналитики по exception - для объединения одинаковых проблем в одну задачу, для генерации задач в трекере и так далее.
Но все тоже можно сделать более-менее простыми запросами поверх того же Clickhouse или VictoriaLogs - и зачем тогда Sentry?

А зачем для записи лога транзакций там много IOPS? Можно же (и нужно) просто лить пачками. Ну а миллионы в сутки - это вообще 30 в секунду, откуда там появилось 5000 IOPS?
Да, память для MS SQL имеет значение, но в 2015м 4GB оперативки - вполне норм.

Информация

В рейтинге
4 614-й
Работает в
Зарегистрирован
Активность