Re: Помогите правильно спроектировать микросервисное приложение
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 20.03.25 15:32
Оценка: +5 :)
Здравствуйте, busk, Вы писали:

B>Как-то только в теории читал про микросервисы, но вот новый проект планируется небольшой и хотел как раз попробовать микросервисы тут.

Не надо, оно тебя сожрет
Re: Помогите правильно спроектировать микросервисное приложение
От: Sinclair Россия https://github.com/evilguest/
Дата: 25.03.25 06:34
Оценка: 32 (3) +2
Здравствуйте, busk, Вы писали:
B>Первое что хотел сказать, что везде пишут микросервисы это где много команд часто или много функционала. В этом проекте ни того ни другого не будет,
B>но зато скоп определен четко и подумал прекрасная возможность потренироваться, чтобы потом уверенее пробовать в большом проекте.
Это — хорошая идея.
B>Тут я понимаю, что проще было бы сделать монолит, но для обучения вполне годный вариант?
Да, проще. Да, годный — невозможно сходу научиться резать монолит на микросервисы так, чтобы не стало хуже, чем было.

B>Второе и собственно основное я так понял из книг, что самое сложное это определить границы сервисов.

Да, совершенно точно.

B>Вот прошу тут помощи как нарезать на сервисы и базы?


B>Приложение: — Система контроля доставок грузов в разных странах (стран 10).

B> — Юзеры заходят по user/pswd и система определяет страну и подгружает данные этой страны. Новый юзер сам может зарегаться по логину выданному ему и восстановить пароль.
B> — В системе будет 4 роли: sysadmin, admin, manager, driver. В каждой стране свои пользователи. Один пользователь = 1 страна.
B> — Сами заказы поступают в эту систему из другой. В этой надо только мониторить и делать разные действия если доставка задержалась или не приехала.
B> — В каждой стране много складов и поэтому когда заказы поступают в систему то они сразу попадают на нужный склад и спец алгоритм распределяет на водителей.

B> — sysadmin управляет только техническими настройками разными (кому когда отчеты отсылать, как в системе заводить оптуска, сколько часов в сутки можно работать, заводит праздники), остальное всё только в режиме просмотра видит.

B> — admin видит всё, не может только технические настройки менять. Следит за водителями, чтобы они всрок доставляли всё — по юаю специальному, вносит отпуска, больничные их, ставит им рабочее время. Если водитель увольняется — удаляет изи системы.
B> — manager следит за водителями своего склада только, может посмотреть по всем своим водителям информацию и по всем доставкам, но менять не может
B> — driver видит только по себе все сделанные доставки и предстоящие. Каждый раз когда он начинает и заканчивает доставку то в системе нажимает Start delivery\End delivery. Если доставка не укладывается в
B>предполагаемые сроки то пишет к доставке комментарий почему не успел

Важно, чтобы микросервисы как можно меньше взаимодействовали между собой. Если не получается — значит, границы выбраны неверно.
По вашему описанию не вполне понятно, что собственно должна делать система. Распределять заказы между водителями?
Смотрите:
0. Сервис аутентификации. Его хочется делать крайне надёжной, т.к. если никто не может зайти, то не работает вообще всё. Очень опасно делать монолит, в котором выкат какой-нибудь мелкой фичи типа "а давайте поздравим всех водителей-женщин с 8 марта" способен сломать логин. То есть эту штуку мы как можно реже релизим, и при каждом выкате покрываем тестами в шесть слоёв. Отдельные пацаны аудируют код на предмет потенциальных уязвимостей, т.к. кража базы паролей — почти самое плохое, что с нами вообще может случиться. Сам сервис скорее всего раскатан в нескольких экземплярах с геодистрибуцией и офигенной избыточностью — чтобы отключение света в нижегородском ДЦ не валило всю федеральную сеть водителей.
(Кстати, очень часто мы захотим это вообще делегировать наружу, чтобы не заниматься дорогостоящими инвестициями в эти пять девяток и прочие особенности. Привинчиваем OAuth и полагаемся на Google/Facebook/etc)
1. Сервис авторизации. После того, как пользователь залогинился, нам нужно ещё и получить набор его прав. В большинстве случаев это довольно-таки типовая структура, вроде ролей. Опять же, требования к ней довольно-таки жёсткие, т.к. она нужна в каждом первом сценарии. Ещё можно заметить, что она в значительной мере дублирует информацию из 0-й системы — как минимум, у нас должен быть тот же самый список пользователей. Поэтому в современном мире зачастую 0 и 1 объединяют в одну.
2. Сервис профилей. Всякие личные данные, предпочтения, и прочее. Набор этих данных меняется относительно часто, поэтому несмотря на структурную похожесть с предыдущим сервисом, его имеет смысл держать отдельно. Если даже кто-то очень криво выкатит обнову, которая даёт пользователю вместо фоточки на аватару выкладывать короткий ролик, логины и права продолжат работать.
Опять же, данные этого сервиса подпадают под всякие регуляторные нормы типа GDPR и его аналогов, поэтому имеет смысл их держать в отдельной базе с отдельными полисями бэкапа, контроля доступа, и функций своевременной очистки.
3. Сервис флагов/пользовательских настроек. Иногда его объединяют с предыдущим, но в большой системе лучше разделять. Потому что требования разные — флаги и настройки не являются personal information, зато постоянно нужны другим сервисам для принятия решений типа "а можно ли этого водителя назначить на рейс в Европу".

4. Вы упомянули про отпуска/больничные/рабочее время. Это выглядит как достаточно изолированный кусок, который может развиваться независимо от других. Опять же, он может попадать под какие-нибудь регуляторные требования в юрисдикции эксплуатации — всякие там нормы от минтруда и прочих проверяющих.

Обратите внимание, во всех сервисах, которые пока что были перечислены, есть понятие "пользователя". Типичной ошибкой начинающих проектировщиков является идея "а давайте мы всех пятерых подключим к одной базе данных — в конце-концов, список пользователей-то у нас общий! Зачем его дублировать?".
Вот это — плохая идея: получите все недостатки МСА без её достоинств. Да, список пользователей будет дублироваться. Да, на это придётся потратить немножко усилий. Но на самом деле всё не так уж и плохо — в том смысле, что, к примеру, настоящее имя пользователя и его дата рождения хранится только в одной системе, а какие-нибудь данные о его трудовой биографии — в другой. Дублирования не так уж и много; основное затруднение — невозможность контролировать ссылочную целостность. У вас всегда будет риск получить в четырёх базах "подвисшие" записи для пользователей, логин которых был забанен в 0м сервисе навсегда. Уборка мусора становится отдельной maintenance задачей.

Едем дальше — вот у нас что-то там про доставки. Собственно, тут пояснений недостаточно, придётся фантазировать. Очевидно, нужен какой-то сервис, который показывает водителю его доставки и позволяет с ними взаимодействовать.
Раздача доставок по водителям может быть частью этого сервиса, а может быть отдельной подсистемой. Чтобы опять же нововведения в алгоритме раздачи заявок не могли ничего отломать в учёте статуса доставок — у водителя в пути не всегда есть возможность "подождать до четверга", чтобы отметить статус заявки. Этому сервису будут нужны данные о том, кто когда планируется на смене — из того сервиса, где учитывались больничные/отпуска и т.п. Обратите внимание, что ему не надо никаких подробностей — можно придумать относительно стабильный, узкий API, по которому этот сервис запрашивает доступность того или иного водителя.

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

Вот примерно так это и должно работать.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Помогите правильно спроектировать микросервисное приложение
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 23.03.25 17:14
Оценка: +5
Здравствуйте, busk, Вы писали:

B>Здравствуйте, gandjustas, Вы писали:



G>>2) яндекс на старте не был микросервисным


B>ну вот да, книжку читал и пишут, что большие проекты часто вначале делают монолитом, когда еще не всё ясно и четко по логике и потом типа уже распиливают на микросервисы.

И вообще не факт что это надо делать.


G>>3) cd\cd без микросервисов работает лучше

B>звучит что микросервисы удел либо больших компаний либо крупных систем.

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

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

В этом случае может быть выгодно иметь микросервисы как раз по границам команд. Других адекватных причин использовать MSA я не видел.
Re[12]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 06.04.25 06:09
Оценка: 11 (2) +1
Здравствуйте, Miroff, Вы писали:

M>Можно это как-то обосновать?

Можно. Когда я делаю GET на ресурс, я получаю его представление. Крайне желательно, чтобы это представление зависело от состояния ресурса, а не от состояния пользователя, который его получает.
Например, можно воткнуть reverse proxy перед сервером приложения, и тогда он сможет снять значительную часть нагрузки с сервера.
Как только мы начинаем менять представление объекта в зависимости от пользователя, о кэшировании можно забыть.

M>Мне кажется, мы о разных вещах говорим. Есть ресурс, есть набор связанных ресурсов с которыми можно проделывать какие-то операции.

Тут всё верно. Ресурсы обычно связаны друг с другом не искусственными линками, а естественным образом, спрятанным в представлении.
Возьмём, к примеру, ресурс Payment.
Вот как выглядит представление этого ресурса через PayPal API:
{
  "id": "0VF52814937998046",
  "status": "CREATED",
  "amount": {
    "value": "10.99",
    "currency_code": "USD"
  },
  "invoice_id": "INVOICE-123",
  "seller_protection": {
    "status": "ELIGIBLE",
    "dispute_categories": [
      "ITEM_NOT_RECEIVED",
      "UNAUTHORIZED_TRANSACTION"
    ]
  },
  "payee": {
    "email_address": "merchant@example.com",
    "merchant_id": "7KNGBPH2U58GQ"
  },
  "expiration_time": "2017-10-10T23:23:45Z",
  "create_time": "2017-09-11T23:23:45Z",
  "update_time": "2017-09-11T23:23:45Z",
  "links": [
    {
      "rel": "self",
      "method": "GET",
      "href": "https://api-m.paypal.com/v2/payments/authorizations/0VF52814937998046"
    },
    {
      "rel": "capture",
      "method": "POST",
      "href": "https://api-m.paypal.com/v2/payments/authorizations/0VF52814937998046/capture"
    },
    {
      "rel": "void",
      "method": "POST",
      "href": "https://api-m.paypal.com/v2/payments/authorizations/0VF52814937998046/void"
    },
    {
      "rel": "reauthorize",
      "method": "POST",
      "href": "https://api-m.paypal.com/v2/payments/authorizations/0VF52814937998046/reauthorize"
    }
  ]
}

Этот ресурс, судя по всему, связан с другим ресурсом — invoice. Но никаких намёков на то, как получить информацию об этом ресурсе, внутри ресурса нет. И линков тоже нет. Зато есть линки про то, как изменить состояние этого же ресурса. Так что это никакой не REST.
В настоящем хардкорном RMM3 REST вместо атрибута invoice_id был бы атрибут invoice со значением "https://www.paypal.com/invoice/details/INVOICE-123".

M>HATEOS позволяет НЕ ВЫЗЫВАЯ операций предсказать, будут они доступны клиенту или нет.

Нет, ничего подобного HATEOAS не предполагает. Нет никакой гарантии, что операции будут доступны. Нет никакой гарантии, что никаких других операций нет.

M>Например, в списке сотрудников рядом с именем Sinclair либо показывать кнопку "объявить выговор" или не показывать. И чтобы это реализовать без HATEOAS часть логики авторизации, кому можно налагать взыскания и на кого, вынужденно скопируется из сервиса в его клиента.

Нет конечно. Зачем? Это крайне контрпродуктивная идея.
Во-первых, "объявление выговора" в REST-системе — это не операция с "сотрудником с именем Синклер". Это создание ресурса "выговор". А точнее — создание ресурса "приказ об объявлении выговора".
В котором могут фигурировать, к примеру, несколько сотрудников. И права на создание этого выговора весьма косвенно связаны с перечисленными там сотрудниками.
Во-вторых, построение безопасности путём скрытия действий в UI — это популярная, но плохая идея. В основном — потому, что она неимоверно бесит пользователей. Вот я сижу перед списком пользователей, хочу объявить выговор. Поискал в меню — нет такой команды. Поискал в свойствах сотрудника — нет такой кнопки. Полез в инструкцию — сказано "для объявления выговора нажмите на кнопку "Объявить выговор". И вот я уже полчаса думаю, то ли я дурак, то ли инструкция устарела, то ли программа глючит. Внезапно, "некрасивый" способ — дать мне нажать на кнопку, а потом вывести "403 у вас недостаточно прав для объявления выговора этому сотруднику" — в разы гуманнее по отношению к пользователю, чем предлагаемая вами идея.

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

Ничего никуда не расползается. Зачем? Микросервис просто делает свою работу. Поймите, нельзя строить микросервис на том, что "я прочитал ресурс — если нет ссылки, значит нельзя рефандить и надо идти по ветке А, а если ссылка есть — то надо идти по ветке Б и выполнять рефанд". Возможно, настройки прав или ешё что-то поменялось между чтением ресурса и переходом по ссылке; всегда можно получить в ответ "403". Так что вместо вот этой вот двухшаговой наркомании "если ссылка, то идём по ветке Б, и если получили 403, то переключаемся обратно на ветку А". Просто идём и пытаемся сделать рефанд, не делая никаких предположений о правах там и всём остальном.

M>Как в примере из соседнего поста, когда сервис туров следит чтобы определенные туры были доступны только совершеннолетним пользователям и эта же логика дублируется в сервисе рекомендаций чтобы не показывать несоврешеннолетним то, что им и так недоступно. HATEOAS бы эту проблему решил докинув ресурс user список доступных для него туров. ,


Это очень, очень плохая архитектура. В первую очередь потому, что вы инвертируете зависимости. Теперь у вас ресурс user (и его микросервис) обязан знать всё о турах (которые вообще-то обрабатываются другим микросервисом).
А ресурс "тур", ясное дело, должен знать всё о пользователях. Поздравляю, вы получили не просто монолит, а трудноразвиваемый монолит.

M>Опять же, можешь раскрыть тему? Пейджинг это простая штука если перестать думать о нем, как о RPC и начать думать как об отдельном ресурсе. Ты СОЗДАЕШЬ отдельный объект "поисковый запрос" и в ответ получаешь список страниц с результатами этого запроса. И, внезапно, у тебя уже нет проблем со стабильностью, сортировки, изменению состава страниц, кэшированию и т.п. Результат фиксируется в момент создания запроса и далее до нового поиска уже не меняется.

И это — тоже очень, очень плохая архитектура. Смотрите как это работает: "поисковый запрос" — это эфемерный ресурс. Последнее, что мы хотим — это хранить его. В первую очередь по соображениям масштабирования. Сколько пользователей вы ожидаете ежедневно? Двух? Как только у вас появляется хотя бы несколько сотен тысяч запросов в сутки, хранение (даже в течение ограниченного времени) их эфемерных запросов становится неподъёмным.
Как раз наоборот — пользователь, который получил в ответ на поиск информацию о том, что нашлось 100000 страниц, скорее всего выполнит новый запрос, потому что этот оказался недостаточно точным.
Нет, бывают такие ситуации, когда поиск сам по себе очень дорогой, и мы как отдельную фичу предлагаем "сохранение запросов", да ещё и иногда с оповещениями об изменениях. Но в простых гражданских случаях это не работает, и поиск делается поверх реалтаймовых данных, а не поверх какого-то снапшота, полученного неведомо когда.
И вот в такой обстановке "традиционный" пейджинг в стиле "дай мне позиции с 120 по 139" — тупиковая ветвь проектировщицкой мысли. Единственное его достоинство — простота реализации.
Зато недостатки у него принципиальные — в частности, невозможность восстановить целостную картину.

Есть несколько способов решить эту проблему. Один из них — примерно то, что вы предлагаете, "думать о запросе как об отдельном ресурсе", только правильно реализованный.
Правильно — значит иметь один ресурс "поисковый запрос". Несмотря на его эфемерность, он вполне реален. То есть не два разных ресурса "пользователи на букву А с 0 по 99" и "пользователи на букву А с 100 по 199", а один ресурс "пользователи на букву А". Если этот ресурс слишком велик для прожёвывания его одним запросом, то мы добавляем к запросу range header и тащим комфортными для нас частями.
А непротиворечивость гарантируется тем, что последующие запросы мы дооборудуем хидером if-match/if-none-match, что позволяет нам заметить момент, когда данные на серверной стороне поменялись, и закешированную версию нужно выкинуть.

M>Нет. POST refund это создание ДРУГОГО ресурса. Другого потому что у него другой URI. Нужно думать о рефанде не как об изменении платежа, а как ос создании нового объекта — сторнирующей операции, потому что сам платеж изменять не позволяет принцип двойной бухгалтерии известный с 17 века: сделанная проводка не может быть удалена.

Отлично, давайте зайдём с этого конца. Хотя там, если покопать в API, будет пачка методов по изменению именно того же объекта (https://developer.paypal.com/docs/api/payments/v2/#authorizations_reauthorize).
В нормальном REST избегают POST методов, поскольку в случае потери результата POST крайне сложно понять, чем там кончилось дело, и что делать теперь.
К сожалению, авторы PayPal API книжек по REST-у не читали. Поэтому у них нет ничего идемпотентного.

M>Это требует проделать вызов. В микросервисной архитектуре такой подход означает что сценарий клиента может развалиться в середине выполнения и, как следствие, для каждого сложного сценария потребуется делать распределенные транзакции с откатом. Так, конечно, можно делать, но это очень дорого. Поэтому в большинстве случаев ты сперва делаешь пречек собирая все доступные ресурсы, проверяешь пререквизиты и только потом начинаешь выполнять изменения.

Простите, но вы рассказываете какие-то небылицы. Что такое "пречеки"? Мы пробежались по всем нужным ресурсам, и убедились, что все нужные нам "действия" торчат в виде линков?
Ну так это ничего не значит. Посмотрите в тот же PayPal API — там очень редко бывает так, что достаточно POST с пустым телом. То есть — результат будет зависеть от параметров запроса. А их вы никаким пречеком не проверите (если в API нет специального метода precheck). Поэтому — да, либо rollback (если вдруг у нас есть детерминированный способ сделать rollback), либо rollforward. Чудес не бывает.
Если вы собрались изображать в любой архитектуре, хоть микросервисной, хоть монолитной, композитный сценарий вроде "запросили кредит — перевели деньги на расчётный счёт — расплатились за покупку товара", то он всегда может сфейлиться на каждом этапе. В прошлом веке для этого применяли протокол двухфазного коммита. Сейчас у нас два варианта:
— реализовать двухфазный коммит (каждый из этапов на самом деле делается в виде двух отдельных методов типа "подготовить ресурс" и "использовать ресурс"; при этом подготовленный ресурс после некоторого таймаута саморассасывается.
— понимать, что мы можем застрять посреди процесса — например, с выданным кредитом, но без дефицитной игровой приставки, которую успели купить.
Никакие "пречеки" тут не помогут, если нет реального резервирования ресурсов.

M>Людям вообще нравится RPC, даже по этой теме видно. Но RPC не дает необходимой для микросервисов изоляции и довольно быстро превращает приложение в распределенный монолит.

RPC людям нравится не за то, что у него есть преимущества, а за то, что они не сразу видят его недостатки.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[10]: Помогите правильно спроектировать микросервисное при
От: Miroff Россия  
Дата: 04.04.25 03:24
Оценка: 82 (1) +1
Здравствуйте, Sinclair, Вы писали:

S>Вот с чем никогда в жизни не работал — так это с описываемой вами архитектурой.


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

S>1. Согласованности: чтобы вся эта слабосвязанная мешанина реально делала то, что нужно?


В рамках доменной области у тебя всегда будет eventual consistency, до той степени, какую обеспечивает твоя доменная модель. Реальный мир устроен схожим образом: большинство бизнес процессов могут прерваться на середине и в этом нет ничего страшного.

S>2. Зависимостей — как мне понять, сколько сервисов нужно запустить, чтобы реализовался сценарий X? Чтобы не получилось, как в анекдоте: "один копает ямы, а другой закапывает; ещё один должен был туда деревья вставлять, но он не пришёл".


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

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

S>3. Предотвращения лайв-локов: один сервис ждёт с шины сообщение А, потом отправит сообщение Б. Другой сервис как раз ждёт сообщение Б, чтобы отправить А


Это не RPC, сервис ничего не ждёт. Сервис отправляет запрос на изменение и забывает о нем. Если сервису важно, чтобы запрос отработал в за какой-то тайм-аут, он проверяет изменения спустя какое-то время и если изменений не произошло, шлет команду на отмену.

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

Рассылки это новый домен относительно пользователй и туров, значит нужен новый сервис. Этому сервису необходимы пользователи, туры и поездки, значит подписываемся на изменения в трёх доменах. От пользователей храним е-мейл и возраст, от тура храним описание, от поездки храним сам факт связи пользователя и тура. Все это складываем в контекст и из контекста извлекаем что кому рекомендовать. При рассылке отправляем нотификации: создана рассылка для пользователя X приглашающая в туры {Y}. И такая система получается очень гибкой и расширяемой. Если нам нужно поменять правила рассылки, мы меняем один сервис. Если нужны новые данные, добавляем подписки. Если нужно действие после рассылки, добавляем нового подписчика. И т.п.

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

S>Если есть какая-то книжка на эту тему — отправьте в неё, пожалуйста


Можно начать со знакомства с моделью акторов на практике
https://www.oreilly.com/library/view/reactive-messaging-patterns/9780133846904/
https://www.oreilly.com/library/view/applied-akka-patterns/9781491934876/ch01.html
Либо поискать что-то более фундаментальное.
Отредактировано 08.04.2025 7:53 Miroff . Предыдущая версия .
Re[6]: Помогите правильно спроектировать микросервисное приложение
От: Sinclair Россия https://github.com/evilguest/
Дата: 25.03.25 05:50
Оценка: +2
Здравствуйте, gandjustas, Вы писали:

G>В этом случае может быть выгодно иметь микросервисы как раз по границам команд. Других адекватных причин использовать MSA я не видел.


Ну ещё ограничить failure domain. Чтобы бага в одном углу приложения клала его не целиком, а только блокировала отдельные сценарии.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[8]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 25.03.25 06:07
Оценка: +2
Здравствуйте, Miroff, Вы писали:

M>Здравствуйте, RushDevion, Вы писали:


RD>>RMM L3 — это когда, получив первый ресурс, мы по link/rel определяем, что с ним дальше можно сделать (и на какие url слать соответствующие запросы), так ведь?


M>Да, но не только. Это как с третьей нормальной формой, RMM L3, это RMM L2 + HATEOAS. В первую очередь хорошее API обеспечивается правильным разделением на ресурсы, с которыми можно оперировать с помощью HTTP глаголов. HATEOAS на это просто очень удачно ложится и позволяет не размывать логику между клиентом и сервером.

Я не вижу каких-то прямо практически значимых преимуществ HATEOAS.
1. Discoverability немножко улучшается, но не очень значительно. Вот мы дёрнули какой-то ресурс GET-ом. Он прислал нам
— набор ссылок на объекты внутри своих свойств (типа "owner": "https://our-api-enpdoint/users/23412312-ws-44"}
— набор ссылок на "глаголы" в коллекции links (типа {"href": "https://api-m.paypal.com/v1/payments/sale/36C38912MN9658832/refund","rel": "refund","method": "POST"})
Дальше что? Всё равно, без чтения документации невозможно понять,
— можно ли в качестве owner использовать URL юзер-аккаунта в другом скоупе
— что делает глагол refund, и какие у него будут параметры, и где их брать
2. Evolvability улучшается крайне незначительно. У нас нет никакого способа научить клиентов всегда ходить только по указанным нами ссылкам. Если мы решили перенести endpoint для рефандов в другое место, то недостаточно просто отдавать новую ссылку в links. Примерно 99% разработчиков клиента зашьют логику генерации ссылки в своё приложение, вместо того, чтобы прикапывать URL для каждого платежа в своей системе (и тратить место; и опять же рисковать пойти по устаревшей ссылке) или там бегать всякий раз делать GET и искать этот ./links[@rel=refund] (и увеличивать нагрузку на сеть и латентность своих сервисов). Нам так или иначе придётся до каждого из них дойти и убедиться, что они переписали своё приложение
3. Накладные расходы значительно увеличиваются. Там, где в RMM L2 мы обходились GUID-ом, а то и вообще int-ом, теперь мы тащим длиннюшие урлы с совершенно бесполезными обрамлениями. Можно немножко починить это путём компрессии реквестов и респонсов, но всё равно — растёт allocation size для каждого запроса, учащаются сборки мусора, снижается общая эффективность, повышается расход электроэнергии.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[9]: Помогите правильно спроектировать микросервисное приложение
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 01.04.25 14:04
Оценка: -1 :)
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, gandjustas, Вы писали:


G>>В managed среда это можно и без микросервисов сделать.

S>Не очень понятно, что вы имеете в виду. Поддержку AppDomain выпилили (за ненадобностью) из нового дотнета, а в жаве её никогда и не было.

Ну есть экспериментальные DotNetIsolator [EXPERIMENTAL]

Правда 2 года не изменялась

// Set up an isolated runtime
using var host = new IsolatedRuntimeHost().WithBinDirectoryAssemblyLoader();
using var runtime = new IsolatedRuntime(host);

// Output: I'm running on X64
Console.WriteLine($"I'm running on {RuntimeInformation.OSArchitecture}");

runtime.Invoke(() =>
{
    // Output: I'm running on Wasm
    Console.WriteLine($"I'm running on {RuntimeInformation.OSArchitecture}");
});
и солнце б утром не вставало, когда бы не было меня
Re[9]: Помогите правильно спроектировать микросервисное приложение
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 02.04.25 07:45
Оценка: 80 (1)
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, gandjustas, Вы писали:


G>>В managed среда это можно и без микросервисов сделать.

S>Не очень понятно, что вы имеете в виду. Поддержку AppDomain выпилили (за ненадобностью) из нового дотнета, а в жаве её никогда и не было.
S>Управляемая среда всего лишь гарантирует отсутствие ошибок типизации и "повисших" ссылок. Всё. Никакой изоляции она из коробки не предоставляет.
S>Понятно, что она лучше любого анменеджеда хотя бы тем, что в ней нет undefined behavior (если, опять же, придерживаться гигиены и не пользоваться всякими ансейф и около-ансейф вещами).
Я говорю о том, что вручную выстроенная модульность внутри приложения, на уровне отсутствия ссылок из группы объектов, поддерживается самой managed средой. Без использования ансейфа и разделяемых данных без должной осмотрительности крайне сложно в managed среде во время обработки одного запроса нарушить работу кода, обрабатывающего другие запросы.


S>Но defined behavior недостаточно для ограничения failure domain. Потому что если есть разделяемое состояние, то невозможно гарантировать его целостность при наступлении неожиданных результатов.

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

Очень хороший кейс.

А давай прикинем как это будет в MSA. там будет точно такая же коллекция в одном из сервисов, и менять её будет не поток, порожденный программистом, а поток порожденный хостом для обработки запроса. А все остальное будет то же самое. И, как в случае монолитного приложения, так и в случае MSA падения как такового не будет. Восстановление после такого falure возможно только сбросом состояния путем насильного перезапуска, например по хелсчеку. Разница в случае MSA будет только в том, что будет перезапущен один маленький сервис, а не толстое приложение. Но при этом весь сценарий работать не будет, пока микросервис с разделяемой коллекцией в памяти не оживет.

Надежный способ решения это использовать какое-то хранилище, которое поддерживает acid транзакции. Но это и в монолите возможно. Причем в монолите есть простор для оптимизации. Так как можно использовать STM например. Но на практике, когда экземпляров приложения может быть больше одного, все разделяемое состояние надо хранить во внешних, желательно транзакционных, хранилищах.




G>>А даже в случае unmanaged можно разделить по процессам и использовать unix-sockets\named-pipes для общения между ними в рамках одного сервера, обеспечивая все взаимодействие и синхронизацию разных инстансов (серверов\контейнеров) через базу.

S>Всё верно. Если у нас shared state вынесен в "базу", которая предоставляет ACID-гарантии, то у нас масштабы проблемы ограничены.
При горизонтальном масштабировании к этому все и придут обязательно. В принципе грамотный архитектор должен сразу на такое натолкнуть.

S>В предположении, что все инварианты инкапсулированы в этой базе. На практике, зачастую собственно перемещение логики из базы в "сервисы" и делается ради того, чтобы обеспечить те инварианты, которые в базе поддерживать оказывается тяжело. То есть у нас опять корректность разделяемого состояния определяется тем, насколько корректно себя ведёт каждый сервис. И наличие бесконтрольного доступа в базу приводит к тому, что ошибка в сервисе А приводит к записи в базу мусора, который нарушает предположения, на основе которых реализованы другие сервисы.

Опять-таки MSA ничем не помогает в этом случае. Без разницы будет мусор писать в базу микросервис или монолит.

G>>Если говорить failure domain с точки зрения логики приложения, то разделение на микросервисы делает ситуацию только хуже. Так как разработчики одного микросервиса могут внести изменения, ломающие работу других и даже не узнают об этом. Поэтому с точки зрения бизнес-логики идеально чтобы бизнес-процесс начинался и заканчивался в одном микросервисе.

S>Это уже административные вопросы. Вы неявно предполагаете, что единицей тестирования является отдельный микросервис, из-за чего бизнес-процесс, пересекающий границы микросервисов, останется непротестированным.
Так это самые важные вопрос. Я еще раз напомню тезис, который в этой теме и другие коллеги подтверждают: MSA это больше про оргструктуру, а не про архитектуру. В интернетах предлагают "правильную" MSA с разделением микросервисов по разным репозитариям исходного кода. Как в этом случае обеспечить синхронность изменений разных микросервисах, если изменяемый бизнес-процесс затрагивает несколько таких микросервисов?

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

В монолите обычно используется одна репа и там по крайней мере все изменения можно (и нужно) вносить в одной (отдельной) ветке.

S>А если у нас процесс тестирования построен (хотя бы частично) вокруг бизнес-сценариев, то нам всё равно, сколько там компонентов, сервисов, или микросервисов в нём участвует.

В msa весьма вероятна ситуация, что в принципе невозможно собрать работающее сочетание микросервисов. Я такое на практике видел. Было три микросервиса (А,Б,В) и два процесса(1,2), затрагивающие три сервиса. В один момент было так, что: А/HEAD, Б/HEAD, В/HEAD~1 работал сценарий 1, но не работал 2. А/HEAD, Б/HEAD~1, В/HEAD работал 2, но не работал 1 и при этом же А/HEAD~1, Б/HEAD, В/HEAD также работал 2, но не работал 1.

И каждый разработчик миросервиса доказывал что "work on my microservice" (современный аналог work on my machine)


S>Микросервисы несколько выигрывают по сравнению с другими архитектурами как раз потому, что сокращают возможности по внесению нежелательных зависимостей.

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

S>То есть пока у нас всё лежит в монолите, сотрудник команды А имеет возможность подсмотреть в код команды Б, и напрямую завязаться на то, что интерфейс IFoo реализован некоторым классом FooImpl. И вместо того, чтобы обратиться по стандартным каналам к архитекторам команды Б "добавьте мне в IFoo метод по расчёту предварительной цены без заключения сделки", делает даункаст и вызывает потрошки напрямую.

Доункаст к чему, если у него нет паблик класса, к которому даункастить?

S>Когда вы распиливаете монолит на процессы и пайпы, такой возможности уже нет — у Foo своё адресное пространство, и мимо протокола к нему обратиться не получится.

Тут даже комментировать не буду. В дотнете и жабе полно средств изоляции. При желании даже в JS можно инкапсуляцию сделать, чтобы до потрохов никто не добрался.

S>Зато можно полезть напрямую в базу "я же знаю, в каких таблицах у них что лежит". В итоге команда Б, полагая себя единоличными владельцами схемы, что-то перекраивает в очередной версии своего сервиса, и код команды А начинает падать, хотя такой же код неделю назад прекрасно работал.

Так можно и в базу другого микросервиса полезть. А чтобы этого не было — надо чтобы это были разные репы и фактически было невозможно запустить сервисы на одной машине. А это автоматом означает сложности в тестировании.
В случае единой репы и нормального архитектора — на ревью бить по рукам (или по лицу) за такой код.

G>>В итоге подходящая модель для MSA — где команды разделены по бизнес-доменам, где все транзакционные бизнес-процессы полностью лежат в ответственности домена. Например закупки, склад, производство, продажи, планирование. Причем это будут дольно большие домены и, соответственно, большие сервисы. Почему их называют "микро-сервисами"


S>Не, это вы как раз рассказываете про SOA, где сервисы всё ещё представляют собой очень крупные блоки. А MSA — это как раз экстремальное развитие SOA, когда мы дробим задачу на ещё более мелкие единицы, которые не реализуют никакой бизнес-процесс, а, скорее, отвечают за некоторые кирпичики этого процесса. Например, у вас есть "ядро" — микросервис, который отвечает за финансовые транзации. Только переводы между счетами, и всё. У него очень жёсткие инварианты, и всё покрыто требованиями регулятора. Поверх этого вы реализуете функциональность типа "Выдача кредитов". Наличие отдельного ядра гарантирует вам, что криворукий джун, разрабатывая код бизнес-процессов "выдача кредита" и "внесение очередного платежа" не напорет с транзакциями и не сломает базовые гарантии типа сохранения суммы всех балансов.

Я именно об этом и говорю. Знаю один банк где над таким ядром-"микросервисом" трудится команда из 40+ только программистов. То есть ни разу он не "микро", о чем я и говорю. А выдача кредитов это вообще с десяток связанных процессов, на каждом из которых команда в 10+ человек. То есть их тоже "микро" назвать сложно.

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

S>Дополнительными бонусами являтся возможность один писать на питоне, другой — на тайпскрипте.

Это какбы единственное неоспоримое преимущество MSA, с которым никто никогда и не спорил.
Re: Помогите правильно спроектировать микросервисное приложение
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 22.03.25 23:52
Оценка: 9 (1)
Здравствуйте, busk, Вы писали:

B>Как-то только в теории читал про микросервисы, но вот новый проект планируется небольшой и хотел как раз попробовать микросервисы тут.

Если это реальный проект за деньги, то лучшее делать его на базе известных подходов, например монолит на базе хексогональной архитектуры.
B>Первое что хотел сказать, что везде пишут микросервисы это где много команд часто или много функционала.
Это не основное их назначение. В монолите точно также можно делить всё на разные компоненты между командами.
B>но зато скоп определен четко и подумал прекрасная возможность потренироваться, чтобы потом уверенее пробовать в большом проекте.
Проект, честно скажем, небольшой.
B>Итого что по функционалу:
Ты забыл внешние системы такие как 1С и систему-поставщика заказов.

B>Третий вопрос. Если без докеров то как настроить этот набор микросервисов?

Это будет сложно. Можно на этом проекте поизучать контейнеризацию на базе докера и засунуть свой монолит и базу в отдельные контейнеры, настроить между ними сетевую связанность и подключить хранилища, подумать как будешь делать бэкап этой базы.
Для микросервисной архитектуры нужно ещё продумывать системный дизайн и процесс деплоя.
Sic luceat lux!
Re[15]: Каких программ вам не хватает?
От: · Великобритания  
Дата: 08.04.25 13:09
Оценка: 8 (1)
Здравствуйте, Sinclair, Вы писали:

S>2. Делаем два ресурса: "анонимизированное постановление", "полноценное постановление". Анонимный доступ ко второму получает 401, аутентифицированный доступ без прав на данное дело получает 403.

Такое экспоненциально рванёт. У тебя 2 ресурса для одного permission "смотреть инфу о фигурантах". Представь у тебя 10 таких permissions, в зависимости от роли пользователя. Потребуется 1024 разных ресурса.
А ещё ты можешь запрашивать список документов. К половине у тебя роль полного доступа, а к половине частичного.

S>3. Делаем два ресурса: постановление, в "тексте" которого есть ссылки на фигурантов, каждый из которых — самостоятельный ресурс. Постановления отдаём всем желающим, детали фигурантов — только авторизованным пользователям. Остальные получают 403.

Получаем список из n документов, и в каждом ещё 10 ссылок. Тут же шлём ещё n*10 запросов, некоторые из которых что-то возвращают, а некоторые дают 403 отлуп... Тучи запросов и тормоза на пустом месте.

S>Как по мне, так первый вариант, очевидно, самый-самый плохой. Он плохо масштабируется, и крайне плохо проверяется на корректность.

Зато работает.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[3]: Помогите правильно спроектировать микросервисное приложение
От: Sinclair Россия https://github.com/evilguest/
Дата: 03.04.25 13:56
Оценка: 3 (1)
Здравствуйте, busk, Вы писали:

B>а вопрос такой: если это будет винда и один сервер то как проще организовать архитектуру двух сервисов (аутенфикация + авторизация) и всего остального?

B>докер или один общий шлюз (я так понял приложение) и дальше запрос идет либо на сервис 1 либо на сервис 2?
Обычно никаких шлюзов нет, и пользователь явно идёт за токеном в сервис номер 1, а уже потом с этим токеном идёт в сервис номер 2.

Можем посмотреть на пример:

Сервис номер 2 расположен по адресу https://graph.microsoft.com/{version}/{resource}?{query-parameters}.
Токены для него получаем из сервиса номер 1 по адресу https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize

Наличие в сервисе 1 авторизации означает, что у вас сервис номер один возвращает в токене не просто идентити пользователя, а и некий набор привилегий, которые сервис номер 2 считывает для принятия решения о том, чего пользователю делать можно, а чего — нельзя. В частности, для Microsoft Graph мы прямо в запросе авторизационного токена сервису логина указываем список scopes, к которым хотим получить доступ. И в случае успеха, токен будет содержать информацию об этом.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Помогите правильно спроектировать микросервисное приложение
От: DiPaolo Россия  
Дата: 20.03.25 15:40
Оценка: 2 (1)
Выглядит так, что тут вкореживать (именно так) микросервисы – дороже выйдет. Ну вообще никак они тут не просматриваются. Очень маленький набор сущностей и функционала. Элементарно нечего пилить

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

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

Тогда может и будет понимание, где надо (и зачем!), а где не надо впихивать микросервисы. Ну и про кубер придет понимание, что этим зоопарком баз и сервисов как-то надо рулить. И как замечательно можно скейлить отдельные куски системы по необходимости
Патриот здравого смысла
Re[16]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 07.04.25 11:22
Оценка: 2 (1)
Здравствуйте, TG, Вы писали:

TG>Я не призываю делать бан кнопок через HATEOAS. Но чем сама идея такого UI плоха?

Сама идея такого UI плоха тем, что
1. не даёт пользователю никакой информации о причинах того, что кнопка неактивна. То ли у пользователя нет прав; то ли у объявления истёк срок доступности этой кнопки; то ли просто баг на сайте.
2. даёт пользователю неверную информацию — состояние кнопки вычисляется в момент t0, а нажатие на эту кнопку происходит в произвольный момент t1, где разница между t1 и t0 может составлять дни, а не секунды.


TG>"Стандартный таймаут" — который часто выставляет фреймворк, например, WCF. Кто-то вообще не заморачивается на эти таймауты и оставляет всё по умолчанию.

Я не понимаю, какое отношение стандартный таймаут имеет к вопросу о проектировании UI.

TG>Да и в "городском" энтерпрайзе пользователи могут столкнуться с тормозами, если они сидят через VPN и админы как-то криво "раскрасили" трафик.


И это всё ещё лучше, чем прятать от пользователя возможность без объяснения причин.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[24]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 11.04.25 05:11
Оценка: 2 (1)
Здравствуйте, ·, Вы писали:
S>>Независимо от моих "привилегий".
·>Закрытые для кого? Закрытость — вещь относительная. На какие-то атрибуты у тебя есть привилегии, на какие-то нет. У других пользователей будет другой доступ к атрибутам.
Нет. Вот как раз предлагаемая вами модель чревата дырками и крайне тяжела в поддержке и верификации.
Я вам рассказываю практический замкнутый пример: нет никаких "привилегий на втрибуты". Есть два вида ресурсов. Доступ к каждому их них либо есть, либо нету.

·>Каким образом закрыт-то? Заклятие наложено что-ли? Субресурс возвращает джсон, как ты ресурсом гарантируешь отстутствие там какого-нибудь contragent.homeAddress?

Очень просто: contragent.homeAddress там нет вообще, вне зависимости от привилегий.

·>Верю. Но не потому, что "API устроен именно так".



·>Почему ты так решил? Ты так говоришь, что ресурс это какая-то охраняемая зона за колючей проволокой.

Потому что я так спроектировал, и это легко проверить как методом "белого ящика", так и "чёрного ящика".
·>Нет, это просто несколько байт в определённом месте хедера запроса, а обрабатывает всё это дело тот же самый условно питонячий код, что и для других ресурсов.
Если у вас так, то всё плохо. Попробуйте перепроектировать так, чтобы в одном коде не смешивалась обработка "своих" и "чужих" инвойсов. Человечество изобрело массу способов факторизации кода.

·>Я спорю с тем, что ресурсы и урлы каким-то образом обеспечивают хоть какую-то безопасность. Что в зависимости от того куда поместить данные — в урл или хедер — вдруг внезапно станет "Зато всё безопасно".

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

·>А чё так мелко? Сразу уж говори — источник данных — заряд на затворе транзистора. Да, там с привилегиями как-то не очень. Я вообще-то говорил о дизайне самого сервиса. БД — это уже другой сервис.

Нет, БД — это не "другой сервис", это неотъемлемый компонент сервиса, оборудованного персистентным состоянием.
Впрочем, можно спроектировать и так, как вы предлагаете — вынести БД в отдельный сервис, из которого торчит очень широкий контракт.
И, естественно, у него очень грубый набор привилегий. Ваша модель "давайте мы будем ограничивать доступ путём передачи пользовательского токена вдоль всей иерархии вызовов" работает примерно никогда.
Все практики безопасности как раз так и устроены, что у принципала X нету привилегий к "сырому" ресурсу A, но есть привилегии на доступ к "производному" ресурсу B. Сервис, выполняющий построение ресурса B, выполняется под принципалом Y, который имеет полные привилегии для A, но учитывает привилегии X при отдаче ему производного ресурса B.
Типичный пример применения концепции в рамках SQL99: пользователю нельзя видеть часть строк в таблице X. Мы не можем навесить привилегию на каждую строку. Зато можем сделать следующее:
1. Отбираем у пользователя привилегии на таблицу X
2. Строим на основе X представление Y, в котором добавлен предикат безопасности (типа select * from X where TotalAmount < 100000)
3. Выдаём пользователю привилегии на Y и указываем, что Y исполняется под привилегиями админа, а не пользователя.
Аналогично мы могли бы поступить и с ограничениями на колонки таблицы. Квадратно-гнездовая система, где чётко видна вся схема Y и легко проверить, что туда попадает, а что нет, как методом статического анализа, так и методом выполнения динамических тестов. Вы предлагаете заменить её на некий невнятный код "хранимой процедуры", которая возвращает всякий раз разный набор строк и колонок в зависимости от рантайм-содержимого параметров.
И всё это под тем предлогом, что "какая нам разница, где передаётся информация о привилегиях — всё равно это текст SQL запроса".
Нет, увы. Факторизация кода позволяет нам изолировать разные сценарии.

·>А, так да. Но собственно тут обсуждалось "Безопасность очень часто входит в конфликт с производительностью", мой вопрос был "Интересно узнать какой такой магией фрагмент в урле повышает безопасность?". И в качестве ответа ты внезапно рассказываешь о "поднимает производительность" "не противоречит безопасности".

Фрагмент в урле существует не сам по себе. Структура урла применятся для роутинга — выбора кода, который будет обслуживать поступивший запрос. Правила роутинга — простая, понятная логика, которую легко отладить и гарантировать отсутствие неожиданностей вроде "в ответ на запрос чужих инвойсов внезапно вызвался код по подготовке своих инвойсов".
Следующим шагом мы можем очень легко проверить, что код по подготовке "чужих" инвойсов никогда не возвращает приватных данных. Просто потому, что в этом коде вообще нет такой ветки, которая бы это делала.
Дальше нам остаётся проверить, что мы корректно проверяем claims в токене для того, чтобы понять, что входит в "свои" и в "чужие" инвойсы.
Собственно, на этом всё.

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

·>С чего ты взял? Никогда не было. А вот у тебя иллюзия в полный рост, цитирую: "чтобы границы безопасности совпадали с границами ресурсов. Потому что это и надёжнее,", "Зато всё безопасно". Нет, конечно. Надёжность тут не причём. Так просто удобнее и понятнее для человеков: не видно, что не должно быть видно. Т.е. чисто иллюзорные результаты.

Это оттого, что я плохо объясняю. Разница в подходах есть. Понятно, что достичь приемлемого результата можно в любом подходе, но стоимость получается разной. Когда границы безопасности совпадают с границами ресурсов, это сильно упрощает доказательство корректности. Я выше примерно написал, каким именно способом. Но вы можете мне не верить и писать более дорогостоящие и трудноподдерживаемые системы — у нас же нет архитектурной полиции
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Помогите правильно спроектировать микросервисное приложение
От: Miroff Россия  
Дата: 20.03.25 15:42
Оценка: +1
Здравствуйте, busk, Вы писали:

B>Тут я понимаю, что проще было бы сделать монолит, но для обучения вполне годный вариант?


А у вас ресурсы-то на микросервисы есть? На тот же K8S и CI/CD хотя бы.

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


Это самое простое. Делить нужно по бизнес-домену (мыши и кактусы отдельно, марксизм и диамат отдельно), по технологиям (ML на питоне, интеграция с внешними сервисами на Scala, интерфейс к БД на сишарпе), требованиям к масштабированию (фронтофисом пользуется вся страна, а бэкофисом 20 человек), надежности (если отчеты упадут об этом узнают через месяц, а если торговый робот упадет, компания обанкротится за 5 минут). Если ничего этого нет, микросервисы не нужны.

B>Третий вопрос. Если без докеров то как настроить этот набор микросервисов? тут их немного будет и читал что можно настроить без докер контейнеров если что.


Можно, только это очень дорого и даже Яндекс себе такого не может позволить.
Re[3]: Помогите правильно спроектировать микросервисное приложение
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 21.03.25 08:08
Оценка: +1
Здравствуйте, busk, Вы писали:

B>Здравствуйте, gandjustas, Вы писали:


G>>Здравствуйте, busk, Вы писали:


B>>>Как-то только в теории читал про микросервисы, но вот новый проект планируется небольшой и хотел как раз попробовать микросервисы тут.

G>>Не надо, оно тебя сожрет

B>поясни пожалуйста подробней. а то смотришь тот же Яндекс, у них везде микросервисы + ci/cd


1) Ты не яндекс, даже на 1% не яндекс, и никогда яндексом не станешь
2) яндекс на старте не был микросервисным
3) cd\cd без микросервисов работает лучше
Re: Помогите правильно спроектировать микросервисное приложение
От: bnk СССР http://unmanagedvisio.com/
Дата: 21.03.25 09:41
Оценка: +1
Здравствуйте, busk, Вы писали:

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


Они проходят по границам команды. Одна команда — один микросервис.
Re[9]: Каких программ вам не хватает?
От: Miroff Россия  
Дата: 25.03.25 08:10
Оценка: -1
Здравствуйте, Sinclair, Вы писали:

S>Я не вижу каких-то прямо практически значимых преимуществ HATEOAS.


HATEOAS позволяет не размазывать логику между сервером и клиентом. Клиенту не нужно думать, можно ему дергать какой-то ресурс или нет. Прислали ссылку, значит можно. Не прислали -- нельзя. Вместе с OPTIONS это такой подход позволяет полностью перенести авторизацию с клиента на сервер. Или, например, пейджинг: клиенту не нужно вычислять сколько страниц всего, какая предыдущая, какая следующая и т.п. Вместо этого ему сразу приходит список страниц, которые можно дернуть.

S>- можно ли в качестве owner использовать URL юзер-аккаунта в другом скоупе


HATEOAS это про чтение, что ты собрался использовать при чтении. Можно ли поменять owner? Надо пробовать, может да, может нет, может в каких-то случаях да, а в остальных нет. Даже OpenAPI не позволяет описать настолько сложные контракты.

S>- что делает глагол refund, и какие у него будут параметры, и где их брать


Это же ресурс, делаешь GET, смотришь, меняешь, делаешь PUT.

S>2. Evolvability улучшается крайне незначительно. У нас нет никакого способа научить клиентов всегда ходить только по указанным нами ссылкам. Если мы решили перенести endpoint для рефандов в другое место, то недостаточно просто отдавать новую ссылку в links.


Правильно делать GET перед PUT, потому что ссылки могут измениться, и вообще конкурентные обновления. Если разработчики не умеют пользоваться REST API это их проблема. Можно тупо менять ссылки при каждом запросе, чтобы даже желания сохранять их куда либо не возникало.

S>3. Накладные расходы значительно увеличиваются.


Я тебя умоляю, мы видео в 4К по сети гоняем и GUID вместо id используем. Несколько ссылок погоды не сделают.
Re[10]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 25.03.25 08:38
Оценка: +1
Здравствуйте, Miroff, Вы писали:

M>HATEOAS позволяет не размазывать логику между сервером и клиентом. Клиенту не нужно думать, можно ему дергать какой-то ресурс или нет. Прислали ссылку, значит можно. Не прислали -- нельзя.

Это заблуждение. Авторизация проверяется совершенно отдельно. Ещё не хватало в представлении ресурса показывать разный набор ссылок в зависимости от transient штуки вроде Bearer-токена.

M>Вместе с OPTIONS это такой подход позволяет полностью перенести авторизацию с клиента на сервер.

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

M>Или, например, пейджинг: клиенту не нужно вычислять сколько страниц всего, какая предыдущая, какая следующая и т.п. Вместо этого ему сразу приходит список страниц, которые можно дернуть.

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

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

M>HATEOAS это про чтение, что ты собрался использовать при чтении.

Нет конечно. HATEOAS — это про идентификацию ресурсов. REST сам по себе (даже без HATEOAS) — как раз про то, что все действия выполняются через управление представлением состояния.
В частности, приделывание к платёжке ссылки refund с методом POST — это RMM не L3, а L1. Потому, что нормальный способ — это PUT либо PATCH, которые прямым либо косвенным образом меняют состояние платежа на refunded.

M>Можно ли поменять owner? Надо пробовать, может да, может нет, может в каких-то случаях да, а в остальных нет. Даже OpenAPI не позволяет описать настолько сложные контракты.

Конечно позволяет. Вот у вас есть объект, у него есть представление. Всё, можно делать PUT этого представления. Если что-то запрещено бизнес-правилами — приедет 409. Если правами доступа — 403.

S>>- что делает глагол refund, и какие у него будут параметры, и где их брать

M>Это же ресурс, делаешь GET, смотришь, меняешь, делаешь PUT.
Нет конечно. Это не ресурс, это адрес для POST запроса.

M>Правильно делать GET перед PUT, потому что ссылки могут измениться, и вообще конкурентные обновления. Если разработчики не умеют пользоваться REST API это их проблема. Можно тупо менять ссылки при каждом запросе, чтобы даже желания сохранять их куда либо не возникало.

Ну, у нас же нет REST-полиции. Никто вас не арестует за такую реализацию (и за любую другую). Но на практике людям больше нравятся сервисы, которые не требуют от них делать лишние запросы, увеличивая трафик и латентность.
Особенно когда гипотетическая нужда переноса URL-ов для parent payment не наступает никогда.

M>Я тебя умоляю, мы видео в 4К по сети гоняем и GUID вместо id используем. Несколько ссылок погоды не сделают.

Сделают. Стоимость эксплуатации складывается из мелочей. Два-три десятка таких идиотских решений — и вот уже ваш стейкхолдер вместо одного виртуального сервера оплачивает ферму из восьми выделенных.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[6]: Помогите правильно спроектировать микросервисное приложение
От: · Великобритания  
Дата: 25.03.25 11:22
Оценка: +1
Здравствуйте, gandjustas, Вы писали:

G>В этом случае может быть выгодно иметь микросервисы как раз по границам команд. Других адекватных причин использовать MSA я не видел.

В мною виденных трейдинговых системах — везде сабж. Одна команда (~10 девов) пилит пол-сотни приложух, которые разворачивачивется в ~тысячу сервисов на десятках хостов в пятёрке датацентров.
И да, сервисы не через REST взаимодйествуют, а через pub-sub сообщения (kafka/29west/mq/fix/аналоги).
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[4]: Помогите правильно спроектировать микросервисное приложение
От: TG  
Дата: 25.03.25 13:24
Оценка: +1
Здравствуйте, Miroff, Вы писали:

M>Микросервисы позволяют пернести часть сложности из приложения в оркестрацию. Это сильно упрощает разработку, когда у тебя в сервисе меньше 10к строк и один разработчик. Нет ни мердж конфликтов, не нужно ни с кем договариваться, не нужна документация, планирование, архитектура.


API приложения полностью зависит от нужд потребителя. Договариваться придётся.
И документация на API нужна (даже если у вас RMM L3). Людям нужно знать не столько функционал отдельного эндпойнта, сколько возможность осуществить некоторый сценарий. Свагер такого не описывает.

M>Выставляешь Restful API и проблема других сервисов как этим API воспользоваться.

Даже условный Яндекс с его, например, Картами не может себе такого позволить и думает о потребителях, иначе конкуренты сожрут.
Re[7]: Помогите правильно спроектировать микросервисное приложение
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 25.03.25 15:32
Оценка: :)
Здравствуйте, ·, Вы писали:

·>Здравствуйте, gandjustas, Вы писали:


G>>В этом случае может быть выгодно иметь микросервисы как раз по границам команд. Других адекватных причин использовать MSA я не видел.

·>В мною виденных трейдинговых системах — везде сабж. Одна команда (~10 девов) пилит пол-сотни приложух, которые разворачивачивется в ~тысячу сервисов на десятках хостов в пятёрке датацентров.
·>И да, сервисы не через REST взаимодйествуют, а через pub-sub сообщения (kafka/29west/mq/fix/аналоги).

Я конечно тоже видел системы, где микросервисов больше чем программистов и пользователей вместе взятых, но при проверке оказывалось что все то же самое можно было бы запились в монолит с меньшими затратами, не потеряв вообще никаких потребительских качеств системы.
Re[8]: Помогите правильно спроектировать микросервисное приложение
От: Sinclair Россия https://github.com/evilguest/
Дата: 01.04.25 05:17
Оценка: +1
Здравствуйте, gandjustas, Вы писали:

G>В managed среда это можно и без микросервисов сделать.

Не очень понятно, что вы имеете в виду. Поддержку AppDomain выпилили (за ненадобностью) из нового дотнета, а в жаве её никогда и не было.
Управляемая среда всего лишь гарантирует отсутствие ошибок типизации и "повисших" ссылок. Всё. Никакой изоляции она из коробки не предоставляет.
Понятно, что она лучше любого анменеджеда хотя бы тем, что в ней нет undefined behavior (если, опять же, придерживаться гигиены и не пользоваться всякими ансейф и около-ансейф вещами).
Но defined behavior недостаточно для ограничения failure domain. Потому что если есть разделяемое состояние, то невозможно гарантировать его целостность при наступлении неожиданных результатов.
Вот у вас есть разделяемая в памяти коллекция, и один поток начал её модификацию, пока второй читает. Ок, мы обеспечили отсутствие гонок, обложив доступ примитивами синхронизации.
Менеджед-среда (более-менее) гарантирует нам то, что при выбросе исключения будут обработаны все блоки finally и, в частности, все удерживаемые блокировки будут отпущены. Но она вовсе не гарантирует нам то, что после отпускания блокировок коллекция придёт в консистентное (с точки зрения прикладных инвариантов) состояние.

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

G>А даже в случае unmanaged можно разделить по процессам и использовать unix-sockets\named-pipes для общения между ними в рамках одного сервера, обеспечивая все взаимодействие и синхронизацию разных инстансов (серверов\контейнеров) через базу.

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

Поэтому сервисная архитектура и появляется как развитие идеи "давайте разведём сервисы по процессам и заставим их взаимодействовать по ограниченным каналам". Выбор JSON over HTTP вместо "proprietary binary protocol over named pipes" обусловлен уже не вопросами надёжности, а вопросами совместимости и готовности к эволюции.
Если мы попытаемся спроектировать свой бинарный протокол со встроенной поддержкой всех нужных negotiations, а также с умением восстанавливаться после сбоев и кэшировать результаты, то у нас получится примерно такой же REST, чутка отличающийся диалектом.

G>Если говорить failure domain с точки зрения логики приложения, то разделение на микросервисы делает ситуацию только хуже. Так как разработчики одного микросервиса могут внести изменения, ломающие работу других и даже не узнают об этом. Поэтому с точки зрения бизнес-логики идеально чтобы бизнес-процесс начинался и заканчивался в одном микросервисе.

Это уже административные вопросы. Вы неявно предполагаете, что единицей тестирования является отдельный микросервис, из-за чего бизнес-процесс, пересекающий границы микросервисов, останется непротестированным.
Но с таким подходом мы налетим на те же проблемы и в монолите — если мы ограничимся юнит-тестами компонентов без интеграционного тестирования получится ровно такой же результат.
А если у нас процесс тестирования построен (хотя бы частично) вокруг бизнес-сценариев, то нам всё равно, сколько там компонентов, сервисов, или микросервисов в нём участвует.
Микросервисы несколько выигрывают по сравнению с другими архитектурами как раз потому, что сокращают возможности по внесению нежелательных зависимостей.
То есть пока у нас всё лежит в монолите, сотрудник команды А имеет возможность подсмотреть в код команды Б, и напрямую завязаться на то, что интерфейс IFoo реализован некоторым классом FooImpl. И вместо того, чтобы обратиться по стандартным каналам к архитекторам команды Б "добавьте мне в IFoo метод по расчёту предварительной цены без заключения сделки", делает даункаст и вызывает потрошки напрямую.
Когда вы распиливаете монолит на процессы и пайпы, такой возможности уже нет — у Foo своё адресное пространство, и мимо протокола к нему обратиться не получится.
Зато можно полезть напрямую в базу "я же знаю, в каких таблицах у них что лежит". В итоге команда Б, полагая себя единоличными владельцами схемы, что-то перекраивает в очередной версии своего сервиса, и код команды А начинает падать, хотя такой же код неделю назад прекрасно работал.

G>В итоге подходящая модель для MSA — где команды разделены по бизнес-доменам, где все транзакционные бизнес-процессы полностью лежат в ответственности домена. Например закупки, склад, производство, продажи, планирование. Причем это будут дольно большие домены и, соответственно, большие сервисы. Почему их называют "микро-сервисами"


Не, это вы как раз рассказываете про SOA, где сервисы всё ещё представляют собой очень крупные блоки. А MSA — это как раз экстремальное развитие SOA, когда мы дробим задачу на ещё более мелкие единицы, которые не реализуют никакой бизнес-процесс, а, скорее, отвечают за некоторые кирпичики этого процесса. Например, у вас есть "ядро" — микросервис, который отвечает за финансовые транзации. Только переводы между счетами, и всё. У него очень жёсткие инварианты, и всё покрыто требованиями регулятора. Поверх этого вы реализуете функциональность типа "Выдача кредитов". Наличие отдельного ядра гарантирует вам, что криворукий джун, разрабатывая код бизнес-процессов "выдача кредита" и "внесение очередного платежа" не напорет с транзакциями и не сломает базовые гарантии типа сохранения суммы всех балансов.
Опять же сбоку этого делается отдельный сервис по оценке рисков, который никак не может сломать поведение бизнес-процесса "рассмотрение кредитных заявок", и в худшем случае у вас какие-то из видов кредитов перестанут выдаваться. Но никаких шансов запороть механику начисления процентов и списания задолженности у этого микросервиса нет.
И так далее — всё строится из параноидально изолированных микрокомпонентов. Один умеет рассчитывать стоимость залогового имущества, другой — умеет управлять статусами залогового имущества. Третий из этих двух собирает бизнес-процесс "переоценка рисков и досрочное истребование кредита в связи с изменением существенных обстоятельств".
Дополнительными бонусами являтся возможность один писать на питоне, другой — на тайпскрипте.

Как-то так.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[10]: Помогите правильно спроектировать микросервисное приложение
От: Sinclair Россия https://github.com/evilguest/
Дата: 02.04.25 09:51
Оценка: +1
Здравствуйте, gandjustas, Вы писали:

G>Я говорю о том, что вручную выстроенная модульность внутри приложения, на уровне отсутствия ссылок из группы объектов, поддерживается самой managed средой. Без использования ансейфа и разделяемых данных без должной осмотрительности крайне сложно в managed среде во время обработки одного запроса нарушить работу кода, обрабатывающего другие запросы.

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

G>А давай прикинем как это будет в MSA. там будет точно такая же коллекция в одном из сервисов, и менять её будет не поток, порожденный программистом, а поток порожденный хостом для обработки запроса. А все остальное будет то же самое. И, как в случае монолитного приложения, так и в случае MSA падения как такового не будет. Восстановление после такого falure возможно только сбросом состояния путем насильного перезапуска, например по хелсчеку. Разница в случае MSA будет только в том, что будет перезапущен один маленький сервис, а не толстое приложение. Но при этом весь сценарий работать не будет, пока микросервис с разделяемой коллекцией в памяти не оживет.

Всё верно. MSA не гарантирует безошибочности. MSA гарантирует, что падение не затронет сценарии, в которых микросервис не задействован.

G>Надежный способ решения это использовать какое-то хранилище, которое поддерживает acid транзакции. Но это и в монолите возможно. Причем в монолите есть простор для оптимизации. Так как можно использовать STM например. Но на практике, когда экземпляров приложения может быть больше одного, все разделяемое состояние надо хранить во внешних, желательно транзакционных, хранилищах.

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

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

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

G>Опять-таки MSA ничем не помогает в этом случае. Без разницы будет мусор писать в базу микросервис или монолит.

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

G>Так это самые важные вопрос. Я еще раз напомню тезис, который в этой теме и другие коллеги подтверждают: MSA это больше про оргструктуру, а не про архитектуру. В интернетах предлагают "правильную" MSA с разделением микросервисов по разным репозитариям исходного кода. Как в этом случае обеспечить синхронность изменений разных микросервисах, если изменяемый бизнес-процесс затрагивает несколько таких микросервисов?

Никак — MSA, собственно, и обеспечивает отсутствие синхронности. Это преимущество, а не недостаток.
Изменения в бизнес-процессе накатываются постепенно: сначала мы обучаем новостям самый "нижний" микросервис в топологически отсортированном списке микросервисов, затем — чуть более "верхние".
Изменения в БП становятся видны в тот момент, когда мы выкатываем изменения "корневого" микросервиса, который оркестрирует весь БП.

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

G>В msa весьма вероятна ситуация, что в принципе невозможно собрать работающее сочетание микросервисов. Я такое на практике видел. Было три микросервиса (А,Б,В) и два процесса(1,2), затрагивающие три сервиса. В один момент было так, что: А/HEAD, Б/HEAD, В/HEAD~1 работал сценарий 1, но не работал 2. А/HEAD, Б/HEAD~1, В/HEAD работал 2, но не работал 1 и при этом же А/HEAD~1, Б/HEAD, В/HEAD также работал 2, но не работал 1.

G>И каждый разработчик миросервиса доказывал что "work on my microservice" (современный аналог work on my machine)

Это организационная проблема. В монолите все эти команды делали бы ровно то же самое ровно с тем же результатом.
А, ну и, возможно, неудачно были проведены границы между микросервисами. Это — отдельное искусство, настолько редкое, что я, ЕМНИП, видел только одно правильное решение (и с десяток заведомо неверных).

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

Может быть. Я не говорю, что MSA — единственный верный способ деятельности

G>Доункаст к чему, если у него нет паблик класса, к которому даункастить?

Почему вы думаете, что нету?
А если нету — всегда можно запилить reflection. Пытливому уму все средства хороши.

G>Тут даже комментировать не буду. В дотнете и жабе полно средств изоляции. При желании даже в JS можно инкапсуляцию сделать, чтобы до потрохов никто не добрался.

Как раз в JS-то можно. Но, опять же, можно!=делают.

G>Так можно и в базу другого микросервиса полезть.

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

G>В случае единой репы и нормального архитектора — на ревью бить по рукам (или по лицу) за такой код.

Это всё хорошо работает до определённых размеров кодовой базы, команды, и уровня ответственности за промахи. Там, где за ошибки принято тюремное заключение или суровые штрафы, делают именно так, не полагаясь на бдительность peer review и личность архитектора.

G>Я именно об этом и говорю. Знаю один банк где над таким ядром-"микросервисом" трудится команда из 40+ только программистов. То есть ни разу он не "микро", о чем я и говорю. А выдача кредитов это вообще с десяток связанных процессов, на каждом из которых команда в 10+ человек. То есть их тоже "микро" назвать сложно.

Так "micro" это же не про размер команды. А про "площадь поверхности".

G>Напомню что апологеты микросервисов говорят что микросервис это когда команду можно накормить двумя пиццами, грубо 4-5 человек.

Хм. Я не очень тесно знаком с апологетами микросервисов, могу чего-то не знать.

G>Это какбы единственное неоспоримое преимущество MSA, с которым никто никогда и не спорил.

Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[10]: Помогите правильно спроектировать микросервисное приложение
От: · Великобритания  
Дата: 02.04.25 10:08
Оценка: +1
Здравствуйте, gandjustas, Вы писали:

G>Я говорю о том, что вручную выстроенная модульность внутри приложения, на уровне отсутствия ссылок из группы объектов, поддерживается самой managed средой. Без использования ансейфа и разделяемых данных без должной осмотрительности крайне сложно в managed среде во время обработки одного запроса нарушить работу кода, обрабатывающего другие запросы.

Гы. Как минимум, память и gc — разделяемые. Так что когда запрос какого-нибудь отчёта для аналитики вдруг роняет по OOM всё сразу, в т.ч. обработку заказов — ничего хорошего.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[11]: Помогите правильно спроектировать микросервисное приложение
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 02.04.25 11:03
Оценка: +1
Здравствуйте, ·, Вы писали:

·>Здравствуйте, gandjustas, Вы писали:


G>>Я говорю о том, что вручную выстроенная модульность внутри приложения, на уровне отсутствия ссылок из группы объектов, поддерживается самой managed средой. Без использования ансейфа и разделяемых данных без должной осмотрительности крайне сложно в managed среде во время обработки одного запроса нарушить работу кода, обрабатывающего другие запросы.

·>Гы. Как минимум, память и gc — разделяемые. Так что когда запрос какого-нибудь отчёта для аналитики вдруг роняет по OOM всё сразу, в т.ч. обработку заказов — ничего хорошего.
Ничего не мешает в рамках монолитного решения вынести отдельный инстанс для обработки тяжелых запросов и на уровне балансера распределять.

Еще раз повторю тезис: MSA это больше про оргструктуру и следующие за ней технические решения. А все инструменты: докеры, кубернетесы, балансеры, кэши, готовые сервисы хранения и расчетов, вполне можно применять даже если у вас весь ваш код в одной репе, копилируется в один бинарник и запускается в одном контейнере.
Re[13]: Помогите правильно спроектировать микросервисное приложение
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 02.04.25 14:32
Оценка: +1
Здравствуйте, ·, Вы писали:

·>Здравствуйте, gandjustas, Вы писали:


G>>>>Я говорю о том, что вручную выстроенная модульность внутри приложения, на уровне отсутствия ссылок из группы объектов, поддерживается самой managed средой. Без использования ансейфа и разделяемых данных без должной осмотрительности крайне сложно в managed среде во время обработки одного запроса нарушить работу кода, обрабатывающего другие запросы.

G>>·>Гы. Как минимум, память и gc — разделяемые. Так что когда запрос какого-нибудь отчёта для аналитики вдруг роняет по OOM всё сразу, в т.ч. обработку заказов — ничего хорошего.
G>>Ничего не мешает в рамках монолитного решения вынести отдельный инстанс для обработки тяжелых запросов и на уровне балансера распределять.
·>Видимо ты тут намекаешь на какую-то принципиальную разницу между SOA и MSA?

«Они очень маленькие. Даже сто строк кода, вероятно, считаются сегодня большим сервисом», — Фред Джордж, Barcelona Ruby Conference


«Команда на две пиццы» https://aws.amazon.com/executive-insights/content/amazon-two-pizza-team/


«Если сервис проектирует и поддерживает несколько программистов, то это не микросервис», — Фред Джордж, GOTO 2016


«Каждый сервис автономен, самостоятелен и выполняет уникальный процесс». https://www.paloaltonetworks.co.uk/cyberpedia/what-are-microservices#:~:text=Each%20service%20is%20autonomous%20and%20self%2Dcontained%20and%20runs%20a%20unique%20process


«Каждый микросервис упакован как контейнер Docker, чтобы обеспечить возможность развёртывания в кластер Kubernetes для оркестрации приложения». https://thinkmicroservices.com/


Тут и паттерны, и технологии, и оргструктуры и много чего еще.


·>Ещё почему-то ты предполагаешь что есть некий один универсальный балансер. А в приложухе может быть REST для аналитики, FIX для заказов и т.п.

Я не понял к чему эта фраза

G>>Еще раз повторю тезис: MSA это больше про оргструктуру и следующие за ней технические решения.

·>По-моему, ты причину со следствием путаешь.
А может и наоборот, не задумывался об этом?
Я вижу что микросервисы цветут там, где слишком много команд и разработчиков чтобы пилить монолиты. Поэтому техническая архитектура диктуется оргструктурой. Если у тебя команда небольшая или ты вообще один что-то делаешь — тебе в принципе не нужны микросервисы.


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

·>А зачем обязательно один бинарник? Если деплоймент разный всё равно. Чтобы были многочасовые билды?
А ты думаешь сборка одного толстого бинарника медленнее, чем сборка трех бинарников потоньше? Или ты думаешь что обязательно пересобирать все проекты каждый раз?
Да и в целом время сборки для деплоя мало интересует, интересует время от команды run до запуска приложения, если ты это делаешь 25 раз в день.

·>Сборка, деплой и перезапуск мелкого сервиса занимает минуты от момента мержа PR. Тогда как типичная выкатка монолита — приятно проведённые выходные.

В теории да. Но внезапно:
1) в микросервисах надо тупо больше кода править
2) если ты затрагиваешь несколько сервисов своим изменением, то несколько сервисов собираются дольше чем один
3) даже докер умеет кэшировать образы, поэтому вполне можно сделать сбору с кэшированием и не пересобирать то, что не изменилось
Re[11]: Помогите правильно спроектировать микросервисное приложение
От: TG  
Дата: 04.04.25 06:01
Оценка: +1
Здравствуйте, Miroff, Вы писали:

Как у Вас это:
M>Разумеется, у такой архитектуры полно недостатков: нужен глубокий анализ домена, нужно бить по рукам тем, кто пытается домен ломать, полная схема взаимодействий становится очень сложной и превращается в комбинаторную стейт машину через которую практически невозможно протащить единичный сценарий, авторизация становится нетривиальным занятием.
сочетается с этим:
M> Но зато можно поддерживать небольшой командой в 10-15 человек несколько сотен микросервисов почти не напрягаясь.
?

Что понимается под поддержкой?
Re[11]: Каких программ вам не хватает?
От: Miroff Россия  
Дата: 04.04.25 06:11
Оценка: -1
Здравствуйте, Sinclair, Вы писали:

S>Это заблуждение. Авторизация проверяется совершенно отдельно. Ещё не хватало в представлении ресурса показывать разный набор ссылок в зависимости от transient штуки вроде Bearer-токена.


Можно это как-то обосновать? Мне кажется, мы о разных вещах говорим. Есть ресурс, есть набор связанных ресурсов с которыми можно проделывать какие-то операции. HATEOS позволяет НЕ ВЫЗЫВАЯ операций предсказать, будут они доступны клиенту или нет. Например, в списке сотрудников рядом с именем Sinclair либо показывать кнопку "объявить выговор" или не показывать. И чтобы это реализовать без HATEOAS часть логики авторизации, кому можно налагать взыскания и на кого, вынужденно скопируется из сервиса в его клиента. А поскольку мы сейчас обсуждаем микросервисную архитектуру, где акторами являются не только пользователи, но и другие сервисы, эта логика начинает неконтролируемо расползаться по системе. Как в примере из соседнего поста, когда сервис туров следит чтобы определенные туры были доступны только совершеннолетним пользователям и эта же логика дублируется в сервисе рекомендаций чтобы не показывать несоврешеннолетним то, что им и так недоступно. HATEOAS бы эту проблему решил докинув ресурс user список доступных для него туров.

S>Да, пейджинг — это один из немногих случаев корректного и полезного применения ссылок. Но вообще, его изготовить правильно — очень сложно. Сильно сложнее, чем кажется на первые три взгляда. В частности, "список страниц, которые можно дёрнуть" — плохая идея, которая ломается в большом количестве сценариев.


Опять же, можешь раскрыть тему? Пейджинг это простая штука если перестать думать о нем, как о RPC и начать думать как об отдельном ресурсе. Ты СОЗДАЕШЬ отдельный объект "поисковый запрос" и в ответ получаешь список страниц с результатами этого запроса. И, внезапно, у тебя уже нет проблем со стабильностью, сортировки, изменению состава страниц, кэшированию и т.п. Результат фиксируется в момент создания запроса и далее до нового поиска уже не меняется.

S>В частности, приделывание к платёжке ссылки refund с методом POST — это RMM не L3, а L1. Потому, что нормальный способ — это PUT либо PATCH, которые прямым либо косвенным образом меняют состояние платежа на refunded.


Нет. POST refund это создание ДРУГОГО ресурса. Другого потому что у него другой URI. Нужно думать о рефанде не как об изменении платежа, а как ос создании нового объекта — сторнирующей операции, потому что сам платеж изменять не позволяет принцип двойной бухгалтерии известный с 17 века: сделанная проводка не может быть удалена.

S>Конечно позволяет. Вот у вас есть объект, у него есть представление. Всё, можно делать PUT этого представления. Если что-то запрещено бизнес-правилами — приедет 409. Если правами доступа — 403.


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

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


Людям вообще нравится RPC, даже по этой теме видно. Но RPC не дает необходимой для микросервисов изоляции и довольно быстро превращает приложение в распределенный монолит.
Re[9]: Помогите правильно спроектировать микросервисное приложение
От: Miroff Россия  
Дата: 04.04.25 10:16
Оценка: +1
Здравствуйте, TG, Вы писали:

TG>Так сервис может не ограничиваться CRUD-ом и состояниями.

TG>Построение маршрута там же Яндекс.Карты, например.
TG>Какое там "полное API" для всех клиентов можно выкатить?

Посмотри на API OpenStreetMap, версия 0.7 вышла 15 лет назад когда, еще JSON не изобрели, и с тех пор ее не апдейтили потому что и так хорошо вышло. Так бывает, когда API проектируют инженеры, а не менеджеры.
Re[8]: Помогите правильно спроектировать микросервисное приложение
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 05.04.25 15:51
Оценка: +1
Здравствуйте, Sharov, Вы писали:

S>А в чем проблема взаимодействовать по REST'у?

В том, что его применяют там, где он не нужен. У меня в последнее время есть сомнения что народ в массе понимает что такое REST и зачем он нужен.
Sic luceat lux!
Re[19]: Каких программ вам не хватает?
От: · Великобритания  
Дата: 09.04.25 09:27
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

S>>>Это ж не настоящие ресурсы, а виртуальные. В параллельном ответе пояснил, что экспоненциальный взрыв наступает даже тогда, когда ресурс "один", но может быть отдан в 1024 разных конфигурациях.

S>·>Гы. Практически с таким же успехом можно засунуть bearer-токен в url, вот у тебя по ресурсу для каждой конфигурации.
S>Ну, да. Поэтому я и не назвал этот способ самым лучшим. Он приемлем тогда, когда у нас нет большого разнообразия пермиссий. Скажем, есть инвойс "с точки зрения плательщика", а есть тот же инвойс "с точки зрения получателя".
Или нет смешанных пермиссий. Скажем, получить список инвойсов за период, и получится что некоторые инвойсы где ты плательщик, а некоторые получатель. В общем, способ может и красивый, но почти бесполезный на практике.

S>Вместо того, чтобы искусственно совмещать их в одном ресурсе и отдавать разный контент в зависимости от содержимого bearer token, делается два разных ресурса с похожей структурой.

Угу. А потом получится, что сегодня два, завтра внезапно понадобился третий, а через год у нас их уже 1024. Так что ещё и немножечко вредный.

S>·>Поход внутри сервиса может осуществляться в памяти того же процесса сервиса, в крайнем случае добавлением соответствующих JOIN в sql. А так у тебя будет куча сетевых вызовов... и представь это всё с мобилы через инет! Надо считать roundtrips.

S>Можно и считать. В разных задачах — разные приоритеты требований. Безопасность очень часто входит в конфликт с производительностью.
Интересно узнать какой такой магией фрагмент в урле повышает безопасность? Как ты будешь доказывать или тестировать безопасность 1024 конфигураций ресурса, пусть и виртуальных?
По сути ровно те же данные в теле запроса. Просто кусочек инфы переползает из ~третей строчки http запроса (там где Authorization: Bearer хедер) в первую строчку (там где урл). Злоумышленникам по барабану какую часть менять, а программисты с равным успехом могут налажать в проверках любой части запроса.

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

S>·>Каждую комбинацию тестировать не нужно. Нужно тестировать каждую привелегию. Два теста: "разрешено всё -> возвращается инфа о фигурантах", "разрешено всё, кроме инфы о фигурантах -> не возвращается инфа о фигурантах". Ну и отдельно матрица роли <-> привилегии.

S>Перед тем, как прийти к таким выводам, придётся как-то доказать независимость code path, которые приводят к появлению тех или иных результатов. Ну, или надеяться на эту независимость, и рисковать пролезанием false negative в каких-то особенных комбинациях привилегий.
Доказывать эту независимость придётся ровно тем же способом, как и для твоих 1024 виртуальных ресурсов.
Единственное, что может помочь, что есть какой-то уже готовый фреймворк, про который авторы зуб дают, что всё безопасно, а твоя аппликуха на него полагается. Но с т.з. системы в целом — ранзицы никакой.

S>>>На практике, конечно же, таких мелкогранулярных систем безопасности не бывает. Как правило, всё квадратно-гнездовое, и набор ролей фиксирован в бизнес-модели (и зачастую ещё и продиктован регулятором).

S>·>Ролей может быть, да. А привилегии — их может быть очень много.
S>Повторюсь: это зависит от задачи. Модель привилегий и ролей — это всего лишь оптимизация процесса "пересмотр ролей". В зарегулированном бизнесе набор привилегий жёстко связан с ролью.
S>И это не просто так: бездумная раздача привилегий слишком легко позволяет создавать дырки там, где их не ожидаешь. Типа, напрямую посмотреть реквизиты произвольного контрагента я не могу (прав нет), но могу отправить ему 1 рубль через платёж по номеру телефона. А код формирования ресурса "квитанция о платеже" ничего о привилегиях на контрагентов не знает — у него свой набор привилегий, и вот я уже вижу все реквизиты встроенными прямо в тело квитанции.
Как твои виртуальные ресурсы помогут? Ну да, "GET /contragents?id=vasya" тебе запрещён, а "POST /payments?to=vasya" тебе выдаст квиток с инфой конртагента.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 09.04.2025 9:28 · . Предыдущая версия .
Re[21]: Каких программ вам не хватает?
От: · Великобритания  
Дата: 09.04.25 13:21
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

S>Ну, вот на практике есть два разных списка: "инвойсы, которые выставил я", и "инвойсы, которые выставили мне". Всё, никаких чудес. Зачем делать единый список, а потом мужественно бороться с разнотипностью — .

S>Посмотрите на тот же Paypal API — он, хоть и не-REST, но устроен именно так.
Я что-то перестал понимать о чём идёт речь. Вроде ты обсуждал возможность, что некий запрос какого-то ресурса, который выдаёт результат, раскрывающий детали других ресурсов. Т.е. когда например результирующий инвойс содержит приватные данные контрагента.
То что Paypal API устроен именно так... ну дык он для того, чтобы человеки хорошо понимали, а не для безопасности.

S>·>Интересно узнать какой такой магией фрагмент в урле повышает безопасность?

S>Очень просто: у нас нет "частичной безопасности", когда содержимое ресурса зависит от каких-то эфемерных вещей. У нас для запроса есть ровно два возможных ответа: 403 или 200.
Частичной нет, верно... да вообще никакой нет. Ну выдал ваш /invoices-for-me?id=123 json 200, в котором внезапно появится секция contragent: {homeAddress: {...}}, хотя разрешено только companyAddress выдавать. А ещё злоумышленник подменит урл на /my-invoices?id=123 и увидит вообще всё.

S>·>Как ты будешь доказывать или тестировать безопасность 1024 конфигураций ресурса, пусть и виртуальных?

S>Очень просто. 2048 тестов, если уж у нас есть 1024 конфигурации ресурса.
Если у тебя уже для такой тривиальной вещи 2048 тестов, то они абсолютно бесполезны, т.к. их никто не сможет проанализировать на безопасность и поддерживать в дальнейшем.

S> Но я повторю ещё раз: у нас не будет 1024 конфигураций. Этот способ не подходит для таких API, в которых есть 10 разных привилегий на один и тот же ресурс.

А пофиг. Привилегии должны проверяться на источнике данных, а не на endpoint-е. Источник данных контрагента — это скорее всего один метод где-то внутрях. И именно он потребует наличие ровно одной конкретной привилегии. И не отдаст данные если привилегии нет, вне зависимости от того как обратились к сервису — через /contragents, через инвойсы или через платежи.
Ещё раз, ресурсы-сервисы-endpoints — это всё о том в каком формате обменяться данными по сети, и отношение к безопасности имеет чисто иллюзорное.

S>·>Урлы имеют смысл не для безопасности, а для кеширующих прокси (та самая производительность!). Но прокси на практике умеют работать только с анонимными ресурсами, у которых никаких пермов нет и можно смело всё отдавать всем. Только в этом случае есть гарантии не нарушения безопасности, т.к. нарушать собственно нечего.

S>На практике прокси прекрасно работают и с ресурсами, у которых cache-control: private. Это как раз позволяет каждому клиенту построить у себя частичную реплику распределённого состояния, и эффективно с ней взаимодействовать.
Не понял. "cache-control: private" — это как раз инструкция отключающая кеш на прокси. Или под "работают" ты тут имел в виду "по идее должен сам отключаться"? И ты так и не пояснил какое это отношение имеет к безопасности.

S>Ну так для 1024 ресурсов у нас будет 2048 тестов. Вам же кажется, что можно как-то обойтись 20 тестами.

S>·>Как твои виртуальные ресурсы помогут? Ну да, "GET /contragents?id=vasya" тебе запрещён, а "POST /payments?to=vasya" тебе выдаст квиток с инфой конртагента.
S>Виртуальные ресурсы помогут избавиться от иллюзии того, что данные Васи видны только тем, у кого есть привилегия "видеть данные Васи".
А откуда такая иллюзия появится в принципе особенно в случае эвфемерных вещей??
Как раз вот илюзия "запретим выдачу деталей контрагента по урлу GET /contragents — значит детали контрагента никому не будут видны без нужной привилегии" и создаётся.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 09.04.2025 13:25 · . Предыдущая версия .
Re[27]: Каких программ вам не хватает?
От: · Великобритания  
Дата: 14.04.25 10:43
Оценка: :)
Здравствуйте, Sinclair, Вы писали:

S>·>Где есть два вида? В спеке?

S>Да, прямо в спеке.
Именно. А толку? Никакой безопасности это само по себе не обеспечит. В проде у тебя работает код, а не спека. Cпека ничего не может гарантировать о реализации.

S>·>Как конкретно это гарантируется? Только не говори: "в API нету!". Не слыхал историй, когда какие-нибудь rest-endpoints случайно возвращали json с неожиданными полями. All tests passed, всё у всех работает.

S>Я вроде написал, как. Историй про то, как all tests passed, а результат не соответствует — нет, не слышал.
Ну лень гуглить, но периодически выскакивают истории типа как из сайтов авиакомпаний и продаж билетов выковыривают инфу о том кто куда летает и где живёт.

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

Очередная иллюзия у тебя. Даже если в тесте не выдаётся лишних полей, это не значит что они не выдаются.

S>·>Ну о чём и говорю. "Спроектировал" — это написал тонну word-документов и презентаций.

S>Нет конечно. "Спроектировал" — это построил фреймворк, в котором не так много возможностей накосячить. Архитектура софта не исчерпывается "внешними" требованиями.
Гы. Очередной фреймворк-всемогутер.

S>·>И проверить легко, не спорю. А на самом деле json генерится питонячим кодом, который рефлексией вываливает всё что есть.

S>Вот это ваше "На самом деле" означает, что вы пытаетесь тестировать код как чёрный ящик. Это не единственный (и не самый эффективный) способ обеспечения качества.
S>Надо смотреть внутрь, и желающих генерить всё что есть через рефлексию бить палкой на code review.
Именно. Т.е. твой "правильный API" — это каша из топора. Начал ты "нарисуем границы API — и всё безопасно", а оказывается ещё надо досыпать тестирование, ящики разных цветов, палки и review.

Ещё раз повторю мой тезис: дизайн API — это в первую очередь про то как обеспечить взаимодействие систем удобным для человеков и эффективным для железяк способом. Поэтому твой 3й способ с ссылками никуда не годится, только снижает эффективность взаимодейсвтвия, а твоё "Зато всё безопасно" — чистая иллюзия.

S>·>И то никакой гарантии, что кто-то куда-то по ошибке не скопипастит.

S>Гарантия предотвращения ошибочных копипастов достигается юнит-тестированием.
Хорошо, но уже лучше. Осталось раскрыть а причём тут вообще "API устроен именно так".

S>Преимущество тут в том, что в коде нет ветвлений — поэтому нам не надо беспокоиться, что "вдруг" в результате образуется сontragent: {homeAddress: {...}}. Достаточно 1 (одного) теста на то, что такого в json нету, и вопрос закрыт.

Тут ведь как. Либо где-то будут ветвления, либо 1024 копипасты, в которой хрен разберёшься.

S>·>В серьёзных случаях у тебя будет 1024 вида своих и чужих.

S>Это как раз в несерьёзных случаях. Серьёзные случаи — это как раз какой-нибудь банковский API. И вот там всё именно так, как я сказал. Потому что нельзя позволить ни криворукому девелоперу нечаянно проверить не ту привилегию, так и криворукому админу нечаянно выдать кому-то не ту привилегию.
Я как раз такое и видел в банковском API. Когда есть какие-то таблицы роутингов и пермишеннов. Настолько огромные, что их никто толком проверить не может. В итоге эти таблицы либо копипастятся на авось, либо генерятся скриптами, с ветвлениями. Зато статичное и проверяемое (правда в теории только).

S>·>Что значит "вынести"? Попробуй хоть как-нибудь не "вынести" какой-нибудь оракл из твоего питоячего сервиса.

S>Ну вот так и не выносим. Оракл является подробностью реализации этого "питонячьего сервиса" и ниоткуда больше не виден. Впрочем, это может быть и не оракл — "питонячьему сервису" с запасом может хватить sqlite.
Он виден с т.з. анализа безопасности.

S>·>Если у тебя два сценария, то, конечно, это щастье. А вот когда сценариев 1024...

S>Когда у вас 1024 сценария, то деваться некуда. Но чаще это означает, что кто-то не справился с факторизацией сценария, в котором есть 8 отдельных подсценариев, каждый из которых работает независимо и его можно протестировать отдельно, т.к. там вариантов гораздо меньше.
Ты почему-то с больной головы на здоровую стал перекладывать. 1024 виртуальных ресурса предложил ты, так что 1024 сценария это у вас. А я как раз писал: "Каждую комбинацию тестировать не нужно. Нужно тестировать каждую привелегию." С чем ты тут же стал спорить. Ты уж определись.

S>·>Ну будет у тебя 1024 кусков кода и неподдерживаемая кодовая база.

S>И какая альтернатива?
Написал же неделю назад: "Каждую комбинацию тестировать не нужно".

S>Прекрасно. Видна некоторая попытка факторизации. Которая, к слову, совершенно бесполезна в вашем подходе с чёрным ящиком: а вдруг завтра кто-то заменит всю вашу кунсткамеру на "питонячий код, который по рефлексии вываливает сразу всё"?

Про тестирование чёрного ящика ты придумал сам, сам и спорь.

S>Ну, и вредна конечно тоже: потому что завтра кто-то в эксплуатации не нарулит кому-то такой набор привилегий, который не даёт выполнить реальный сценарий. Зачем так делать — непонятно. Ну, кроме "нам было лень проектировать, и мы свалили ответственность на кого-то другого.

Не очень понял проблему. Если реальный сценарий не ложится на привилегии — это ошбика бизнес-требований.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[6]: Каких программ вам не хватает?
От: Константин Л. Франция  
Дата: 16.04.25 14:31
Оценка: +1
Здравствуйте, Miroff, Вы писали:

M>Здравствуйте, m2user, Вы писали:


M>>Как минимум нужно предоставить документацию на API и получить feedback


M>Прелесть RMM L3 в том, что он самодокументируемый и на 99% фидбека можно сразу отвечать: "это не RESTful, мы этого делать не будем"



RMM L3 не нужен, потому что:

1. не заменяет документацию, зато дикий оверхед
2. добавляет лишней связности — теперь я должен грузить ссылки на апи (и, судя по твоим дальнейшим постам, еще и в зависимости от пермиссий) для всех связных сущностей
3. почти всегда бесполезен, тк говорит что можно, а не что нужно — то есть протекание недоделанной (бизнес-логика на базе только доступных ссылок? ну-ну) бизнес логики туда, куда не надо
Re[10]: Каких программ вам не хватает?
От: Константин Л. Франция  
Дата: 16.04.25 14:52
Оценка: +1
Здравствуйте, Miroff, Вы писали:

M>Это же ресурс, делаешь GET, смотришь, меняешь, делаешь PUT.


PUT без параметров?

S>>2. Evolvability улучшается крайне незначительно. У нас нет никакого способа научить клиентов всегда ходить только по указанным нами ссылкам. Если мы решили перенести endpoint для рефандов в другое место, то недостаточно просто отдавать новую ссылку в links.


M>Правильно делать GET перед PUT, потому что ссылки могут измениться, и вообще конкурентные обновления. Если разработчики не умеют пользоваться REST API это их проблема. Можно тупо менять ссылки при каждом запросе, чтобы даже желания сохранять их куда либо не возникало.


а если ссылки поменялись между GET и PUT? "и вообще конкурентные обновления" — какие ужасы ты пишешь

S>>3. Накладные расходы значительно увеличиваются.


M>Я тебя умоляю, мы видео в 4К по сети гоняем и GUID вместо id используем. Несколько ссылок погоды не сделают.


я не гоняю, а ты можешь гонять свои ссылки 720p тогда раз кто-то 4k гоняет
Re[17]: Каких программ вам не хватает?
От: Константин Л. Франция  
Дата: 16.04.25 16:58
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Константин Л., Вы писали:


КЛ>>вообще не очевидно. в любом случае тебе надо сделать фильтр данных, как ты его сделал и на каком этапе не так важно.

S>Не, не в любом. Только в том, если кому-то нужны дополнительные подробности.

ну когда не нужны тогда и фильтр не нужен, верно?

КЛ>>введением магического второго ресурса проблема фильтра никуда не уйдет.


S>Я не очень понимаю, что такое "проблема фильтра". Магический второй ресурс означает, что есть два ресурса: один даже join в базе не делает с таблицами "смежных сущностей", другой делает джойн, но проверяет ровно одну пермиссию в токене, а не отдаёт 2^10 вариантов в зависимости от хидера.


фильтр — это способ либо собрать либо очистить ресурс. принципиальной разницы между виртуальными ресурсами (как в твоем случае) и одним ресурсом нет вообще. все равно где-то придется ответить на вопрос какие данные возвращаем

КЛ>>и про комбинаторный взрыв тебе правильно сказали. Номер 1 самый рабочий и адекватный — по токену получаем список пермиссий и по ним фильтруем резалтсет.

S>Ну я бы так дизайнить не стал. Соображения я привёл. У каждого они свои — вон кто-то хочет просто написать универсальный код на питоне, который через рефлексию всю базу наружу отдаёт, а пермиссии берёт из токена.

это детали, можно и в базе пермиссии проверять

S>Можно и так делать, если результат не шибко важен.


не понимаю в чем принципиальная разница с одним ресурсом и несколькими (кроме как комбинаторики)

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

S>Да, тут я согласен.

кул
Re[25]: Каких программ вам не хватает?
От: Константин Л. Франция  
Дата: 17.04.25 11:42
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

[]

S>Я вам рассказываю практический замкнутый пример: нет никаких "привилегий на втрибуты". Есть два вида ресурсов. Доступ к каждому их них либо есть, либо нету.


что значит есть? физически есть? то есть реально в базе 2 таблицы?

S>·>Каким образом закрыт-то? Заклятие наложено что-ли? Субресурс возвращает джсон, как ты ресурсом гарантируешь отстутствие там какого-нибудь contragent.homeAddress?

S>Очень просто: contragent.homeAddress там нет вообще, вне зависимости от привилегий.

кто его оттуда вырезал?

S>·>Нет, это просто несколько байт в определённом месте хедера запроса, а обрабатывает всё это дело тот же самый условно питонячий код, что и для других ресурсов.

S>Если у вас так, то всё плохо. Попробуйте перепроектировать так, чтобы в одном коде не смешивалась обработка "своих" и "чужих" инвойсов. Человечество изобрело массу способов факторизации кода.

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

S>Впрочем, можно спроектировать и так, как вы предлагаете — вынести БД в отдельный сервис, из которого торчит очень широкий контракт.


он так не предлагает

S>И, естественно, у него очень грубый набор привилегий. Ваша модель "давайте мы будем ограничивать доступ путём передачи пользовательского токена вдоль всей иерархии вызовов" работает примерно никогда.


примерно всегда так и работает

S>Все практики безопасности как раз так и устроены, что у принципала X нету привилегий к "сырому" ресурсу A, но есть привилегии на доступ к "производному" ресурсу B. Сервис, выполняющий построение ресурса B, выполняется под принципалом Y, который имеет полные привилегии для A, но учитывает привилегии X при отдаче ему производного ресурса B.


ну то есть делает именно то, что мы тут тебе и говорим, только ты все это каким-то магическим образом разрулишь всего лишь через роутинг?

S>Типичный пример применения концепции в рамках SQL99: пользователю нельзя видеть часть строк в таблице X. Мы не можем навесить привилегию на каждую строку.


почему это мы не можем?

Зато можем сделать следующее:
S>1. Отбираем у пользователя привилегии на таблицу X

зачем? только столбцы выбросить? такое работает только когда у тебя 2-3 роли в аппке и мало пермиссий

S>2. Строим на основе X представление Y, в котором добавлен предикат безопасности (типа select * from X where TotalAmount < 100000)

S>3. Выдаём пользователю привилегии на Y и указываем, что Y исполняется под привилегиями админа, а не пользователя.

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

S>Аналогично мы могли бы поступить и с ограничениями на колонки таблицы. Квадратно-гнездовая система, где чётко видна вся схема Y и легко проверить, что туда попадает, а что нет, как методом статического анализа, так и методом выполнения динамических тестов. Вы предлагаете заменить её на некий невнятный код "хранимой процедуры", которая возвращает всякий раз разный набор строк и колонок в зависимости от рантайм-содержимого параметров.


действительно, результат поискового запроса зависит от критериев поиска (пермиссии один из них внезапно), вот это дичь, да?

S>И всё это под тем предлогом, что "какая нам разница, где передаётся информация о привилегиях — всё равно это текст SQL запроса".

S>Нет, увы. Факторизация кода позволяет нам изолировать разные сценарии.

для петпроджектов да, но мы о нормальных системах говорим

S>Фрагмент в урле существует не сам по себе. Структура урла применятся для роутинга — выбора кода, который будет обслуживать поступивший запрос. Правила роутинга — простая, понятная логика, которую легко отладить и гарантировать отсутствие неожиданностей вроде "в ответ на запрос чужих инвойсов внезапно вызвался код по подготовке своих инвойсов".


а если ты внутри роутинга не туда нароутил?

S>В вашем же подходе в коде какая-то каша, отдаётся примерно произвольный набор атрибутов с соответствии с хитро устроенными предикатами, смешивающими проверку нескольких разных claims. Доказать, что код выдаёт корректное сочетание атрибутов для произвольного сочетания claims — та ещё задача.


ну это звучит как "доказать, что код выдает правильную поисковую выдачу та еще задача".
Re[26]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.04.25 12:37
Оценка: +1
Здравствуйте, Константин Л., Вы писали:

S>>Я вам рассказываю практический замкнутый пример: нет никаких "привилегий на втрибуты". Есть два вида ресурсов. Доступ к каждому их них либо есть, либо нету.

КЛ>что значит есть? физически есть? то есть реально в базе 2 таблицы?
Совершенно необязательно. В базе это может быть одна таблица, 2 таблицы, или 17 таблиц. Структура базы тут очень косвенно задействована.

КЛ>кто его оттуда вырезал?

Я не понимаю термина "вырезал". Никто никого ниоткуда не "вырезал".
Просто у нас есть такой тип данных, InboundInvoice, который отличается от OutboundInvoice.
На стороне сервиса они могут находиться в каких-то взаимоотношениях друг с другом (типа — оба отнаследованы от общей базы, или собираются путём алгебры типов из запчастей, вроде CommonInvoice & InboundInvoice / CommonInvoice & OutboundInvoice).
Снаружи мы всё равно видим только схему Json, и она разная для разных ендпоинтов.

КЛ>ты тут смешиваешь свои и чужие инвойсы, чтобы навести туману.

Это не я смешиваю
КЛ>давай мы будем всегда про свои инвойсы, но в одном случае для отчетности, в другом для превью — как хранить будешь и разделять?
Я не буду их разделять — зачем? Мне непонятен сценарий. Если дадите больше деталей — можно спроектировать.
КЛ>он так не предлагает
Цитирую:

А на самом деле json генерится питонячим кодом, который рефлексией вываливает всё что есть

КЛ>примерно всегда так и работает
Поверю вам на слово.

КЛ>ну то есть делает именно то, что мы тут тебе и говорим

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

КЛ>почему это мы не можем?

Потому что row level security есть далеко не в любой СУБД. И даже в тех, где такое есть, далеко не всегда это будет наиболее эффективным решением.
КЛ>зачем? только столбцы выбросить?
И строки тоже.

КЛ>такое работает только когда у тебя 2-3 роли в аппке и мало пермиссий

Такое работает примерно всегда. Я ещё ни разу не видел настолько безумной архитектуры, чтобы SQL исполнялся в контексте безопасности конечного пользователя, пришедшего из интернета.

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

"Его" — это кого? Поле?

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

Можете привести пример такого select? Я вроде понимаю, о чём вы пишете, но уверенности нет.

КЛ>а ведь еще ничего не сказано про ABAC, который часто нужен и который в твою схему вообще не вписывается

Да, для ABAC нужна другая схема. Но он очень часто является оверкиллом.

КЛ>действительно, результат поискового запроса зависит от критериев поиска (пермиссии один из них внезапно), вот это дичь, да?

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

КЛ>для петпроджектов да, но мы о нормальных системах говорим

Ну, критерии "нормальных систем" у всех разные.

КЛ>а если ты внутри роутинга не туда нароутил?

То это будет обнаружено первым же smoke test.

КЛ>ну это звучит как "доказать, что код выдает правильную поисковую выдачу та еще задача".

Конечно. Это вполне актуальная проблема; и основное её решение ровно то же, что я предлагаю — факторизация. Потому что иначе вы точно так же утонете в объёме тестирования.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[27]: Каких программ вам не хватает?
От: Константин Л. Франция  
Дата: 17.04.25 15:07
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

S>Снаружи мы всё равно видим только схему Json, и она разная для разных ендпоинтов.


и как и откуда в эту схему кладутся данные?

я, кажется, начинаю понимать — по dto на роль, ORM, отдельные endpoints и вуаля? но тут есть 2 проблемы — работает только на простых security моделях, и никак не решает проблем, когда внутри этого dto есть многокардинальные поля (массивы etc, которые тоже надо фильтровать по роли).


ну есть еще конечно другой вариант — когда очень много денег и очень много ответственности и надо прям все по-красоте. но это не индустриальный стандарт

КЛ>>ты тут смешиваешь свои и чужие инвойсы, чтобы навести туману.

S>Это не я смешиваю


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

S>Я не буду их разделять — зачем? Мне непонятен сценарий. Если дадите больше деталей — можно спроектировать.
КЛ>>он так не предлагает

мне кажется он специально преувеличил, но не суть

S>Цитирую:

S>

S>А на самом деле json генерится питонячим кодом, который рефлексией вываливает всё что есть



КЛ>>ну то есть делает именно то, что мы тут тебе и говорим

S>Нет, делает ровно противоположное. Более того, прямо тут в топике приводились утверждения про то, что "на самом деле" микросервисы не только пользовательских принципалов не используют, а вообще бегают все под одним и тем же аккаунтом.

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

КЛ>>почему это мы не можем?

S>Потому что row level security есть далеко не в любой СУБД. И даже в тех, где такое есть, далеко не всегда это будет наиболее эффективным решением.

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

КЛ>>зачем? только столбцы выбросить?

S>И строки тоже.

так у вас нет row-level permission же

КЛ>>такое работает только когда у тебя 2-3 роли в аппке и мало пермиссий


S>Такое работает примерно всегда. Я ещё ни разу не видел настолько безумной архитектуры, чтобы SQL исполнялся в контексте безопасности конечного пользователя, пришедшего из интернета.


" SQL исполнялся в контексте безопасности конечного пользователя " — вот это вообще что такое? что тут ты понимаешь под контекстом? а когда ты делаешь эти свои лишние телодвижения из 3х пунктов, ты разве не мапишь "контексте безопасности конечного пользователя, пришедшего из интернета" на конкретную роль в базе?

sql исполняется от админа всегда и точка. резалсеты зависят от пермиссий юзера из интернета.

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

S>"Его" — это кого? Поле?

строку, опечатка конечно

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

S>Можете привести пример такого select? Я вроде понимаю, о чём вы пишете, но уверенности нет.

select * from rows r
join rows_perms p on r.id = p.r_id
where p.perm = 'row_read' and p.user_id = :userid

или

select * from rows r where r.group_id in :user_groups

userid/user_groups резолвятся по токену из запроса

да как угодно, при том, что работает тот самый швейцарский сыр, про который тут упоминали —
возможность вообще что-то читать из таблицы rows проверяется до отправки sql в базу. все запросы от админа. в базе никакой встроенной security не используется, потому что, опять же, нет нормально row-level security встроенного. С полями — либо динамически генеришь строку sql, либо jooq (предпочтительнее)

select fields from field_perm where field_perm.perm = 'row_read_for_report'

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


КЛ>>а ведь еще ничего не сказано про ABAC, который часто нужен и который в твою схему вообще не вписывается

S>Да, для ABAC нужна другая схема. Но он очень часто является оверкиллом.

ABAC, это когда ты принимаешь решение не только от роли, но и контекста — времени запроса и пт. То есть довольно часто.

КЛ>>действительно, результат поискового запроса зависит от критериев поиска (пермиссии один из них внезапно), вот это дичь, да?

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

да, но ничего с точки зрения трейдоффа разработка/результат не придумали. открываешь google aim и видишь и роли, и отдельные пермиссии.

КЛ>>для петпроджектов да, но мы о нормальных системах говорим

S>Ну, критерии "нормальных систем" у всех разные.

много ролей, много разных пермиссий

КЛ>>а если ты внутри роутинга не туда нароутил?

S>То это будет обнаружено первым же smoke test.

ага, то есть любой смоук тест у нас в лобой системе обнаруживает любую проблему?

КЛ>>ну это звучит как "доказать, что код выдает правильную поисковую выдачу та еще задача".

S>Конечно. Это вполне актуальная проблема; и основное её решение ровно то же, что я предлагаю — факторизация. Потому что иначе вы точно так же утонете в объёме тестирования.

и никто ее не делает, потому что это невозможно поддерживать
Отредактировано 17.04.2025 15:24 Константин Л. . Предыдущая версия .
Re[13]: Каких программ вам не хватает?
От: Miroff Россия  
Дата: 18.04.25 14:03
Оценка: +1
Здравствуйте, Константин Л., Вы писали:

КЛ>это ты какой-то очень простой crud описываешь


Именно! В этом и смысл REST, выражать сложную логику через очень простой CRUD
Помогите правильно спроектировать микросервисное приложение
От: busk  
Дата: 20.03.25 14:46
Оценка:
Привет всем.
Как-то только в теории читал про микросервисы, но вот новый проект планируется небольшой и хотел как раз попробовать микросервисы тут.

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


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

Приложение: — Система контроля доставок грузов в разных странах (стран 10).
— Юзеры заходят по user/pswd и система определяет страну и подгружает данные этой страны. Новый юзер сам может зарегаться по логину выданному ему и восстановить пароль.
— В системе будет 4 роли: sysadmin, admin, manager, driver. В каждой стране свои пользователи. Один пользователь = 1 страна.
— Сами заказы поступают в эту систему из другой. В этой надо только мониторить и делать разные действия если доставка задержалась или не приехала.
— В каждой стране много складов и поэтому когда заказы поступают в систему то они сразу попадают на нужный склад и спец алгоритм распределяет на водителей.

— sysadmin управляет только техническими настройками разными (кому когда отчеты отсылать, как в системе заводить оптуска, сколько часов в сутки можно работать, заводит праздники), остальное всё только в режиме просмотра видит.
— admin видит всё, не может только технические настройки менять. Следит за водителями, чтобы они всрок доставляли всё — по юаю специальному, вносит отпуска, больничные их, ставит им рабочее время. Если водитель увольняется — удаляет изи системы.
— manager следит за водителями своего склада только, может посмотреть по всем своим водителям информацию и по всем доставкам, но менять не может
— driver видит только по себе все сделанные доставки и предстоящие. Каждый раз когда он начинает и заканчивает доставку то в системе нажимает Start delivery\End delivery. Если доставка не укладывается в
предполагаемые сроки то пишет к доставке комментарий почему не успел


Итого что по функционалу:
Sysadmin — логин в систему, управление настройками, праздниками и просмотр всего.
Admin — логин в систему, cледит за водителями, чтобы они всрок доставляли всё, вносит отпуска, больничные их, ставит им рабочее время. Если водитель увольняется — удаляет изи системы.
Manager логин в систему, следит за водителями своего склада только, может посмотреть по всем своим водителям информацию и по всем доставкам
Driver логин в систему, видит только по себе все сделанные доставки и предстоящие. Каждый раз когда он начинает и заканчивает доставку то в системе нажимает Start delivery\End delivery. Если доставка не укладывается в
предполагаемые сроки то пишет к доставке комментарий почему не успел


Третий вопрос. Если без докеров то как настроить этот набор микросервисов? тут их немного будет и читал что можно настроить без докер контейнеров если что.
Re[2]: Помогите правильно спроектировать микросервисное приложение
От: busk  
Дата: 20.03.25 15:34
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Здравствуйте, busk, Вы писали:


B>>Как-то только в теории читал про микросервисы, но вот новый проект планируется небольшой и хотел как раз попробовать микросервисы тут.

G>Не надо, оно тебя сожрет

поясни пожалуйста подробней. а то смотришь тот же Яндекс, у них везде микросервисы + ci/cd
Re[2]: Помогите правильно спроектировать микросервисное приложение
От: busk  
Дата: 21.03.25 04:18
Оценка:
Здравствуйте, Miroff, Вы писали:

M>Здравствуйте, busk, Вы писали:


B>>Тут я понимаю, что проще было бы сделать монолит, но для обучения вполне годный вариант?


M>А у вас ресурсы-то на микросервисы есть? На тот же K8S и CI/CD хотя бы.


я планировал без кубера, читал так можно. Ниже написал модель какую думал. ci/cd у нас есть на другом сервере и думал туда добавить билд нового проекта.
а кубер реально много ресурсов требует дополнительно? я думал он просто как failover service


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


M>Это самое простое. Делить нужно по бизнес-домену (мыши и кактусы отдельно, марксизм и диамат отдельно), по технологиям (ML на питоне, интеграция с внешними сервисами на Scala, интерфейс к БД на сишарпе), требованиям к масштабированию (фронтофисом пользуется вся страна, а бэкофисом 20 человек), надежности (если отчеты упадут об этом узнают через месяц, а если торговый робот упадет, компания обанкротится за 5 минут). Если ничего этого нет, микросервисы не нужны.


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

B>>Третий вопрос. Если без докеров то как настроить этот набор микросервисов? тут их немного будет и читал что можно настроить без докер контейнеров если что.


M>Можно, только это очень дорого и даже Яндекс себе такого не может позволить.


а почему дорого? я так понял просто каждый сервис — отдельный апп в веб сервере и есть шлюз приложение которое регулирует и каждая база на свой сервис.
Re[2]: Помогите правильно спроектировать микросервисное приложение
От: busk  
Дата: 21.03.25 04:37
Оценка:
Здравствуйте, DiPaolo, Вы писали:

DP>Выглядит так, что тут вкореживать (именно так) микросервисы – дороже выйдет. Ну вообще никак они тут не просматриваются. Очень маленький набор сущностей и функционала. Элементарно нечего пилить


DP>Опять же, если это все без кубера делать, то жди беды и геморроя Так что не стоит


DP>Потренироваться можно на пет-проекте. Самому придумать и написать что-то несложное. Один микросервис отдает погоду, второй загруженность дорог. Третий все это забирает и что-то отдает наружу. Плюс отдельный микросервис принимают от пользователей какие-то данные. Тут же добавить кэши, обратный прокси. можно потом с лоад балансером поиграться. Каждый сервис пусть по базе имеет. Сделать несколько инстансов каждого микросервиса. Ну и так далее...


DP>Тогда может и будет понимание, где надо (и зачем!), а где не надо впихивать микросервисы. Ну и про кубер придет понимание, что этим зоопарком баз и сервисов как-то надо рулить. И как замечательно можно скейлить отдельные куски системы по необходимости


Понял, спасибо. Монолит тогда сделаю.

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

дополнительно. Еще будет 3 сервиса на питоне: один будет из 1с качать информацию по отпускам, болничным, один будет также из 1с качать новых сотрудников.

я правильно понимаю: сервис аутенфикации, сервис получения заказов со статусами по дням, сервис настроек и сервис сотрудников (где можно им выставлять рабочее время, заводить отгулы, удалять их если они уволились)
Re[3]: Помогите правильно спроектировать микросервисное приложение
От: DiPaolo Россия  
Дата: 21.03.25 05:11
Оценка:
B>А так вот, чисто для развития и понимания в реальных приложениях, подскажи пожалуйста как тут нарезать сервисы?
Да вот именно, что сложно их как-то нарезать. Как коллега правильно заметил, есть несколько вариантов нарезки, и ни один из них сюда не подходит.

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

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

B>дополнительно. Еще будет 3 сервиса на питоне: один будет из 1с качать информацию по отпускам, болничным, один будет также из 1с качать новых сотрудников.


Все что с 1С лучше вынести в один сервис (адаптер для интеграции со сторонним сервисом). Тем самым вся логика работы с конкретной сторонней системой будет сосредоточена в одном месте и будет инкапсулировать все что касается работы с этим сервисом. А наружу давать уже обработанные данные в форматах и сущностях, с коротким работает ваша система.

B>я правильно понимаю: сервис аутенфикации, сервис получения заказов со статусами по дням, сервис настроек и сервис сотрудников (где можно им выставлять рабочее время, заводить отгулы, удалять их если они уволились)


Я бы сделал так:
— основной бэк (заказы, настройки, сотрудники)
— сервис аутентификации (в вашем случае это тоже лишнее — выносить в отдельный микросервис; но пусть, так часто делают, когда микросервисов много и/или есть SSO)
— сервис для работы с 1С
Патриот здравого смысла
Re: Помогите правильно спроектировать микросервисное приложение
От: DiPaolo Россия  
Дата: 21.03.25 05:17
Оценка:
B>Третий вопрос. Если без докеров то как настроить этот набор микросервисов? тут их немного будет и читал что можно настроить без докер контейнеров если что.

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

Сделать можно так: скрипт, который запускает все сервисы + СУБД должна быть запущена (ее проще всего поднять в докере как раз) и базы созданы.

При этом надо продумать: а как определять, что тот или иной сервис упал/недоступен?

Далее, если понадобится вторая машина, тут встанет тоже вопрос, как с этим управляться.

Ну и дальше будет постепенно приходить понимание, зачем кубер и прочее.

Кстати, кубер сразу не стоит брать. Достаточно будет привнести докеры, а потом Docker compose. Этого хватит. А уже потом – кубер.
Патриот здравого смысла
Re[2]: Помогите правильно спроектировать микросервисное приложение
От: busk  
Дата: 21.03.25 07:32
Оценка:
Здравствуйте, DiPaolo, Вы писали:

B>>Третий вопрос. Если без докеров то как настроить этот набор микросервисов? тут их немного будет и читал что можно настроить без докер контейнеров если что.


DP>Что касается докера и кубера... это хорошая идея – начать без них. Тогда чуть позже придет понимание исходя из реальных потребностей, зачем один и второй нужен.



а я кстати тут вот понял, что без кубера и докера у меня бы точно были проблемы. Читал, что вроде нормально это всё под линухом работает.
а у меня на проде венда + mssql.

За советы спасибо!

видимо, да, домашний проект надо под линукс + postrges
Re[4]: Помогите правильно спроектировать микросервисное приложение
От: busk  
Дата: 21.03.25 08:25
Оценка:
Здравствуйте, gandjustas, Вы писали:


G>2) яндекс на старте не был микросервисным


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

G>3) cd\cd без микросервисов работает лучше


звучит что микросервисы удел либо больших компаний либо крупных систем.
Re[3]: Помогите правильно спроектировать микросервисное приложение
От: Miroff Россия  
Дата: 21.03.25 11:23
Оценка:
Здравствуйте, busk, Вы писали:

B>я планировал без кубера, читал так можно. Ниже написал модель какую думал. ci/cd у нас есть на другом сервере и думал туда добавить билд нового проекта.


Можно, но микросервисы плохо работают без полноценного CD. Релизить руками умаешься.

B>а кубер реально много ресурсов требует дополнительно? я думал он просто как failover service


Ресурсов в смысле админа, который умеет k8s поднять и способен его настроить. Там же не один k8s, а еще сбор логов, CD пайплайны, мониторинг и т.п.

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


Микросервисы позволяют пернести часть сложности из приложения в оркестрацию. Это сильно упрощает разработку, когда у тебя в сервисе меньше 10к строк и один разработчик. Нет ни мердж конфликтов, не нужно ни с кем договариваться, не нужна документация, планирование, архитектура. Выставляешь Restful API и проблема других сервисов как этим API воспользоваться. Если в проекте энфорсится RMM level 3 и стопроцентная обратная совместимость, можно делать проекты на 1000 человеко-лет с минимальным оверхедом. За это приходится расплачиваться необходимостью контроллировать сложность взаимодействия. Вплоть до экономических механизмов, когда каждая команда платит за ресурсы потребленные их микросервисами в облаке.

B>а почему дорого?


Потому что k8s и docker сейчас умеют даже студенты, а для рукопашного CD нужны крайне продвинутые админы, умеющего автоматизировать развертывание каким-нибудь Chef или Puppet. Даже когда Chef был на пике моды, таких были единицы.

B>я так понял просто каждый сервис — отдельный апп в веб сервере и есть шлюз приложение которое регулирует и каждая база на свой

сервис.

Тогда не получится ни масштабирования, ни rolling updates без даунтайма, ни надежности. Непонятно зачем тогда вообще микросервисы?
Re: Помогите правильно спроектировать микросервисное приложение
От: Qulac Россия  
Дата: 21.03.25 12:43
Оценка:
Здравствуйте, busk, Вы писали:

B>Привет всем.

B>Как-то только в теории читал про микросервисы, но вот новый проект планируется небольшой и хотел как раз попробовать микросервисы тут.

Я потренировался бы сначала, прежде чем делать реальный проект на микросервисах или в крайнем случае вывел бы в сервисы какую ни будь не критичную часть функционала, типа хранения разных типов уведомлений для пользователей.
Программа – это мысли спрессованные в код
Re: Помогите правильно спроектировать микросервисное приложение
От: SkyDance Земля  
Дата: 21.03.25 17:09
Оценка:
B>самое сложное это определить границы сервисов. Вот прошу тут помощи как нарезать на сервисы и базы?

Это как раз самое простое. Границы определяются orgchart — "организационной диаграммой". Иными словами, разделением ответственности по принципу "если это делает другая команда, это другой сервис".

Все остальные разделения рано или поздно скатятся во все ту же диаграмму подчинения.

PS: не видел еще ни одного продукта с микросервисной архитектурой который бы не скатился именно в этот принцип разделения. Во многих случаях разделение идет дальше (вплоть до того, что каждому программисту — по микросервису, а то и два-три), но в этом случае нередок обратный процесс помещения нескольких микросервисов внутрь единого огромного бинарника (привет фейсбуку).
Re: Помогите правильно спроектировать микросервисное приложение
От: L_G Россия  
Дата: 22.03.25 13:17
Оценка:
Даже подразумевая, что всё это делается лишь для тренировки/обучения и не более —
больше, чем на две базы данных описанное разделить крайне трудно. Получается 1) аутентификация и авторизация 2) всё остальное.
Тем более, сервис аутентификации и авторизации вполне логично сделать централизованным (общим на весь корпоративный зоопарк приложений).
А сервисов больше, чем баз делать может иметь смысл только когда их реально делают разные команды (я не про экземпляры одинаковых).
Думаю, и 2 сервисов должно вполне хватить для отработки основных навыков.
Каша в голове — пища для ума (с)
Re[3]: Помогите правильно спроектировать микросервисное приложение
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 23.03.25 03:01
Оценка:
Здравствуйте, busk, Вы писали:

G>>Не надо, оно тебя сожрет


B>поясни пожалуйста подробней. а то смотришь тот же Яндекс, у них везде микросервисы + ci/cd


В том же яндексе в каждом микросервисе ад и Израиль, оно тебе надо?
Маньяк Робокряк колесит по городу
Re[5]: Помогите правильно спроектировать микросервисное приложение
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 23.03.25 03:04
Оценка:
Здравствуйте, busk, Вы писали:

B>звучит что микросервисы удел либо больших компаний либо крупных систем.


Монолит в одно жало/одной командой пилить гораздо проще.

Когда дорастёшь до того, что начнут возникать проблемы с монолитом — ты уже будешь нанимать программистов по 500 рублей и на архитектуру (монолит/микросервисы) тебе уже будет начхать
Маньяк Робокряк колесит по городу
Re[3]: Помогите правильно спроектировать микросервисное приложение
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 23.03.25 03:08
Оценка:
Здравствуйте, busk, Вы писали:

B>а я кстати тут вот понял, что без кубера и докера у меня бы точно были проблемы. Читал, что вроде нормально это всё под линухом работает.

B>а у меня на проде венда + mssql.

Докер под виндой десяткой вроде работает без проблем
Маньяк Робокряк колесит по городу
Re[4]: Помогите правильно спроектировать микросервисное приложение
От: m2user  
Дата: 23.03.25 07:31
Оценка:
M>Это сильно упрощает разработку, когда у тебя в сервисе меньше 10к строк и один разработчик.
M>Нет ни мердж конфликтов,

+1

M>не нужно ни с кем договариваться, не нужна документация,


Как минимум нужно предоставить документацию на API и получить feedback

M> планирование, архитектура.


слабо верится, и над архитектурой нужно тоже думать, и планировать (хотя бы по срокам имплементации этого самого API)

M> За это приходится расплачиваться необходимостью контроллировать сложность взаимодействия. Вплоть до экономических механизмов, когда каждая команда платит за ресурсы потребленные их микросервисами в облаке.


Так это вроде и без микросервисов всегда так было. Есть проблемы с производительностью — отвечает автор кода, являющегося узким местом.
Re[5]: Каких программ вам не хватает?
От: Miroff Россия  
Дата: 24.03.25 14:35
Оценка:
Здравствуйте, m2user, Вы писали:

M>Как минимум нужно предоставить документацию на API и получить feedback


Прелесть RMM L3 в том, что он самодокументируемый и на 99% фидбека можно сразу отвечать: "это не RESTful, мы этого делать не будем"

M>слабо верится, и над архитектурой нужно тоже думать, и планировать (хотя бы по срокам имплементации этого самого API)


Так RMM L3 однозначный, там не над чем думать. Размышлений требует дефиниция ресурсов, но она в 90% случаев типовая и там опять же думать не над чем.

M>Так это вроде и без микросервисов всегда так было. Есть проблемы с производительностью — отвечает автор кода, являющегося узким местом.


Это вопрос не производительности, а потребляемых ресурсов. Микросервис суперпросто поднять, но суперсложно удалить. Например, компания, которая ввела внутренний биллинг, обнаружила себя тратящей несколько десятков миллионов в месяц на порядка тысячи микросервисов, которые непонятно кто и с какой целью поднял. Причем административными средствами проблема не решалась, потому что всегда оказывалось что микросервис поднял Вася пять лет назад для проекта X и за 5 лет Вася уволился, проект X влили в проект Y, который заменили на проект Z, в процессе два раза сменив команду и три раза сделав пивот на 180 градусов. И теперь концов уже не найти, нужен ли этот сервис СЕЙЧАС и если нужен, то ДЛЯ ЧЕГО.
Re[6]: Каких программ вам не хватает?
От: RushDevion Россия  
Дата: 24.03.25 18:32
Оценка:
M>Прелесть RMM L3 в том, что он самодокументируемый и на 99% фидбека можно сразу отвечать: "это не RESTful, мы этого делать не будем"

Чисто для общего развития.
RMM L3 — это когда, получив первый ресурс, мы по link/rel определяем, что с ним дальше можно сделать (и на какие url слать соответствующие запросы), так ведь?

Можно пример какого-нибудь публичного REST API, которое именно классический RMM L3 (т.е. не Graph QL и т.п.)?

Просто в моей микросервисной практике все попытки внедрить hypermedia в конечном итоге скатывались либо в полноценную Open API/Swagger спеку, либо в Graph QL, либо в текстовую документацию.
Отредактировано 24.03.2025 21:02 RushDevion . Предыдущая версия . Еще …
Отредактировано 24.03.2025 18:49 RushDevion . Предыдущая версия .
Re[7]: Каких программ вам не хватает?
От: Miroff Россия  
Дата: 25.03.25 01:30
Оценка:
Здравствуйте, RushDevion, Вы писали:

RD>RMM L3 — это когда, получив первый ресурс, мы по link/rel определяем, что с ним дальше можно сделать (и на какие url слать соответствующие запросы), так ведь?


Да, но не только. Это как с третьей нормальной формой, RMM L3, это RMM L2 + HATEOAS. В первую очередь хорошее API обеспечивается правильным разделением на ресурсы, с которыми можно оперировать с помощью HTTP глаголов. HATEOAS на это просто очень удачно ложится и позволяет не размывать логику между клиентом и сервером.

RD>Можно пример какого-нибудь публичного REST API, которое именно классический RMM L3 (т.е. не Graph QL и т.п.)?


PayPal API

RD>Просто в моей микросервисной практике все попытки внедрить hypermedia в конечном итоге скатывались либо в полноценную Open API/Swagger спеку, либо в Graph QL, либо в текстовую документацию.


HATEOAS не отменяет сваггера. Все равно нужно описывать семантику полей и действий.
Re: Помогите правильно спроектировать микросервисное приложение
От: cppguard  
Дата: 25.03.25 08:58
Оценка:
Здравствуйте, busk, Вы писали:

B>Привет всем.

B>Как-то только в теории читал про микросервисы, но вот новый проект планируется небольшой и хотел как раз попробовать микросервисы тут.

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

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


Я бы начал с ответа на вопрос: зачем вообще тебе микросервисы? Просто попробовать или действительно есть нужда? Просто пробовать на боевом проекте это почти всегда или фиаско, или бессонные ночи. Иногда сразу оба варианта В моём случае я оба раза выбирал микросервисы по прочине нехватки ресурсов для реализации всего функционала. Но не надо путать с нехваткой ресурсов для написания микросервисов как таковых — что монолит, что микросервисы потребовали бы целой команды, а я был один. Поэтому я разбил проект на непересекающиеся модули и для каждого использовал фреймворк или библиотеку, которая на старте давала 80% функционала из коробки. Например, нужен обыкновыенний CRUD? — Берём сразу Rail и не думаем. Илитных икспертов, которые расскажут, что Ruby медленный, посылаем в /dev/null — современный Ruby можно горизонтально масштабировать, а выигрышь от ускорения за счёт использования другого языка никогда не окупит время разработки эквивалентного функционала на этом языке. Теперь помимо CRUD нужно добавить возможность запускать процессы (например, мы пишем свой godbolt), изолировать их и контролировать. Отлично! Используем systemd для запуска процессов, а контроль осуществим через DBus. И как круто, что есть возможность генерировать интерфейсы классов на Python для DBus — не нужно руками прописывать вызовы API! Теперь у нас есть Ruby и Python. Просто связываем их через БД (вообще любая подойдёт). И вот у нас уже микросервисы. А если пойти дальше, то выяснится, что пресловутые микросервисы это REST гипертрофированный до размера операционной системы — состояние хранится где-то на диске (или в памяти в особо тяжёлых случаях), вызовы происходят через сервисы, а корректность состояния осуществляется через блокировки хранилища. Другого пока не придумали. Сложности и ошибки возникают, когда какой-то smart ass, решает, что он очень уж smart и пытается вынести контроль целостности данных с уровня хранилища на уровень приложения. Не надо так делать, и всё будет хорошо. И не надо бояться использовать разные языки. Лично я не понимаю, какой вообще смысл микросервисов, если мы всё пишем на одном языке? Теряется вся гибкость, всё преимущество возможности стоять на плечах гигантов и использовать готовые решения.

B>Третий вопрос. Если без докеров то как настроить этот набор микросервисов? тут их немного будет и читал что можно настроить без докер контейнеров если что.


Это вообще ортогональный вопрос. Контейнеры и микросервисы никак не связаны, но контейнеры позволяют изолировать многие процессы, в том числе и процесс выкатывания обновлений. Если, например, сервис это .exe то вообще никакой выгоды от контейнеров. Ну и при горизонтальном масштабировании не приходится настраивать систему с нуля. Но если не нравится докер, то есть контейнеры systemd, если lxc — выбирай на свой вкус.

Резюме: 80% написанного в личных блогах про микросервисы это каргокульт, можно не читать. Микросервисы это вообще обыкновенная архитектура — 100% современных автомобилей используют микросервисную архитектуру ещё с нулевых, не нужно её бояться. Купи книгу с кабанчиком (Клепман) и прочти её три раза.
Re[2]: Помогите правильно спроектировать микросервисное приложение
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 25.03.25 09:54
Оценка:
Здравствуйте, cppguard, Вы писали:

C>Так, во-первых не слушай старых пердунов (ну, или молодых смузихлёбов , утверждающих, что для микросервисной архитектуры нужны большие ресурсы. Я целых два(!!!) раза успешно реализовывал микросервисы в одиночку.

Мы все видели твои решения в некоторых разделах. Что ты там успешно напроектировал и реализовал — большой вопрос .
Sic luceat lux!
Re[2]: Помогите правильно спроектировать микросервисное приложение
От: TG  
Дата: 25.03.25 12:58
Оценка:
Здравствуйте, cppguard, Вы писали:

C>Я бы начал с ответа на вопрос: зачем вообще тебе микросервисы?

Дайте своё определение микросервисов.

C>А если пойти дальше, то выяснится, что пресловутые микросервисы это REST гипертрофированный до размера операционной системы — состояние хранится где-то на диске (или в памяти в особо тяжёлых случаях), вызовы происходят через сервисы, а корректность состояния осуществляется через блокировки хранилища.

Это Вы Кафку и прочие MQ REST-ом обозвали? Зачем?

C>Купи книгу с кабанчиком (Клепман) и прочти её три раза.

"Кабанчик" хорош, но его мало. Например, он никак не поможет определить границы сервисов.
Re[6]: Каких программ вам не хватает?
От: TG  
Дата: 25.03.25 13:01
Оценка:
Здравствуйте, Miroff, Вы писали:

M>Это вопрос не производительности, а потребляемых ресурсов. Микросервис суперпросто поднять, но суперсложно удалить. Например, компания, которая ввела внутренний биллинг, обнаружила себя тратящей несколько десятков миллионов в месяц на порядка тысячи микросервисов, которые непонятно кто и с какой целью поднял. Причем административными средствами проблема не решалась, потому что всегда оказывалось что микросервис поднял Вася пять лет назад для проекта X и за 5 лет Вася уволился, проект X влили в проект Y, который заменили на проект Z, в процессе два раза сменив команду и три раза сделав пивот на 180 градусов. И теперь концов уже не найти, нужен ли этот сервис СЕЙЧАС и если нужен, то ДЛЯ ЧЕГО.


Как-то не очень в такое верится.
"Тысячи микросервисов" — это при инстансы или типы сервисов?
Re[2]: Помогите правильно спроектировать микросервисное приложение
От: TG  
Дата: 25.03.25 13:06
Оценка:
Здравствуйте, Sinclair, Вы писали:

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

S>Вот это — плохая идея: получите все недостатки МСА без её достоинств. Да, список пользователей будет дублироваться. Да, на это придётся потратить немножко усилий. Но на самом деле всё не так уж и плохо — в том смысле, что, к примеру, настоящее имя пользователя и его дата рождения хранится только в одной системе, а какие-нибудь данные о его трудовой биографии — в другой. Дублирования не так уж и много; основное затруднение — невозможность контролировать ссылочную целостность. У вас всегда будет риск получить в четырёх базах "подвисшие" записи для пользователей, логин которых был забанен в 0м сервисе навсегда. Уборка мусора становится отдельной maintenance задачей.

Для таких вещей надо делать сервис реконсиляции.
С последующим ручным (скорее всего) разбором и разрешением коллизий.
Re[3]: Помогите правильно спроектировать микросервисное приложение
От: cppguard  
Дата: 25.03.25 13:16
Оценка:
Здравствуйте, Kernan, Вы писали:

K>Мы все видели твои решения в некоторых разделах. Что ты там успешно напроектировал и реализовал — большой вопрос .


Очень большой вопрос, но за это платили деньги и просили продолжать работать. Для меня это критерий успешности
Re[3]: Помогите правильно спроектировать микросервисное приложение
От: cppguard  
Дата: 25.03.25 13:51
Оценка:
Здравствуйте, TG, Вы писали:

C>>Я бы начал с ответа на вопрос: зачем вообще тебе микросервисы?

TG>Дайте своё определение микросервисов.

Зачем?

TG>Это Вы Кафку и прочие MQ REST-ом обозвали? Зачем?


Ну, это было очень грубое сравнение. Просто мало людей понимают, что есть данные и есть код, и код изменяет данные. И можно придумывать велосипед снова и снова и говорить про принципиально новые подходы к разработке, но суть меняется мало. Например, возьмём понолит, реализуем ключевые функции через динамические библиотеки, реализуем механизм горячего обновления функций при измении соответствующего файла библиотеки — опа! У нас получилась микросервисная архитектура. Или не микросервисная — как посмотреть. Я работал в разных проектах — от социальных сетей до роботов, и везде было одно и то же: код, данные, шины обмена данными, интерфейсы взаимодейсвтия. И когда начинают сраться по поводу микросервисов и монолитов, я в упор не понимаю, в чём реально принципиальная разница? Если открыть произвольную статью про проблемы микросервисов, то 99% нытья сведётся к тому, что архитектура получилась слабосвязная, валидации никакой нет, поэтому команды каждый день ломают друг другу совместимость. Но это норма. Когда-то срались по поводу REST vs. XML RPC (хотя это ложная дихотомия, одно не отменяет другого), потом конечно же RPC вернулся в виде gRCP и Thrift, только об этом стыдливо умолчали, ведь сколько людей было унижено на собеседовании вопросами об абсолютном доминировании REST.

TG>"Кабанчик" хорош, но его мало. Например, он никак не поможет определить границы сервисов.


Что посоветуете почитать? Выбор зоны ответственности сервиса это вопрос, выходящий далеко за рамки темы микросервисов. Детское автомобильное кресло это категория "товары для детей" или "автоаксессуары"? Вот и с сервисами так же. У меня недостаточно опыта работы в кровавом энтерпрайзе, чтобы дискутировать на эту тему, хотя даже за его пределами приходится решать эту проблему. Вот прямо сейчас нужно понять, данные с лидара нужно слать в сыром виде по шине, а другой сервис будет заниматься обработкой, или же всё делать в рамках одного сервиса? В первом случае возникает нагрузка на шину, во втором случае — нагрузка на вычислительный узел. Пока что решение — вынести вообще всю систему восприятия робота в отдельную подсистему, но там свои нюансы.
Re[7]: Помогите правильно спроектировать микросервисное приложение
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 25.03.25 15:02
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, gandjustas, Вы писали:


G>>В этом случае может быть выгодно иметь микросервисы как раз по границам команд. Других адекватных причин использовать MSA я не видел.


S>Ну ещё ограничить failure domain. Чтобы бага в одном углу приложения клала его не целиком, а только блокировала отдельные сценарии.


В managed среда это можно и без микросервисов сделать. А даже в случае unmanaged можно разделить по процессам и использовать unix-sockets\named-pipes для общения между ними в рамках одного сервера, обеспечивая все взаимодействие и синхронизацию разных инстансов (серверов\контейнеров) через базу.

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

В итоге подходящая модель для MSA — где команды разделены по бизнес-доменам, где все транзакционные бизнес-процессы полностью лежат в ответственности домена. Например закупки, склад, производство, продажи, планирование. Причем это будут дольно большие домены и, соответственно, большие сервисы. Почему их называют "микро-сервисами"&
Re[8]: Помогите правильно спроектировать микросервисное приложение
От: · Великобритания  
Дата: 25.03.25 16:55
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>·>В мною виденных трейдинговых системах — везде сабж. Одна команда (~10 девов) пилит пол-сотни приложух, которые разворачивачивется в ~тысячу сервисов на десятках хостов в пятёрке датацентров.

G>·>И да, сервисы не через REST взаимодйествуют, а через pub-sub сообщения (kafka/29west/mq/fix/аналоги).
G>Я конечно тоже видел системы, где микросервисов больше чем программистов и пользователей вместе взятых, но при проверке оказывалось что все то же самое можно было бы запились в монолит с меньшими затратами, не потеряв вообще никаких потребительских качеств системы.
Охотно верю. Я лишь рассказал о типах систем, которые ты не видел. Если интересно и есть вопросы, спрашивай.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[12]: Помогите правильно спроектировать микросервисное приложение
От: · Великобритания  
Дата: 02.04.25 11:21
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>>>Я говорю о том, что вручную выстроенная модульность внутри приложения, на уровне отсутствия ссылок из группы объектов, поддерживается самой managed средой. Без использования ансейфа и разделяемых данных без должной осмотрительности крайне сложно в managed среде во время обработки одного запроса нарушить работу кода, обрабатывающего другие запросы.

G>·>Гы. Как минимум, память и gc — разделяемые. Так что когда запрос какого-нибудь отчёта для аналитики вдруг роняет по OOM всё сразу, в т.ч. обработку заказов — ничего хорошего.
G>Ничего не мешает в рамках монолитного решения вынести отдельный инстанс для обработки тяжелых запросов и на уровне балансера распределять.
Видимо ты тут намекаешь на какую-то принципиальную разницу между SOA и MSA?
Ещё почему-то ты предполагаешь что есть некий один универсальный балансер. А в приложухе может быть REST для аналитики, FIX для заказов и т.п.

G>Еще раз повторю тезис: MSA это больше про оргструктуру и следующие за ней технические решения.

По-моему, ты причину со следствием путаешь.

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

А зачем обязательно один бинарник? Если деплоймент разный всё равно. Чтобы были многочасовые билды?
Сборка, деплой и перезапуск мелкого сервиса занимает минуты от момента мержа PR. Тогда как типичная выкатка монолита — приятно проведённые выходные.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[11]: Помогите правильно спроектировать микросервисное приложение
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 02.04.25 22:01
Оценка:
Здравствуйте, Sinclair, Вы писали:

G>>А давай прикинем как это будет в MSA. там будет точно такая же коллекция в одном из сервисов, и менять её будет не поток, порожденный программистом, а поток порожденный хостом для обработки запроса. А все остальное будет то же самое. И, как в случае монолитного приложения, так и в случае MSA падения как такового не будет. Восстановление после такого falure возможно только сбросом состояния путем насильного перезапуска, например по хелсчеку. Разница в случае MSA будет только в том, что будет перезапущен один маленький сервис, а не толстое приложение. Но при этом весь сценарий работать не будет, пока микросервис с разделяемой коллекцией в памяти не оживет.

S>Всё верно. MSA не гарантирует безошибочности. MSA гарантирует, что падение не затронет сценарии, в которых микросервис не задействован.
Смотря что значит "не затронет". Если сервис А зависит от срвиса Б, а сервис Б содержит ошибку, даже неважно приводящую к падению или нет, то и А не будет корректно работать.
Падение — не самая страшная часть, даже в проде. Плохо когда: после падения не может подняться, или вместо падения не работает корректно — висит в ожидании или отдает некорректные данные. Причем второе при несинхронной разработке весьма вероятно.

G>>Надежный способ решения это использовать какое-то хранилище, которое поддерживает acid транзакции. Но это и в монолите возможно. Причем в монолите есть простор для оптимизации. Так как можно использовать STM например. Но на практике, когда экземпляров приложения может быть больше одного, все разделяемое состояние надо хранить во внешних, желательно транзакционных, хранилищах.

S>Либо отказываться от разделяемого состояния. Потому что людей, умеющих изготовить полноценное клиент-серверное приложение внутри ACID-хранилища, на рынке не осталось (даже если предположить, что они когда-то были)
Его же не надо "внутри", надо чтобы разделяемое состояние польностью сохранялось и обрабатывалось ACID хранилищем, желательно внешним по отношению к самому приложению. Чтобы приложение можно было безопасно масштабировать и перезапускать.

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

S>Вопрос открытый. Чего я только не видел в энтерпрайзе, при самых грамотных архитекторах.
Бывает конечно всякое, и архитекторы, которые не понимают как и почему базы работают. Но в целом это подход по умолчанию: "давайте состояние приложения положим в базу". Раньше по умолчанию выбирали РСУБД, но сейчас уговаривать приходится.

G>>Опять-таки MSA ничем не помогает в этом случае. Без разницы будет мусор писать в базу микросервис или монолит.

S>Нет, разница принципиальная. Микросервис физически не может записать в чужую базу кривую запись о переводе денег.
Ну физически то может. Но сделать это гораздо сложнее чем в монолите.
Но у этой медали есть и обратная сторона: если у вас разные базы, то сделать джоин в них крайне сложно. Задачи которые в монолите бы решались одной строкой в SQL в MSA начинают требовать тонны кода.
Пример реальный: профили пользователей лежат в одном сервисе, данные о туристических маршрутах в другом. Важная часть логики: для несовреннолетних доступна одна часть маршрутов, для соврешеннолетных — другая. Есть еще другие признаки для фильтров: по регионам, интересам итд.
Теперь нам надо сделать рассылку, подобрав подходящие маршруты для клиентов.
В монолите — один джоин. В MSA — пожалуйста напишите тонну кода.
В реальности ситуация была еще хуже. Данные о бронях групп и совершенных путешествиях лежали в третьем сервисе. И конечно же надо было из предложений исключить тех кто уже ездил.


G>>Так это самые важные вопрос. Я еще раз напомню тезис, который в этой теме и другие коллеги подтверждают: MSA это больше про оргструктуру, а не про архитектуру. В интернетах предлагают "правильную" MSA с разделением микросервисов по разным репозитариям исходного кода. Как в этом случае обеспечить синхронность изменений разных микросервисах, если изменяемый бизнес-процесс затрагивает несколько таких микросервисов?

S>Никак — MSA, собственно, и обеспечивает отсутствие синхронности. Это преимущество, а не недостаток.
А в чем собственно преимущество? Ну если в деньгах посчитать.

S>Изменения в бизнес-процессе накатываются постепенно: сначала мы обучаем новостям самый "нижний" микросервис в топологически отсортированном списке микросервисов, затем — чуть более "верхние".

S>Изменения в БП становятся видны в тот момент, когда мы выкатываем изменения "корневого" микросервиса, который оркестрирует весь БП.
Если сервисы имеют строгую иерархию и представляют из себя "слои" приложения, то возможно это и так.
Но сразу три замечания:
1) это цикл внедрения фичи удлиняет. Так как скорости выгоднее делать "вертикальное" деление проекта.
2) Это противоречит мысли самодостаточности сервиса. "Верхний" не работает без "нижних", а "нижние" не нужны без "верних".
3) При падении\ошибке в "нижних" "верхние" тоже ломаются.



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

G>>В msa весьма вероятна ситуация, что в принципе невозможно собрать работающее сочетание микросервисов. Я такое на практике видел. Было три микросервиса (А,Б,В) и два процесса(1,2), затрагивающие три сервиса. В один момент было так, что: А/HEAD, Б/HEAD, В/HEAD~1 работал сценарий 1, но не работал 2. А/HEAD, Б/HEAD~1, В/HEAD работал 2, но не работал 1 и при этом же А/HEAD~1, Б/HEAD, В/HEAD также работал 2, но не работал 1.

G>>И каждый разработчик миросервиса доказывал что "work on my microservice" (современный аналог work on my machine)

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

S>А, ну и, возможно, неудачно были проведены границы между микросервисами. Это — отдельное искусство, настолько редкое, что я, ЕМНИП, видел только одно правильное решение (и с десяток заведомо неверных).

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

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

S>Может быть. Я не говорю, что MSA — единственный верный способ деятельности
Я делаю более сильное утверждение: MSA пригодна только там, где есть соответствующая оргструктура: много несвязанных команд, каждая из которых работает на процессами, слабо связанными друг с другом. Такое в банках и маркетплейсах такое очень часто встречается, а они составляют основу русского бигтеха.
А например в корпоративных системах оно не надо, как при кастомной разработке, так и при разработке тиражируемого продукта.

G>>Доункаст к чему, если у него нет паблик класса, к которому даункастить?

S>Почему вы думаете, что нету?
S>А если нету — всегда можно запилить reflection. Пытливому уму все средства хороши.
Ну я точно также могу сказать про запись в чужую базу. Оно ведь все равно деплоится все в одно приложение докера\кубера и контейнеры видят друг друга. И все равно разраб сталкивается с тестовой средой, где может "в дикой природе" наблюдать какие еще сервисы работают и с какими хранилищами.

G>>Тут даже комментировать не буду. В дотнете и жабе полно средств изоляции. При желании даже в JS можно инкапсуляцию сделать, чтобы до потрохов никто не добрался.

S>Как раз в JS-то можно. Но, опять же, можно!=делают.
Так и в MSA изоляция зачастую условная. Да, у каждого сервиса база своя, но сервер БД один. Дорого поднимать несколько экзепляров даже постгреса. И учетные данные одни.
Если разработчикам не прививать дисциплину, то никакая изоляция не поможет.

G>>Так можно и в базу другого микросервиса полезть.

S>Невозможно. Базу чужого микросервиса даже не видно. И даже если вдруг чужая база лежит на той же машине, то доступ к ней выдан другому сервис-аккаунту, чем тот, под которым бегает этот микросервис.
Ну-ну. Это на практике может быть в бигтехе, где базы нарезаются отдельной командой и не входят в профиль деплоя. Но пока все приложение это одни набор yaml файлов для docker\kuber — пролезть можно. Опять-таки если недостаточная дисциплина.

Один раз премии лишить за рефлекшн без необходимости и сразу желание пропадет так писать.

G>>В случае единой репы и нормального архитектора — на ревью бить по рукам (или по лицу) за такой код.

S>Это всё хорошо работает до определённых размеров кодовой базы, команды, и уровня ответственности за промахи. Там, где за ошибки принято тюремное заключение или суровые штрафы, делают именно так, не полагаясь на бдительность peer review и личность архитектора.
Ну давай честно: есть предел размера команды или предел структуры управления для монолита. С этим никто не спорит.
Далее возможно развитие или по пути MSA или по пути "ядро\платформа и прикладная часть".
Но до этого предела монолит превосходит MSA по любым параметрам.

G>>Я именно об этом и говорю. Знаю один банк где над таким ядром-"микросервисом" трудится команда из 40+ только программистов. То есть ни разу он не "микро", о чем я и говорю. А выдача кредитов это вообще с десяток связанных процессов, на каждом из которых команда в 10+ человек. То есть их тоже "микро" назвать сложно.

S>Так "micro" это же не про размер команды. А про "площадь поверхности".
Не очень понятно в чем она измеряется.
Re[2]: Помогите правильно спроектировать микросервисное приложение
От: busk  
Дата: 03.04.25 09:07
Оценка:
Здравствуйте, Sinclair, Вы писали:


S>Важно, чтобы микросервисы как можно меньше взаимодействовали между собой. Если не получается — значит, границы выбраны неверно.

S>По вашему описанию не вполне понятно, что собственно должна делать система. Распределять заказы между водителями?
S>Смотрите:
S>0. Сервис аутентификации. Его хочется делать крайне надёжной, т.к. если никто не может зайти, то не работает вообще всё. Очень опасно делать монолит, в котором выкат какой-нибудь мелкой фичи типа "а давайте поздравим всех водителей-женщин с 8 марта" способен сломать логин. То есть эту штуку мы как можно реже релизим, и при каждом выкате покрываем тестами в шесть слоёв. Отдельные пацаны аудируют код на предмет потенциальных уязвимостей, т.к. кража базы паролей — почти самое плохое, что с нами вообще может случиться. Сам сервис скорее всего раскатан в нескольких экземплярах с геодистрибуцией и офигенной избыточностью — чтобы отключение света в нижегородском ДЦ не валило всю федеральную сеть водителей.
S>(Кстати, очень часто мы захотим это вообще делегировать наружу, чтобы не заниматься дорогостоящими инвестициями в эти пять девяток и прочие особенности. Привинчиваем OAuth и полагаемся на Google/Facebook/etc)
S>1. Сервис авторизации. После того, как пользователь залогинился, нам нужно ещё и получить набор его прав. В большинстве случаев это довольно-таки типовая структура, вроде ролей. Опять же, требования к ней довольно-таки жёсткие, т.к. она нужна в каждом первом сценарии. Ещё можно заметить, что она в значительной мере дублирует информацию из 0-й системы — как минимум, у нас должен быть тот же самый список пользователей. Поэтому в современном мире зачастую 0 и 1 объединяют в одну.



вот эти 2 прямо можно в один сервис и отдельную базу, на остальном боюсь не хватит ресурсов и опыта для начала.

а вопрос такой: если это будет винда и один сервер то как проще организовать архитектуру двух сервисов (аутенфикация + авторизация) и всего остального?
докер или один общий шлюз (я так понял приложение) и дальше запрос идет либо на сервис 1 либо на сервис 2?
Re[14]: Помогите правильно спроектировать микросервисное при
От: · Великобритания  
Дата: 03.04.25 10:41
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>>>·>Гы. Как минимум, память и gc — разделяемые. Так что когда запрос какого-нибудь отчёта для аналитики вдруг роняет по OOM всё сразу, в т.ч. обработку заказов — ничего хорошего.

G>>>Ничего не мешает в рамках монолитного решения вынести отдельный инстанс для обработки тяжелых запросов и на уровне балансера распределять.
G>·>Видимо ты тут намекаешь на какую-то принципиальную разницу между SOA и MSA?
...
G>Тут и паттерны, и технологии, и оргструктуры и много чего еще.
Ок, можно согласится что в разных контекстах/организациях под SOA/MSA понимаются разные вещи. Нет никакого официального математически строгого определения.
Я рассуждаю с т.з. "собираем много разных бинарей, деплоим в разные места с разными опциями".

G>>>Еще раз повторю тезис: MSA это больше про оргструктуру и следующие за ней технические решения.

G>·>По-моему, ты причину со следствием путаешь.
G>А может и наоборот, не задумывался об этом?
Задумывался. Вполне возможно где-то может быть и наоборот в соответствии с карго-культом.

G>Я вижу что микросервисы цветут там, где слишком много команд и разработчиков чтобы пилить монолиты. Поэтому техническая архитектура диктуется оргструктурой. Если у тебя команда небольшая или ты вообще один что-то делаешь — тебе в принципе не нужны микросервисы.

Иногда нужны — если есть соответствующие технические требования.

G>·>А зачем обязательно один бинарник? Если деплоймент разный всё равно. Чтобы были многочасовые билды?

G>А ты думаешь сборка одного толстого бинарника медленнее, чем сборка трех бинарников потоньше? Или ты думаешь что обязательно пересобирать все проекты каждый раз?
Гы. Трёх? Ты тут выше написал о сотне строк на сервис. За "монолит" объёмом на 3 сотни — я всеми конечностями.

G>Да и в целом время сборки для деплоя мало интересует, интересует время от команды run до запуска приложения, если ты это делаешь 25 раз в день.

В мире soa/msa часто бывает так, что запустить приложение ты просто не можешь командой run. Ресурсов на рабочей машине не хватит. Так что run запускаются только некоторые части, чаще просто тесты.

G>·>Сборка, деплой и перезапуск мелкого сервиса занимает минуты от момента мержа PR. Тогда как типичная выкатка монолита — приятно проведённые выходные.

G>В теории да. Но внезапно:
G>1) в микросервисах надо тупо больше кода править
зато общий impact правок ниже.

G>2) если ты затрагиваешь несколько сервисов своим изменением, то несколько сервисов собираются дольше чем один

В msa у тебя будет не три бинарника, а хотя бы тридцать. И работая над очередной фичей типично трогаешь 1-2, в плохих случаях 4-5 бинарников. А вот сборка 2 бинарников от 30 отличается уже на порядок.

G>3) даже докер умеет кэшировать образы, поэтому вполне можно сделать сбору с кэшированием и не пересобирать то, что не изменилось

А дальше? Как потом бинарник будет решать кем он сейчас работает — rest-сервером или fix-коннектором или распределённым кешем? Потребуется нетривиальная система конфигов.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 03.04.2025 11:02 · . Предыдущая версия .
Re[15]: Помогите правильно спроектировать микросервисное при
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 03.04.25 13:04
Оценка:
Здравствуйте, ·, Вы писали:

G>>Я вижу что микросервисы цветут там, где слишком много команд и разработчиков чтобы пилить монолиты. Поэтому техническая архитектура диктуется оргструктурой. Если у тебя команда небольшая или ты вообще один что-то делаешь — тебе в принципе не нужны микросервисы.

·>Иногда нужны — если есть соответствующие технические требования.
Предположим:
Команда из 10 человек, 7 разрабы, 3 аналитики и тестеры. Используется всеми один стек: условно дотнет и TS\react на клиенте.
Какие могут быть технические требования, чтобы с микросервисами они реализовывались проще, чем без них?


G>>·>А зачем обязательно один бинарник? Если деплоймент разный всё равно. Чтобы были многочасовые билды?

G>>А ты думаешь сборка одного толстого бинарника медленнее, чем сборка трех бинарников потоньше? Или ты думаешь что обязательно пересобирать все проекты каждый раз?
·>Гы. Трёх? Ты тут выше написал о сотне строк на сервис. За "монолит" объёмом на 3 сотни — я всеми конечностями.
уже на трех одновременно пересобираемых микросервисах время сборки монолита оказывается меньше.

G>>Да и в целом время сборки для деплоя мало интересует, интересует время от команды run до запуска приложения, если ты это делаешь 25 раз в день.

·>В мире soa/msa часто бывает так, что запустить приложение ты просто не можешь командой run. Ресурсов на рабочей машине не хватит. Так что run запускаются только некоторые части, чаще просто тесты.
Довольно странное заявление. Почему может не хватить ресурсов запустить проекта, который ничего не делает? Только кривостью рук разработчиков может быть такое решение обосновано.

G>>·>Сборка, деплой и перезапуск мелкого сервиса занимает минуты от момента мержа PR. Тогда как типичная выкатка монолита — приятно проведённые выходные.

G>>В теории да. Но внезапно:
G>>1) в микросервисах надо тупо больше кода править
·>зато общий impact правок ниже.
Я не понимаю что это. Что значит "общий импакт"? Я считаю количество строк\методов\объектов.

G>>2) если ты затрагиваешь несколько сервисов своим изменением, то несколько сервисов собираются дольше чем один

·>В msa у тебя будет не три бинарника, а хотя бы тридцать. И работая над очередной фичей типично трогаешь 1-2, в плохих случаях 4-5 бинарников. А вот сборка 2 бинарников от 30 отличается уже на порядок.
Тогда непонятно с чем ты споришь. Всегда найдется N, такое, что пересборка N микросервисов будет дольше чем пересборка монолита с аналогичным функционалом. Причем это N оказывается довольно небольшим. По моей практике N бывает от 3 до 5.

G>>3) даже докер умеет кэшировать образы, поэтому вполне можно сделать сбору с кэшированием и не пересобирать то, что не изменилось

·>А дальше? Как потом бинарник будет решать кем он сейчас работает — rest-сервером или fix-коннектором или распределённым кешем? Потребуется нетривиальная система конфигов.
Она все равно O(1), то пишется один раз и потом вносятся правки, независимые от объема изменений кода.
А кот конфиг для микросервисов зачастую O(N), так как развитие систем на базе MSA приводит к росту числа микросервисов, что в свою очередь увеличивает объем конфигов.
Re[7]: Помогите правильно спроектировать микросервисное приложение
От: Sharov Россия  
Дата: 03.04.25 15:39
Оценка:
Здравствуйте, ·, Вы писали:

·>И да, сервисы не через REST взаимодйествуют, а через pub-sub сообщения (kafka/29west/mq/fix/аналоги).


А в чем проблема взаимодействовать по REST'у?
Кодом людям нужно помогать!
Re[8]: Помогите правильно спроектировать микросервисное приложение
От: · Великобритания  
Дата: 03.04.25 20:49
Оценка:
Здравствуйте, Sharov, Вы писали:

S>·>И да, сервисы не через REST взаимодйествуют, а через pub-sub сообщения (kafka/29west/mq/fix/аналоги).

S>А в чем проблема взаимодействовать по REST'у?
Отсутствие гибкости. Rest — это синхронный p2p request-response только. Притом с большим оверхедом в виде http обёртки.
Сообщения — это кто угодно с кем угодно, streaming, множество отправителей/получателей и т.п. В MSA без такого трудно обойтись.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[16]: Помогите правильно спроектировать микросервисное при
От: · Великобритания  
Дата: 03.04.25 21:02
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>>>Я вижу что микросервисы цветут там, где слишком много команд и разработчиков чтобы пилить монолиты. Поэтому техническая архитектура диктуется оргструктурой. Если у тебя команда небольшая или ты вообще один что-то делаешь — тебе в принципе не нужны микросервисы.

G>·>Иногда нужны — если есть соответствующие технические требования.
G>Предположим:
G>Команда из 10 человек, 7 разрабы, 3 аналитики и тестеры. Используется всеми один стек: условно дотнет и TS\react на клиенте.
G>Какие могут быть технические требования, чтобы с микросервисами они реализовывались проще, чем без них?
Ну тут Sinclair вроде рассказывал варианты. Могу рассказать что я видал, но там много чего, а не просто ts/react. Сразу скажу, это торговые системы, где процент веба около нуля.

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

G>·>Гы. Трёх? Ты тут выше написал о сотне строк на сервис. За "монолит" объёмом на 3 сотни — я всеми конечностями.
G>уже на трех одновременно пересобираемых микросервисах время сборки монолита оказывается меньше.
Очень сомневаюсь, когда бинарников десятки.

G>>>Да и в целом время сборки для деплоя мало интересует, интересует время от команды run до запуска приложения, если ты это делаешь 25 раз в день.

G>·>В мире soa/msa часто бывает так, что запустить приложение ты просто не можешь командой run. Ресурсов на рабочей машине не хватит. Так что run запускаются только некоторые части, чаще просто тесты.
G>Довольно странное заявление. Почему может не хватить ресурсов запустить проекта, который ничего не делает? Только кривостью рук разработчиков может быть такое решение обосновано.
А зачем вообще запускать что-то, что ничего не делает? Ты уж определись.

G>·>зато общий impact правок ниже.

G>Я не понимаю что это. Что значит "общий импакт"? Я считаю количество строк\методов\объектов.
Что обновив какой-нибудь условный коннектор с платёжной системой можно сломать только платежи, а не всю систему.

G>>>2) если ты затрагиваешь несколько сервисов своим изменением, то несколько сервисов собираются дольше чем один

G>·>В msa у тебя будет не три бинарника, а хотя бы тридцать. И работая над очередной фичей типично трогаешь 1-2, в плохих случаях 4-5 бинарников. А вот сборка 2 бинарников от 30 отличается уже на порядок.
G>Тогда непонятно с чем ты споришь. Всегда найдется N, такое, что пересборка N микросервисов будет дольше чем пересборка монолита с аналогичным функционалом. Причем это N оказывается довольно небольшим. По моей практике N бывает от 3 до 5.
Ну видимо какие-то простые маленькие системы в твоей практике были.

G>·>А дальше? Как потом бинарник будет решать кем он сейчас работает — rest-сервером или fix-коннектором или распределённым кешем? Потребуется нетривиальная система конфигов.

G>Она все равно O(1), то пишется один раз и потом вносятся правки, независимые от объема изменений кода.
G>А кот конфиг для микросервисов зачастую O(N), так как развитие систем на базе MSA приводит к росту числа микросервисов, что в свою очередь увеличивает объем конфигов.
Так растёт число не само по себе, а потому что добавляется новая функциональность, которую надо конфигурить — адреса-пароли-явки.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[9]: Помогите правильно спроектировать микросервисное приложение
От: Sharov Россия  
Дата: 03.04.25 22:33
Оценка:
Здравствуйте, ·, Вы писали:

·>Здравствуйте, Sharov, Вы писали:


S>>·>И да, сервисы не через REST взаимодйествуют, а через pub-sub сообщения (kafka/29west/mq/fix/аналоги).

S>>А в чем проблема взаимодействовать по REST'у?
·>Отсутствие гибкости. Rest — это синхронный p2p request-response только. Притом с большим оверхедом в виде http обёртки.
·>Сообщения — это кто угодно с кем угодно, streaming, множество отправителей/получателей и т.п. В MSA без такого трудно обойтись.

А что мешает его сделать асинхронным?
Кодом людям нужно помогать!
Re[9]: Помогите правильно спроектировать микросервисное приложение
От: Sinclair Россия https://github.com/evilguest/
Дата: 04.04.25 01:14
Оценка:
Здравствуйте, ·, Вы писали:

·>Отсутствие гибкости. Rest — это синхронный p2p request-response только. Притом с большим оверхедом в виде http обёртки.

·>Сообщения — это кто угодно с кем угодно, streaming, множество отправителей/получателей и т.п. В MSA без такого трудно обойтись.
Вот с чем никогда в жизни не работал — так это с описываемой вами архитектурой.
Как в ней решаются вопросы
1. Согласованности: чтобы вся эта слабосвязанная мешанина реально делала то, что нужно?
2. Зависимостей — как мне понять, сколько сервисов нужно запустить, чтобы реализовался сценарий X? Чтобы не получилось, как в анекдоте: "один копает ямы, а другой закапывает; ещё один должен был туда деревья вставлять, но он не пришёл".
3. Предотвращения лайв-локов: один сервис ждёт с шины сообщение А, потом отправит сообщение Б. Другой сервис как раз ждёт сообщение Б, чтобы отправить А

Если есть какая-то книжка на эту тему — отправьте в неё, пожалуйста
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[10]: Помогите правильно спроектировать микросервисное приложение
От: TG  
Дата: 04.04.25 05:55
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Вот с чем никогда в жизни не работал — так это с описываемой вами архитектурой.

S>Как в ней решаются вопросы
S>1. Согласованности: чтобы вся эта слабосвязанная мешанина реально делала то, что нужно?
S>2. Зависимостей — как мне понять, сколько сервисов нужно запустить, чтобы реализовался сценарий X? Чтобы не получилось, как в анекдоте: "один копает ямы, а другой закапывает; ещё один должен был туда деревья вставлять, но он не пришёл".
S>3. Предотвращения лайв-локов: один сервис ждёт с шины сообщение А, потом отправит сообщение Б. Другой сервис как раз ждёт сообщение Б, чтобы отправить А

S>Если есть какая-то книжка на эту тему — отправьте в неё, пожалуйста


Только оркестрацией сервисов. Например, https://github.com/temporalio/temporal.
Re[5]: Помогите правильно спроектировать микросервисное приложение
От: Miroff Россия  
Дата: 04.04.25 06:19
Оценка:
Здравствуйте, TG, Вы писали:

TG>API приложения полностью зависит от нужд потребителя. Договариваться придётся.


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

Альтернатива — дизайн от доменной модели, когда ты определяешь доменные сущности, их состояния и переходы между ними и выставляешь полное API для манипулирования этими сущностями не беспокоясь о том, нужно кому-то это прямо сейчас или нет. Это позволяет клиентам твоего сервиса реализовать любой сценарий не дергая тебя и не требуя изменений твоего API. Это и есть полноценная микросервисная архитектура.
Re[6]: Помогите правильно спроектировать микросервисное приложение
От: TG  
Дата: 04.04.25 07:14
Оценка:
Здравствуйте, Miroff, Вы писали:

TG>>API приложения полностью зависит от нужд потребителя. Договариваться придётся.


M>Дизайн от сценариев лишь один из возможных подходов. Если ты дизайнишь API в расчете на пользователя, пользователь, конечно рад, но при каждом изменении сценариев потребителя тебе приходится подстраивать под них свое API, а если потребителей много то еще и увязывать их сценарии между собой. В результате ты делаешь кучу ненужной работы, переусложняешь свой сервис и в конце концов обнаруживаешь себя внутри распределенного монолита.


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

M>Альтернатива — дизайн от доменной модели, когда ты определяешь доменные сущности, их состояния и переходы между ними и выставляешь полное API для манипулирования этими сущностями не беспокоясь о том, нужно кому-то это прямо сейчас или нет. Это позволяет клиентам твоего сервиса реализовать любой сценарий не дергая тебя и не требуя изменений твоего API. Это и есть полноценная микросервисная архитектура.


Что Вы понимаете под доменной моделью?
И что значит "полное API"?
Re[7]: Помогите правильно спроектировать микросервисное приложение
От: Miroff Россия  
Дата: 04.04.25 07:25
Оценка:
Здравствуйте, TG, Вы писали:

TG>И если клиент готов платить, почему не делать?


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

TG>Что Вы понимаете под доменной моделью?


https://martinfowler.com/bliki/DomainDrivenDesign.html

TG>И что значит "полное API"?


Возможность достигнуть любого состояния системы посредством API. CRUD на все доменныек сущности плюс переходы по всем возможным состояниям.
Re[10]: Помогите правильно спроектировать микросервисное приложение
От: · Великобритания  
Дата: 04.04.25 07:32
Оценка:
Здравствуйте, Sharov, Вы писали:

S>·>Отсутствие гибкости. Rest — это синхронный p2p request-response только. Притом с большим оверхедом в виде http обёртки.

S>·>Сообщения — это кто угодно с кем угодно, streaming, множество отправителей/получателей и т.п. В MSA без такого трудно обойтись.
S>А что мешает его сделать асинхронным?
Спека http. Я наверное неточно выразился, я имел в виду, что на каждый запрос приходит ответ, который надо прочитать, даже если это "204 No Content". Притом ответ ровно один.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[8]: Помогите правильно спроектировать микросервисное приложение
От: TG  
Дата: 04.04.25 10:09
Оценка:
Здравствуйте, Miroff, Вы писали:

TG>>И если клиент готов платить, почему не делать?

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

Пусть об этом голова у менеджмента болит.

TG>>И что значит "полное API"?

M>Возможность достигнуть любого состояния системы посредством API. CRUD на все доменныек сущности плюс переходы по всем возможным состояниям.

Так сервис может не ограничиваться CRUD-ом и состояниями.
Построение маршрута там же Яндекс.Карты, например.
Какое там "полное API" для всех клиентов можно выкатить?
Re[10]: Помогите правильно спроектировать микросервисное приложение
От: TG  
Дата: 04.04.25 10:37
Оценка:
Здравствуйте, Miroff, Вы писали:

TG>>Так сервис может не ограничиваться CRUD-ом и состояниями.

TG>>Построение маршрута там же Яндекс.Карты, например.
TG>>Какое там "полное API" для всех клиентов можно выкатить?

M>Посмотри на API OpenStreetMap, версия 0.7 вышла 15 лет назад когда, еще JSON не изобрели, и с тех пор ее не апдейтили потому что и так хорошо вышло. Так бывает, когда API проектируют инженеры, а не менеджеры.

Это не означает, что все довольны.

Вот, допустим, я заказчик/клиент Яндекс.Карт, OSM и т.д.
Задача: построить маршрут с условиями:
— маршрут не должен проходить по дорогам общего пользования (в том числе грунтовым) и вообще не должен приближаться к ним ближе, чем на 5 км.
— если без пересечения дорог общего пользования не обойтись, то пересечение маршрута с ними должно идти под углом, близким к прямому
— нельзя прокладывать маршрут по: болотам, лесам, возвышенностям
— нельзя прокладывать маршрут по определенным зонам, задаваемым пользователем в запросе.

Какое готовое API известных сервисов картографии такое уже умеет?
Re[13]: Помогите правильно спроектировать микросервисное приложение
От: SkyDance Земля  
Дата: 04.04.25 17:26
Оценка:
·>Сборка, деплой и перезапуск мелкого сервиса занимает минуты от момента мержа PR. Тогда как типичная выкатка монолита — приятно проведённые выходные.

Беда приходит тогда, когда требуется поменять код, общий для многих/всех микросервисов. Например, добавить (m)TLS, или еще что-то такое. Любой инфраструктурный проект в МСА вызывает многолетнюю попаболь, и приводит к жутчайшим штуковинам типа Istio и прочим service-mesh'ам.
Re[13]: Каких программ вам не хватает?
От: TG  
Дата: 07.04.25 06:58
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Во-вторых, построение безопасности путём скрытия действий в UI — это популярная, но плохая идея. В основном — потому, что она неимоверно бесит пользователей. Вот я сижу перед списком пользователей, хочу объявить выговор. Поискал в меню — нет такой команды. Поискал в свойствах сотрудника — нет такой кнопки. Полез в инструкцию — сказано "для объявления выговора нажмите на кнопку "Объявить выговор". И вот я уже полчаса думаю, то ли я дурак, то ли инструкция устарела, то ли программа глючит. Внезапно, "некрасивый" способ — дать мне нажать на кнопку, а потом вывести "403 у вас недостаточно прав для объявления выговора этому сотруднику" — в разы гуманнее по отношению к пользователю, чем предлагаемая вами идея.


Ну, идея как-то промаркировать элементы в списке, с которыми я могу что-то делать и с которыми не могу, вполне нормальная.
Жмякнуть на кнопку, подождать стандартный таймаут в 60 сек. и получить отлуп, может выбешивать не меньше.
Re[14]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 07.04.25 07:29
Оценка:
Здравствуйте, TG, Вы писали:

TG>Ну, идея как-то промаркировать элементы в списке, с которыми я могу что-то делать и с которыми не могу, вполне нормальная.

Нет.
TG>Жмякнуть на кнопку, подождать стандартный таймаут в 60 сек. и получить отлуп, может выбешивать не меньше.
Не очень понятно, откуда взялся "стандартный таймаут". Большинство сервисов отвечают в течение 1-2 секунд. Это я говорю про обращения с другого континента.
А уж если им и делать ничего не надо, а только вернуть ошибку — то ещё быстрее.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[15]: Каких программ вам не хватает?
От: TG  
Дата: 07.04.25 08:46
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, TG, Вы писали:


TG>>Ну, идея как-то промаркировать элементы в списке, с которыми я могу что-то делать и с которыми не могу, вполне нормальная.

S>Нет.

Сайты с бесплатными объявлениями бывают вываливают в поиске архивные объявления и какие-то кнопки там неактивны.
Мы такой подход не одобряем (с), но тамошние маркетологи, видимо, имеют другое мнение.
Я не призываю делать бан кнопок через HATEOAS. Но чем сама идея такого UI плоха?

TG>>Жмякнуть на кнопку, подождать стандартный таймаут в 60 сек. и получить отлуп, может выбешивать не меньше.

S>Не очень понятно, откуда взялся "стандартный таймаут".

"Стандартный таймаут" — который часто выставляет фреймворк, например, WCF. Кто-то вообще не заморачивается на эти таймауты и оставляет всё по умолчанию.

S> Большинство сервисов отвечают в течение 1-2 секунд. Это я говорю про обращения с другого континента.

S>А уж если им и делать ничего не надо, а только вернуть ошибку — то ещё быстрее.

Это, скажем так, в норме. За городом на мобильном интернете лаг уже составляет секунды.
Да и в "городском" энтерпрайзе пользователи могут столкнуться с тормозами, если они сидят через VPN и админы как-то криво "раскрасили" трафик.
Re[13]: Каких программ вам не хватает?
От: Miroff Россия  
Дата: 08.04.25 07:14
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Можно. Когда я делаю GET на ресурс, я получаю его представление. Крайне желательно, чтобы это представление зависело от состояния ресурса, а не от состояния пользователя, который его получает.

S>Например, можно воткнуть reverse proxy перед сервером приложения, и тогда он сможет снять значительную часть нагрузки с сервера.
S>Как только мы начинаем менять представление объекта в зависимости от пользователя, о кэшировании можно забыть.

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

S>Во-вторых, построение безопасности путём скрытия действий в UI — это популярная, но плохая идея. В основном — потому, что она неимоверно бесит пользователей. Вот я сижу перед списком пользователей, хочу объявить выговор. Поискал в меню — нет такой команды. Поискал в свойствах сотрудника — нет такой кнопки. Полез в инструкцию — сказано "для объявления выговора нажмите на кнопку "Объявить выговор". И вот я уже полчаса думаю, то ли я дурак, то ли инструкция устарела, то ли программа глючит. Внезапно, "некрасивый" способ — дать мне нажать на кнопку, а потом вывести "403 у вас недостаточно прав для объявления выговора этому сотруднику" — в разы гуманнее по отношению к пользователю, чем предлагаемая вами идея.


Современная ИБ говорит, что если какой-то функционал пользователю недоступен он и не должен знать о существовании этого функционала. Иначе мотивированный пользователь начнет искать способ для эскалации привилегий и, чем черт не шутит, вдруг найдет. К тому же, с точки зрения UX скрытие кнопки эквивалентно вызову с ошибкой потому что а) причин ошибки бесконечно много и в этом случае все их нужно обрабатывать и б) ИБ не велит раскрывать внутреннее устройство приложения через сообщения об ошибках, так что пользователь максимум что увидит это "тебе нельзя".

M>>Как в примере из соседнего поста, когда сервис туров следит чтобы определенные туры были доступны только совершеннолетним пользователям и эта же логика дублируется в сервисе рекомендаций чтобы не показывать несоврешеннолетним то, что им и так недоступно. HATEOAS бы эту проблему решил докинув ресурс user список доступных для него туров. ,


S>Это очень, очень плохая архитектура. В первую очередь потому, что вы инвертируете зависимости. Теперь у вас ресурс user (и его микросервис) обязан знать всё о турах (которые вообще-то обрабатываются другим микросервисом).

S>А ресурс "тур", ясное дело, должен знать всё о пользователях. Поздравляю, вы получили не просто монолит, а трудноразвиваемый монолит.

У тебя в любом случае есть связь между двумя ресурсами. Ее можно показать с одного конца, с другого конца или с обоих концов. Последний вариант самый универсальный. Если связь пересекает границы микросервисов, существуют способы это реализовать не увеличивая лишнюю связность: обогащение на уровне gateway, backend for frontend, обогащения на уровне middleware, наконец, просто засунуть в HATEOAS вместо списка туров, ссылку по которой этот список можно получить. Обычно, за HATEOS как раз и отвечает не сам сервис, а middleware. Можно, конечно, замести связь под ковер, но как раз усложняет поддержку сервисов.

S>И это — тоже очень, очень плохая архитектура. Смотрите как это работает: "поисковый запрос" — это эфемерный ресурс. Последнее, что мы хотим — это хранить его. В первую очередь по соображениям масштабирования. Сколько пользователей вы ожидаете ежедневно? Двух? Как только у вас появляется хотя бы несколько сотен тысяч запросов в сутки, хранение (даже в течение ограниченного времени) их эфемерных запросов становится

неподъёмным.

А давай посчитаем Один указатель (кэшировать нужно не весь результат, а только порядок записей), пусть long -- 8 байт * 300k запросов в сутки * 1000 записей (ты же не забываешь про max_search_results)= всего 2.2Gb При этом 300к уникальных запросов это где-то 20M DAU т.е. федеральная система уровня всего СНГ по поиску с запасом влазит на одну машину. У нас, слава богу, не 2005 год и уже завезли кэши в разделяемой памяти, типа hazelcast и ehcache.

S>А непротиворечивость гарантируется тем, что последующие запросы мы дооборудуем хидером if-match/if-none-match, что позволяет нам заметить момент, когда данные на серверной стороне поменялись, и закешированную версию нужно выкинуть.


Во-первых, проверка изменились ли результаты поиска эквивалентна выполнению самого запроса, так что кэширование результатов поиска не имеет смысла и никто им не пользуется. Во-вторых, допустим клиент узнает что результаты изменились, делать-то ему что? Повторять запрос? Тогда никакой консистентности при переходе между страницами не будет и получится ровно то же самое что и с параметрами offset + limit в запросе. Настроить промежуточный кэширующий сервер, который примет полные результаты поиска, а отдавать будет с учетом range. Ну так то же хранение и получится.

S>Простите, но вы рассказываете какие-то небылицы. Что такое "пречеки"? Мы пробежались по всем нужным ресурсам, и убедились, что все нужные нам "действия" торчат в виде линков?


Мы подняли все ресурсы, входящие в сценарий, убедились, что их состояние позволяет реализовать этот сценарий и только после этого начинаем претворять сценарий в жизнь. Понимаешь, когда речь идет про микро сервисы, когда каждый сервис отвечает за свой домен и управляет одним-двумя ресурсами, почти все сценарии захватывают несколько сервисов. При этом подавляющее большинство сценариев не требует строгой консистентности, вполне достаточно eventual consistency. Поэтому нет необходимости любой сценарий превращать в сагу или двухфазный коммит. Более того, сценарии, требующие строгой консистентности встречаются настолько редко, что большинство разработчиков такого не реализовывали ни разу в жизни. В то же время, eventual consistency это все еще consistency, а если у нас сценарии разваливаются через раз, никакой консистентности не будет. Поэтому, дизайнить систему так, чтобы сценарии не разваливались, это хорошая идея. В том числе поддерживать между сервисами контракт, что если мы получили от строннего сервиса ресурс и список связанных ресурсов, то попытка обратиться к этим ресурсам не вызовет ошибки.
Re[14]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 08.04.25 09:19
Оценка:
Здравствуйте, Miroff, Вы писали:

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

Я бы разводил такие вещи по разным "ресурсам", так, чтобы границы безопасности совпадали с границами ресурсов. Потому что это и надёжнее, и эффективнее.
Например: есть у нас, допустим, судебное постановление. Имена и реквизиты упомянутых там лиц — дело чувствительное. Анонимной публике их видеть не положено; а вот авторизованной — да, нужно.
Вариантов три:
1. При отдаче текста постановления смотрим в токен пользователя, и либо заменяем все имена плейсхолдерами, либо вставляем как надо.
2. Делаем два ресурса: "анонимизированное постановление", "полноценное постановление". Анонимный доступ ко второму получает 401, аутентифицированный доступ без прав на данное дело получает 403.
3. Делаем два ресурса: постановление, в "тексте" которого есть ссылки на фигурантов, каждый из которых — самостоятельный ресурс. Постановления отдаём всем желающим, детали фигурантов — только авторизованным пользователям. Остальные получают 403.
Как по мне, так первый вариант, очевидно, самый-самый плохой. Он плохо масштабируется, и крайне плохо проверяется на корректность.

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

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

M>Современная ИБ говорит, что если какой-то функционал пользователю недоступен он и не должен знать о существовании этого функционала.

Можно ссылку на источник, который вы цитируете? Я не эксперт по ИБ, с удовольствием ознакомлюсь.
M>Иначе мотивированный пользователь начнет искать способ для эскалации привилегий и, чем черт не шутит, вдруг найдет.
В той литературе по ИБ, которую я читал в детстве, излагаемая вами концепция называлась "security by obscurity" и считалась однозначным злом. По сравнению, естественно, с нормальной безопасностью, которая не построена на невежестве пользователей.

REST зарубает вашу идею на корню, т.к. весь "функционал" в нём известен заранее: GET/PUT/DELETE.


M>К тому же, с точки зрения UX скрытие кнопки эквивалентно вызову с ошибкой потому что а) причин ошибки бесконечно много и в этом случае все их нужно обрабатывать и б) ИБ не велит раскрывать внутреннее устройство приложения через сообщения об ошибках, так что пользователь максимум что увидит это "тебе нельзя".

Я не понимаю, что вы имеете под пунктом а). Да, совершенно верно, причин ошибки много, и их надо обрабатывать. В любом случае. Как минимум вы должны уметь отличать 4хх от 5хх. Полагаться на то, что ошибок не существует — верный способ заслужить ненависть пользователей. Я знаю, что сейчас модно либо вообще не обрабатывать ошибки (тыкаешь кнопку — и ничего не происходит), либо обрабатывать их в стиле "произошла неизвестная ошибка". Но нужно отдавать себе отчёт в том, что это — не лучший UX. Его можно чем-то оправдывать, но стремиться надо к хорошему — к UX, который пользователя уважает. В частности, не требует от него навыков трассировки веб-сайтов по F12 для того, чтобы отличить ситуацию "в этом детском саду нет мест" от "сессия прокисла, перелогиньтесь".

M>У тебя в любом случае есть связь между двумя ресурсами. Ее можно показать с одного конца, с другого конца или с обоих концов. Последний вариант самый универсальный. Если связь пересекает границы микросервисов, существуют способы это реализовать не увеличивая лишнюю связность: обогащение на уровне gateway, backend for frontend, обогащения на уровне middleware, наконец, просто засунуть в HATEOAS вместо списка туров, ссылку по которой этот список можно получить. Обычно, за HATEOS как раз и отвечает не сам сервис, а middleware.

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

M>А давай посчитаем Один указатель (кэшировать нужно не весь результат, а только порядок записей), пусть long -- 8 байт * 300k запросов в сутки * 1000 записей (ты же не забываешь про max_search_results)= всего 2.2Gb При этом 300к уникальных запросов это где-то 20M DAU т.е. федеральная система уровня всего СНГ по поиску с запасом влазит на одну машину. У нас, слава богу, не 2005 год и уже завезли кэши в разделяемой памяти, типа hazelcast и ehcache.

Омг, омг. Во-первых, кэшировать нужно, конечно же, весь результат. Потому что иначе совершенно непонятно, как в поиск Ивановых затесался Петров. Или в список билетов до 12000р затесался перелёт за 58000.
Во-вторых, что такое "указатель"? Я так понял, вы положились на то, что все исходные данные загружены в память вашей единственной машины?

M>Во-первых, проверка изменились ли результаты поиска эквивалентна выполнению самого запроса, так что кэширование результатов поиска не имеет смысла и никто им не пользуется.

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

M>Во-вторых, допустим клиент узнает что результаты изменились, делать-то ему что? Повторять запрос?

Зачем? REST как раз позволяет "обновить кэш" одним запросом безо всяких повторений.

M>Тогда никакой консистентности при переходе между страницами не будет и получится ровно то же самое что и с параметрами offset + limit в запросе. Настроить промежуточный кэширующий сервер, который примет полные результаты поиска, а отдавать будет с учетом range. Ну так то же хранение и получится.

Всё верно. Только это хранение вы реализуете не за счёт своих средств, дорогостоящих и ограниченных, а за счёт средств клиентов, которые масштабируются автоматически и бесплатно.
Наличие "промежуточного" кэшируюшего сервера — не обязательная часть решения. Можно считать, что у вас есть "кэширующий клиент", который способен построить иллюзию согласованной бесшовной картины.
Вы застали до-гуглмэпные времена? Когда основным картографическим сервисом был MapQuest, который как раз реализовывал концепцию "постраничной навигации". Пользователь мог двигать "окно просмотра" по фиксированной сетке, перемещаясь по ней в четырёх направлениях. Гугл сумел придумать и реализовать клиента, который создаёт иллюзию "бесконечного канваса", несмотря на наличие под капотом точно такого же "постраничного" механизма.
Теперь всем очевидно, что именно такой способ навигации по "огромной плоскости" и является нормальной реализацией концепции просмотра большой картинки через маленькое окно. Карты гугла, яндекса, 2гиса, и примерно кого угодно теперь устроены именно так, и никак иначе. Та же концепция — у Miro, Figma, и бесчисленного множества диаграммных сервисов.
И только "табличные данные", которые являются частным случаем ровно той же задачи, до сих пор реализуются методиками девяностых годов прошлого века. Нет никакой причины так делать, кроме "здесь так принято" и "мне лень думать, как сделать нормально".

M>Мы подняли все ресурсы, входящие в сценарий, убедились, что их состояние позволяет реализовать этот сценарий и только после этого начинаем претворять сценарий в жизнь. Понимаешь, когда речь идет про микро сервисы, когда каждый сервис отвечает за свой домен и управляет одним-двумя ресурсами, почти все сценарии захватывают несколько сервисов. При этом подавляющее большинство сценариев не требует строгой консистентности, вполне достаточно eventual consistency. Поэтому нет необходимости любой сценарий превращать в сагу или двухфазный коммит. Более того, сценарии, требующие строгой консистентности встречаются настолько редко, что большинство разработчиков такого не реализовывали ни разу в жизни. В то же время, eventual consistency это все еще consistency, а если у нас сценарии разваливаются через раз, никакой консистентности не будет. Поэтому, дизайнить систему так, чтобы сценарии не разваливались, это хорошая идея. В том числе поддерживать между сервисами контракт, что если мы получили от строннего сервиса ресурс и список связанных ресурсов, то попытка обратиться к этим ресурсам не вызовет ошибки.

Этот "контракт" невозможно надёжно обеспечить в реальной среде. Всё, что можно делать — это притворяться, что он выполняется. Поэтому существенной разницы между hateoas и "компактной" формой ресурсов с точки зрения достигнутого результата я не вижу.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[15]: Каких программ вам не хватает?
От: Miroff Россия  
Дата: 08.04.25 12:26
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>2. Делаем два ресурса: "анонимизированное постановление", "полноценное постановление". Анонимный доступ ко второму получает 401, аутентифицированный доступ без прав на данное дело получает 403.


А если у тебя десять независимых полей в ресурсе? Будешь делать 100 ресурсов? Сильно сомневаюсь что это хорошее решение, их же придется потом тестировать.

S>3. Делаем два ресурса: постановление, в "тексте" которого есть ссылки на фигурантов, каждый из которых — самостоятельный ресурс. Постановления отдаём всем желающим, детали фигурантов — только авторизованным пользователям. Остальные получают 403.


Опять же, ИБ не велит) Как только у атакующего появляется возможность идентифицировать анонимизированые ресурсы, деанонимизация становится делом техники.

S>Можно ссылку на источник, который вы цитируете? Я не эксперт по ИБ, с удовольствием ознакомлюсь.


Можно, например, начать с википедии и заполировать OWASP Developer Guide. Современный подход к ИБ построен на модели швейцарского сыра: вместо того чтобы обеспечивать безопасность только в одном слое, мы реализуем достаточный уровень безопасности на каждом слое. Один из аспектов такого подхода это принцип минимальных привилегий (пользователю или сервису выдаются как можно меньшие права на как можно более короткий срок достаточный для выполнения операции) и принцип разделения (пользователю выдается только та информация, которая необходима для выполнения операции). И нет, это не security by obscutiry, потому что безопасность на слое ресурсов никак не отменяет проверки прав на уровне сервисов, а лишь дополняет их. Короче, если ты все еще занимаешься разработкой и тем более принятием архитектурных решений, рекомендую пройти какой-нибудь хороший AppSec тренинг, а то с твоего детства многое изменилось )

S>Я не понимаю, что вы имеете под пунктом а). Да, совершенно верно, причин ошибки много, и их надо обрабатывать. В любом случае.


В времена Нового Царства, каждый египтянин после смерти подвергался суду Осириса, где он должен был долго и нужно перечислять чего в жизни он НЕ делал. Вот и с ошибками та же история ) Позитивный сценарий может завершиться только одним способом, негативный -- бесконечным множеством способов из которых восстановимых считанные единицы: 502, да 401 и то не всегда.

S>Во-вторых, что такое "указатель"? Я так понял, вы положились на то, что все исходные данные загружены в память вашей единственной машины?


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

S>Всё верно. Только это хранение вы реализуете не за счёт своих средств, дорогостоящих и ограниченных, а за счёт средств клиентов, которые масштабируются автоматически и бесплатно.


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

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


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

S>Этот "контракт" невозможно надёжно обеспечить в реальной среде. Всё, что можно делать — это притворяться, что он выполняется. Поэтому существенной разницы между hateoas и "компактной" формой ресурсов с точки зрения достигнутого результата я не вижу.


Так практически вся микросервисная архитектура это история не про гарантии, а про достаточно хорошие допущения.
Re[16]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 08.04.25 12:48
Оценка:
Здравствуйте, Miroff, Вы писали:

M>А если у тебя десять независимых полей в ресурсе? Будешь делать 100 ресурсов?

Это очень странное предположение. Что значит "независимых"? Независимость и означает, что это не один ресурс, а несколько. А их искусственное склеивание — прямой путь создать себе проблемы.
M>Сильно сомневаюсь что это хорошее решение, их же придется потом тестировать.
А в других вариантах их типа можно не тестировать? Как раз нет: вам нужно протестировать не просто корректность раздачи прав доступа на 10 разных ресурсов, а 210 комбинаций вида "есть права на F1 и F3, нет прав на F2 и прочие".

S>>3. Делаем два ресурса: постановление, в "тексте" которого есть ссылки на фигурантов, каждый из которых — самостоятельный ресурс. Постановления отдаём всем желающим, детали фигурантов — только авторизованным пользователям. Остальные получают 403.


M>Опять же, ИБ не велит) Как только у атакующего появляется возможность идентифицировать анонимизированые ресурсы, деанонимизация становится делом техники.

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

S>>Можно ссылку на источник, который вы цитируете? Я не эксперт по ИБ, с удовольствием ознакомлюсь.


M>Можно, например, начать с википедии и заполировать OWASP Developer Guide. 4

Спасибо, интересно.

M>Не обязательно, любой идентификатор объекта. Хотя, конечно, кэши на разделяемой памяти выгладят красиво.

Ну, вот "любой идентификатор" — это уже не 8 байт, а как минимум 16 (если мы пользуемся гуидами). А то и больше, если у нас ресурсы размазаны по нескольким неймспейсам.

M>Погоди, ты же только что предлагал в заголовках передавать range. Как у тебя будет работать согласованное кэширование, если часть диапазона клиентом даже не запрашивалась? Не говоря уже о том, что браузеры не поддерживают кэширование совместно с range.

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

M>Вообще говоря, в 25 году мало кто работает с табличными данными вообще. Сейчас в моде разделяемое состояние между сервером и клиентом и реактивное программирование для двусторонней синхронизации этой модели в реальном времени. Если непонятно сформулировал, посмотри на фейсбук.

Ок, тем лучше. У меня отвалился антизапрет, а включать VPN чтобы почитать фейсбуковый API guide мне лень. Выражу осторожное сомнение в том, что у фейсбука под капотом — пейджинг на limit offset. Скорее всего, там предикатный метки (примерно так же, как сделаны continuation token в многостраничных респонсах MS Graph API) или там какие-нибудь timestamp ranges.

M>Так практически вся микросервисная архитектура это история не про гарантии, а про достаточно хорошие допущения.

Кмк, это не потому, что такова была цель, а потому что "так получилось". Я же говорю — удачных примеров MSA я видел в единичных количествах, а вот неудачных — как говна за баней.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[16]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 08.04.25 15:24
Оценка:
Здравствуйте, ·, Вы писали:

S>>2. Делаем два ресурса: "анонимизированное постановление", "полноценное постановление". Анонимный доступ ко второму получает 401, аутентифицированный доступ без прав на данное дело получает 403.

·>Такое экспоненциально рванёт. У тебя 2 ресурса для одного permission "смотреть инфу о фигурантах". Представь у тебя 10 таких permissions, в зависимости от роли пользователя. Потребуется 1024 разных ресурса.
Это ж не настоящие ресурсы, а виртуальные. В параллельном ответе пояснил, что экспоненциальный взрыв наступает даже тогда, когда ресурс "один", но может быть отдан в 1024 разных конфигурациях.

S>>3. Делаем два ресурса: постановление, в "тексте" которого есть ссылки на фигурантов, каждый из которых — самостоятельный ресурс. Постановления отдаём всем желающим, детали фигурантов — только авторизованным пользователям. Остальные получают 403.

·>Получаем список из n документов, и в каждом ещё 10 ссылок. Тут же шлём ещё n*10 запросов, некоторые из которых что-то возвращают, а некоторые дают 403 отлуп... Тучи запросов и тормоза на пустом месте.
Зато всё безопасно. Причин для тормозов я не вижу: ваш "рабочий" вариант делает всё то же самое "под капотом", т.к. пермишны проверить всё равно надо, и сходить за данными фигуранта тоже надо. Единственная радость — некоторая экономия на хидерах.

S>>Как по мне, так первый вариант, очевидно, самый-самый плохой. Он плохо масштабируется, и крайне плохо проверяется на корректность.

·>Зато работает.
А вы тестировали? Все 1024 комбинации прав и привилегий?

На практике, конечно же, таких мелкогранулярных систем безопасности не бывает. Как правило, всё квадратно-гнездовое, и набор ролей фиксирован в бизнес-модели (и зачастую ещё и продиктован регулятором).
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[17]: Каких программ вам не хватает?
От: · Великобритания  
Дата: 08.04.25 16:15
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>>>2. Делаем два ресурса: "анонимизированное постановление", "полноценное постановление". Анонимный доступ ко второму получает 401, аутентифицированный доступ без прав на данное дело получает 403.

S>·>Такое экспоненциально рванёт. У тебя 2 ресурса для одного permission "смотреть инфу о фигурантах". Представь у тебя 10 таких permissions, в зависимости от роли пользователя. Потребуется 1024 разных ресурса.
S>Это ж не настоящие ресурсы, а виртуальные. В параллельном ответе пояснил, что экспоненциальный взрыв наступает даже тогда, когда ресурс "один", но может быть отдан в 1024 разных конфигурациях.
Гы. Практически с таким же успехом можно засунуть bearer-токен в url, вот у тебя по ресурсу для каждой конфигурации.

S>·>Получаем список из n документов, и в каждом ещё 10 ссылок. Тут же шлём ещё n*10 запросов, некоторые из которых что-то возвращают, а некоторые дают 403 отлуп... Тучи запросов и тормоза на пустом месте.

S>Зато всё безопасно. Причин для тормозов я не вижу: ваш "рабочий" вариант делает всё то же самое "под капотом", т.к. пермишны проверить всё равно надо, и сходить за данными фигуранта тоже надо. Единственная радость — некоторая экономия на хидерах.
Поход внутри сервиса может осуществляться в памяти того же процесса сервиса, в крайнем случае добавлением соответствующих JOIN в sql. А так у тебя будет куча сетевых вызовов... и представь это всё с мобилы через инет! Надо считать roundtrips.

S>·>Зато работает.

S>А вы тестировали? Все 1024 комбинации прав и привилегий?
Каждую комбинацию тестировать не нужно. Нужно тестировать каждую привелегию. Два теста: "разрешено всё -> возвращается инфа о фигурантах", "разрешено всё, кроме инфы о фигурантах -> не возвращается инфа о фигурантах". Ну и отдельно матрица роли <-> привилегии.

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

S>На практике, конечно же, таких мелкогранулярных систем безопасности не бывает. Как правило, всё квадратно-гнездовое, и набор ролей фиксирован в бизнес-модели (и зачастую ещё и продиктован регулятором).

Ролей может быть, да. А привилегии — их может быть очень много.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[18]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 09.04.25 06:55
Оценка:
Здравствуйте, ·, Вы писали:

S>>Это ж не настоящие ресурсы, а виртуальные. В параллельном ответе пояснил, что экспоненциальный взрыв наступает даже тогда, когда ресурс "один", но может быть отдан в 1024 разных конфигурациях.

·>Гы. Практически с таким же успехом можно засунуть bearer-токен в url, вот у тебя по ресурсу для каждой конфигурации.
Ну, да. Поэтому я и не назвал этот способ самым лучшим. Он приемлем тогда, когда у нас нет большого разнообразия пермиссий. Скажем, есть инвойс "с точки зрения плательщика", а есть тот же инвойс "с точки зрения получателя".
Вместо того, чтобы искусственно совмещать их в одном ресурсе и отдавать разный контент в зависимости от содержимого bearer token, делается два разных ресурса с похожей структурой.

·>Поход внутри сервиса может осуществляться в памяти того же процесса сервиса, в крайнем случае добавлением соответствующих JOIN в sql. А так у тебя будет куча сетевых вызовов... и представь это всё с мобилы через инет! Надо считать roundtrips.

Можно и считать. В разных задачах — разные приоритеты требований. Безопасность очень часто входит в конфликт с производительностью.

·>Каждую комбинацию тестировать не нужно. Нужно тестировать каждую привелегию. Два теста: "разрешено всё -> возвращается инфа о фигурантах", "разрешено всё, кроме инфы о фигурантах -> не возвращается инфа о фигурантах". Ну и отдельно матрица роли <-> привилегии.

Перед тем, как прийти к таким выводам, придётся как-то доказать независимость code path, которые приводят к появлению тех или иных результатов. Ну, или надеяться на эту независимость, и рисковать пролезанием false negative в каких-то особенных комбинациях привилегий.
·>Анонимный доступ это такая же роль, как и авторизированный внутренний юзер, внешний юзер, юзер из другого подразделения, админ, аудитор и т.п. И у каждой роли своё подмножество привилегий.
Это всё понятно.
S>>На практике, конечно же, таких мелкогранулярных систем безопасности не бывает. Как правило, всё квадратно-гнездовое, и набор ролей фиксирован в бизнес-модели (и зачастую ещё и продиктован регулятором).
·>Ролей может быть, да. А привилегии — их может быть очень много.
Повторюсь: это зависит от задачи. Модель привилегий и ролей — это всего лишь оптимизация процесса "пересмотр ролей". В зарегулированном бизнесе набор привилегий жёстко связан с ролью.
И это не просто так: бездумная раздача привилегий слишком легко позволяет создавать дырки там, где их не ожидаешь. Типа, напрямую посмотреть реквизиты произвольного контрагента я не могу (прав нет), но могу отправить ему 1 рубль через платёж по номеру телефона. А код формирования ресурса "квитанция о платеже" ничего о привилегиях на контрагентов не знает — у него свой набор привилегий, и вот я уже вижу все реквизиты встроенными прямо в тело квитанции.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[20]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 09.04.25 11:35
Оценка:
Здравствуйте, ·, Вы писали:

·>Или нет смешанных пермиссий. Скажем, получить список инвойсов за период, и получится что некоторые инвойсы где ты плательщик, а некоторые получатель.

Ну, вот на практике есть два разных списка: "инвойсы, которые выставил я", и "инвойсы, которые выставили мне". Всё, никаких чудес. Зачем делать единый список, а потом мужественно бороться с разнотипностью — .
Посмотрите на тот же Paypal API — он, хоть и не-REST, но устроен именно так.

·>Угу. А потом получится, что сегодня два, завтра внезапно понадобился третий, а через год у нас их уже 1024. Так что ещё и немножечко вредный.

Или не получится.

·>Интересно узнать какой такой магией фрагмент в урле повышает безопасность?

Очень просто: у нас нет "частичной безопасности", когда содержимое ресурса зависит от каких-то эфемерных вещей. У нас для запроса есть ровно два возможных ответа: 403 или 200.

·>Как ты будешь доказывать или тестировать безопасность 1024 конфигураций ресурса, пусть и виртуальных?

Очень просто. 2048 тестов, если уж у нас есть 1024 конфигурации ресурса. Но я повторю ещё раз: у нас не будет 1024 конфигураций. Этот способ не подходит для таких API, в которых есть 10 разных привилегий на один и тот же ресурс.

·>Урлы имеют смысл не для безопасности, а для кеширующих прокси (та самая производительность!). Но прокси на практике умеют работать только с анонимными ресурсами, у которых никаких пермов нет и можно смело всё отдавать всем. Только в этом случае есть гарантии не нарушения безопасности, т.к. нарушать собственно нечего.

На практике прокси прекрасно работают и с ресурсами, у которых cache-control: private. Это как раз позволяет каждому клиенту построить у себя частичную реплику распределённого состояния, и эффективно с ней взаимодействовать.

·>Доказывать эту независимость придётся ровно тем же способом, как и для твоих 1024 виртуальных ресурсов.

Ну так для 1024 ресурсов у нас будет 2048 тестов. Вам же кажется, что можно как-то обойтись 20 тестами.
·>Как твои виртуальные ресурсы помогут? Ну да, "GET /contragents?id=vasya" тебе запрещён, а "POST /payments?to=vasya" тебе выдаст квиток с инфой конртагента.
Виртуальные ресурсы помогут избавиться от иллюзии того, что данные Васи видны только тем, у кого есть привилегия "видеть данные Васи".
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[22]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 09.04.25 15:47
Оценка:
Здравствуйте, ·, Вы писали:
·>Я что-то перестал понимать о чём идёт речь. Вроде ты обсуждал возможность, что некий запрос какого-то ресурса, который выдаёт результат, раскрывающий детали других ресурсов. Т.е. когда например результирующий инвойс содержит приватные данные контрагента.
Нет, не содержит он никаких приватных данных контрагента. Инвойс, выставленный мне, ни в каком случае не показывает "закрытые" атрибуты отправителя. Независимо от моих "привилегий".
Инвойс, который выставил я, содержит дополнительные поля, которые на стороне получателя видны не будут. Опять же, мне они видны независимо от моих привилегий.
Доступ к "моим" инвойсам всем остальным пользователям закрыт не на уровне отдельных полей и привилегий, а на уровне всего субресурса
·>То что Paypal API устроен именно так... ну дык он для того, чтобы человеки хорошо понимали, а не для безопасности.
У пейпала с безопасностью всё в порядке.

·>Частичной нет, верно... да вообще никакой нет. Ну выдал ваш /invoices-for-me?id=123 json 200, в котором внезапно появится секция contragent: {homeAddress: {...}}, хотя разрешено только companyAddress выдавать. А ещё злоумышленник подменит урл на /my-invoices?id=123 и увидит вообще всё.

Нет, не увидит. Внутри ресурса /my-invoices/ нет никаких чужих инвойсов.
·>Если у тебя уже для такой тривиальной вещи 2048 тестов, то они абсолютно бесполезны, т.к. их никто не сможет проанализировать на безопасность и поддерживать в дальнейшем.
У меня складывается впечатление, что вы читаете не всё, что я пишу. Давайте вы ещё раз перечитаете всё с самого начала и внимательно посмотрите, с какими тезисами вы спорите.

·>А пофиг. Привилегии должны проверяться на источнике данных, а не на endpoint-е.

Забавная идея. Ну, вот у вас "источник данных" — реляционная БД. Какие вы там привилегии собрались проверять?

·>Ещё раз, ресурсы-сервисы-endpoints — это всё о том в каком формате обменяться данными по сети, и отношение к безопасности имеет чисто иллюзорное.

Ну, иллюзорную так иллюзорную.

·>Не понял. "cache-control: private" — это как раз инструкция отключающая кеш на прокси.

Я неправильно написал. Речь не о прокси, а о кэшировании на стороне клиента. Оно точно так же поднимает производительность, т.к. позволяет нам не отдавать неизменные данные; при этом оно никак не противоречит безопасности.


S>>Виртуальные ресурсы помогут избавиться от иллюзии того, что данные Васи видны только тем, у кого есть привилегия "видеть данные Васи".

·>А откуда такая иллюзия появится в принципе особенно в случае эвфемерных вещей??
Ну вот у вас она уже возникла.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[23]: Каких программ вам не хватает?
От: · Великобритания  
Дата: 10.04.25 11:20
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>·>Я что-то перестал понимать о чём идёт речь. Вроде ты обсуждал возможность, что некий запрос какого-то ресурса, который выдаёт результат, раскрывающий детали других ресурсов. Т.е. когда например результирующий инвойс содержит приватные данные контрагента.

S>Нет, не содержит он никаких приватных данных контрагента. Инвойс, выставленный мне, ни в каком случае не показывает "закрытые" атрибуты отправителя.
S>Независимо от моих "привилегий".
Закрытые для кого? Закрытость — вещь относительная. На какие-то атрибуты у тебя есть привилегии, на какие-то нет. У других пользователей будет другой доступ к атрибутам.

S>Инвойс, который выставил я, содержит дополнительные поля, которые на стороне получателя видны не будут. Опять же, мне они видны независимо от моих привилегий.

S>Доступ к "моим" инвойсам всем остальным пользователям закрыт не на уровне отдельных полей и привилегий, а на уровне всего субресурса
Каким образом закрыт-то? Заклятие наложено что-ли? Субресурс возвращает джсон, как ты ресурсом гарантируешь отстутствие там какого-нибудь contragent.homeAddress?

S>·>То что Paypal API устроен именно так... ну дык он для того, чтобы человеки хорошо понимали, а не для безопасности.

S>У пейпала с безопасностью всё в порядке.
Верю. Но не потому, что "API устроен именно так".

S>·>Частичной нет, верно... да вообще никакой нет. Ну выдал ваш /invoices-for-me?id=123 json 200, в котором внезапно появится секция contragent: {homeAddress: {...}}, хотя разрешено только companyAddress выдавать. А ещё злоумышленник подменит урл на /my-invoices?id=123 и увидит вообще всё.

S>Нет, не увидит. Внутри ресурса /my-invoices/ нет никаких чужих инвойсов.
Почему ты так решил? Ты так говоришь, что ресурс это какая-то охраняемая зона за колючей проволокой. Нет, это просто несколько байт в определённом месте хедера запроса, а обрабатывает всё это дело тот же самый условно питонячий код, что и для других ресурсов.

S>·>Если у тебя уже для такой тривиальной вещи 2048 тестов, то они абсолютно бесполезны, т.к. их никто не сможет проанализировать на безопасность и поддерживать в дальнейшем.

S>У меня складывается впечатление, что вы читаете не всё, что я пишу. Давайте вы ещё раз перечитаете всё с самого начала и внимательно посмотрите, с какими тезисами вы спорите.
Я спорю с тем, что ресурсы и урлы каким-то образом обеспечивают хоть какую-то безопасность. Что в зависимости от того куда поместить данные — в урл или хедер — вдруг внезапно станет "Зато всё безопасно".

S>·>А пофиг. Привилегии должны проверяться на источнике данных, а не на endpoint-е.

S>Забавная идея. Ну, вот у вас "источник данных" — реляционная БД. Какие вы там привилегии собрались проверять?
А чё так мелко? Сразу уж говори — источник данных — заряд на затворе транзистора. Да, там с привилегиями как-то не очень. Я вообще-то говорил о дизайне самого сервиса. БД — это уже другой сервис.

S>·>Не понял. "cache-control: private" — это как раз инструкция отключающая кеш на прокси.

S>Я неправильно написал. Речь не о прокси, а о кэшировании на стороне клиента. Оно точно так же поднимает производительность, т.к. позволяет нам не отдавать неизменные данные; при этом оно никак не противоречит безопасности.
А, так да. Но собственно тут обсуждалось "Безопасность очень часто входит в конфликт с производительностью", мой вопрос был "Интересно узнать какой такой магией фрагмент в урле повышает безопасность?". И в качестве ответа ты внезапно рассказываешь о "поднимает производительность" "не противоречит безопасности".

S>·>А откуда такая иллюзия появится в принципе особенно в случае эвфемерных вещей??

S>Ну вот у вас она уже возникла.
С чего ты взял? Никогда не было. А вот у тебя иллюзия в полный рост, цитирую: "чтобы границы безопасности совпадали с границами ресурсов. Потому что это и надёжнее,", "Зато всё безопасно". Нет, конечно. Надёжность тут не причём. Так просто удобнее и понятнее для человеков: не видно, что не должно быть видно. Т.е. чисто иллюзорные результаты.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 10.04.2025 11:24 · . Предыдущая версия .
Re[25]: Каких программ вам не хватает?
От: · Великобритания  
Дата: 11.04.25 12:24
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>·>Закрытые для кого? Закрытость — вещь относительная. На какие-то атрибуты у тебя есть привилегии, на какие-то нет. У других пользователей будет другой доступ к атрибутам.

S>Нет. Вот как раз предлагаемая вами модель чревата дырками и крайне тяжела в поддержке и верификации.
S>Я вам рассказываю практический замкнутый пример: нет никаких "привилегий на втрибуты". Есть два вида ресурсов. Доступ к каждому их них либо есть, либо нету.
Где есть два вида? В спеке?

S>·>Каким образом закрыт-то? Заклятие наложено что-ли? Субресурс возвращает джсон, как ты ресурсом гарантируешь отстутствие там какого-нибудь contragent.homeAddress?

S>Очень просто: contragent.homeAddress там нет вообще, вне зависимости от привилегий.
Как конкретно это гарантируется? Только не говори: "в API нету!". Не слыхал историй, когда какие-нибудь rest-endpoints случайно возвращали json с неожиданными полями. All tests passed, всё у всех работает.

S>·>Почему ты так решил? Ты так говоришь, что ресурс это какая-то охраняемая зона за колючей проволокой.

S>Потому что я так спроектировал, и это легко проверить как методом "белого ящика", так и "чёрного ящика".
Ну о чём и говорю. "Спроектировал" — это написал тонну word-документов и презентаций. И проверить легко, не спорю. А на самом деле json генерится питонячим кодом, который рефлексией вываливает всё что есть. И даже если всё было красиво в начале проекта, то после нескольких лет поддержки, рефакторингов и переписывания вдруг может что-то где-то вылезти.

S>·>Нет, это просто несколько байт в определённом месте хедера запроса, а обрабатывает всё это дело тот же самый условно питонячий код, что и для других ресурсов.

S>Если у вас так, то всё плохо. Попробуйте перепроектировать так, чтобы в одном коде не смешивалась обработка "своих" и "чужих" инвойсов. Человечество изобрело массу способов факторизации кода.
Может такое только в каких-то мелких проектах и пройдёт... И то никакой гарантии, что кто-то куда-то по ошибке не скопипастит. В серьёзных случаях у тебя будет 1024 вида своих и чужих.

S>·>А чё так мелко? Сразу уж говори — источник данных — заряд на затворе транзистора. Да, там с привилегиями как-то не очень. Я вообще-то говорил о дизайне самого сервиса. БД — это уже другой сервис.

S>Нет, БД — это не "другой сервис", это неотъемлемый компонент сервиса, оборудованного персистентным состоянием.
Надо технически смотреть, а не по поверпоинт презентациям. БД — компонент, если embedded, в лучшем случае. А так по сути другой сервис — формируешь запрос (query) и получаешь ответ (recordset). Ничем по факту от какого-нибудь rest не отличается, только протокол общения другой, вместо http у тебя sql.

S>Впрочем, можно спроектировать и так, как вы предлагаете — вынести БД в отдельный сервис, из которого торчит очень широкий контракт.

S>И, естественно, у него очень грубый набор привилегий. Ваша модель "давайте мы будем ограничивать доступ путём передачи пользовательского токена вдоль всей иерархии вызовов" работает примерно никогда.
Что значит "вынести"? Попробуй хоть как-нибудь не "вынести" какой-нибудь оракл из твоего питоячего сервиса.

S>Все практики безопасности как раз так и устроены, что у принципала X нету привилегий к "сырому" ресурсу A, но есть привилегии на доступ к "производному" ресурсу B. Сервис, выполняющий построение ресурса B, выполняется под принципалом Y, который имеет полные привилегии для A, но учитывает привилегии X при отдаче ему производного ресурса B.

S>Типичный пример применения концепции в рамках SQL99: пользователю нельзя видеть часть строк в таблице X. Мы не можем навесить привилегию на каждую строку. Зато можем сделать следующее:
S>1. Отбираем у пользователя привилегии на таблицу X
S>2. Строим на основе X представление Y, в котором добавлен предикат безопасности (типа select * from X where TotalAmount < 100000)
S>3. Выдаём пользователю привилегии на Y и указываем, что Y исполняется под привилегиями админа, а не пользователя.
S>Аналогично мы могли бы поступить и с ограничениями на колонки таблицы. Квадратно-гнездовая система, где чётко видна вся схема Y и легко проверить, что туда попадает, а что нет, как методом статического анализа, так и методом выполнения динамических тестов. Вы предлагаете заменить её на некий невнятный код "хранимой процедуры", которая возвращает всякий раз разный набор строк и колонок в зависимости от рантайм-содержимого параметров.
Я как-то более о практике. Статический анализ, конечно, хорошо... Но если тебе для этого придётся описывать "1024 виртуальных ресурсов" и писать 2048 тестов для них, но это не заработает на практике, хотя в теории, конечно, красота...

S>Нет, увы. Факторизация кода позволяет нам изолировать разные сценарии.

Если у тебя два сценария, то, конечно, это щастье. А вот когда сценариев 1024...

S>·>А, так да. Но собственно тут обсуждалось "Безопасность очень часто входит в конфликт с производительностью", мой вопрос был "Интересно узнать какой такой магией фрагмент в урле повышает безопасность?". И в качестве ответа ты внезапно рассказываешь о "поднимает производительность" "не противоречит безопасности".

S>Фрагмент в урле существует не сам по себе. Структура урла применятся для роутинга — выбора кода, который будет обслуживать поступивший запрос. Правила роутинга — простая, понятная логика, которую легко отладить и гарантировать отсутствие неожиданностей вроде "в ответ на запрос чужих инвойсов внезапно вызвался код по подготовке своих инвойсов".
S>Следующим шагом мы можем очень легко проверить, что код по подготовке "чужих" инвойсов никогда не возвращает приватных данных. Просто потому, что в этом коде вообще нет такой ветки, которая бы это делала.
Ну будет у тебя 1024 кусков кода и неподдерживаемая кодовая база.

S>В вашем же подходе в коде какая-то каша, отдаётся примерно произвольный набор атрибутов с соответствии с хитро устроенными предикатами, смешивающими проверку нескольких разных claims. Доказать, что код выдаёт корректное сочетание атрибутов для произвольного сочетания claims — та ещё задача.

У меня проверка конкретного claim одна же. Я писал выше. Будет что-то
Json getInvoiceForRest(..., securityContext, ...) {
  verifyPrivilegesForTheInvoice(..., securityContext, ...);//тут мы проверяем привилегии для данного инвойса
  return new Invoice {
    date: getInvoiceDate(...)
    contragent: getContragentDetails(..., securityContext, ...)// вот внутри этого метода и проверятся имеющиеся привилегии и вернутся только доступные данные конртагента.
    shipping: getShippingDetails(..., securityContext, ...)// вот внутри этого метода и проверятся имеющиеся привилегии и вернутся только доступные данные о доставке.
  }
}

Конечно, это не отменяет "Правила роутинга" и другие подобные подходы, а дополняет. Как тут Miroff швейцарский сыр упоминал.

S>·>С чего ты взял? Никогда не было. А вот у тебя иллюзия в полный рост, цитирую: "чтобы границы безопасности совпадали с границами ресурсов. Потому что это и надёжнее,", "Зато всё безопасно". Нет, конечно. Надёжность тут не причём. Так просто удобнее и понятнее для человеков: не видно, что не должно быть видно. Т.е. чисто иллюзорные результаты.

S>Это оттого, что я плохо объясняю. Разница в подходах есть. Понятно, что достичь приемлемого результата можно в любом подходе, но стоимость получается разной. Когда границы безопасности совпадают с границами ресурсов, это сильно упрощает доказательство корректности. Я выше примерно написал, каким именно способом. Но вы можете мне не верить и писать более дорогостоящие и трудноподдерживаемые системы — у нас же нет архитектурной полиции
Ну я просто написал когда этот твой способ не работает. Но я, конечно, верю, что в некоторых случаях и твой способ работает. Но это не значит, что он универсальный всемогутер.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[26]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 12.04.25 06:20
Оценка:
Здравствуйте, ·, Вы писали:

·>Где есть два вида? В спеке?

Да, прямо в спеке.

·>Как конкретно это гарантируется? Только не говори: "в API нету!". Не слыхал историй, когда какие-нибудь rest-endpoints случайно возвращали json с неожиданными полями. All tests passed, всё у всех работает.

Я вроде написал, как. Историй про то, как all tests passed, а результат не соответствует — нет, не слышал.
Но вы отклоняетесь: если у вас такие кривые тесты, которые пропускают наличие лишних полей, то в системе с "привилегией на атрибуты" у вас тем более будет бардак.

S>>Потому что я так спроектировал, и это легко проверить как методом "белого ящика", так и "чёрного ящика".

·>Ну о чём и говорю. "Спроектировал" — это написал тонну word-документов и презентаций.
Нет конечно. "Спроектировал" — это построил фреймворк, в котором не так много возможностей накосячить. Архитектура софта не исчерпывается "внешними" требованиями.

·>И проверить легко, не спорю. А на самом деле json генерится питонячим кодом, который рефлексией вываливает всё что есть.

Вот это ваше "На самом деле" означает, что вы пытаетесь тестировать код как чёрный ящик. Это не единственный (и не самый эффективный) способ обеспечения качества.
Надо смотреть внутрь, и желающих генерить всё что есть через рефлексию бить палкой на code review.
·>Может такое только в каких-то мелких проектах и пройдёт...
Вот то, что вы предлагаете, как раз и проходит только в мелких проектах. В крупных проектах требуется более строгий контроль, чем "я проверил всю динамику глазами и всё сошлось".
·>И то никакой гарантии, что кто-то куда-то по ошибке не скопипастит.
Гарантия предотвращения ошибочных копипастов достигается юнит-тестированием. Преимущество тут в том, что в коде нет ветвлений — поэтому нам не надо беспокоиться, что "вдруг" в результате образуется сontragent: {homeAddress: {...}}. Достаточно 1 (одного) теста на то, что такого в json нету, и вопрос закрыт.
·>В серьёзных случаях у тебя будет 1024 вида своих и чужих.
Это как раз в несерьёзных случаях. Серьёзные случаи — это как раз какой-нибудь банковский API. И вот там всё именно так, как я сказал. Потому что нельзя позволить ни криворукому девелоперу нечаянно проверить не ту привилегию, так и криворукому админу нечаянно выдать кому-то не ту привилегию.

·>Надо технически смотреть, а не по поверпоинт презентациям. БД — компонент, если embedded, в лучшем случае. А так по сути другой сервис — формируешь запрос (query) и получаешь ответ (recordset). Ничем по факту от какого-нибудь rest не отличается, только протокол общения другой, вместо http у тебя sql.

Верно мыслите, так всё и есть.

·>Что значит "вынести"? Попробуй хоть как-нибудь не "вынести" какой-нибудь оракл из твоего питоячего сервиса.

Ну вот так и не выносим. Оракл является подробностью реализации этого "питонячьего сервиса" и ниоткуда больше не виден. Впрочем, это может быть и не оракл — "питонячьему сервису" с запасом может хватить sqlite.

·>Я как-то более о практике.

Это я о практике, а вы рассказываете какие-то сказки. Ну, точнее вы предлагаете заведомо неудачные решения, через которые мы проходили по нескольку раз начиная ещё с девяностых.
·>Статический анализ, конечно, хорошо... Но если тебе для этого придётся описывать "1024 виртуальных ресурсов" и писать 2048 тестов для них, но это не заработает на практике, хотя в теории, конечно, красота...
Не придётся. Я уже писал причины.
·>Если у тебя два сценария, то, конечно, это щастье. А вот когда сценариев 1024...
Когда у вас 1024 сценария, то деваться некуда. Но чаще это означает, что кто-то не справился с факторизацией сценария, в котором есть 8 отдельных подсценариев, каждый из которых работает независимо и его можно протестировать отдельно, т.к. там вариантов гораздо меньше.

·>Ну будет у тебя 1024 кусков кода и неподдерживаемая кодовая база.

И какая альтернатива?

·>У меня проверка конкретного claim одна же. Я писал выше. Будет что-то

·>
·>Json getInvoiceForRest(..., securityContext, ...) {
·>  verifyPrivilegesForTheInvoice(..., securityContext, ...);//тут мы проверяем привилегии для данного инвойса
·>  return new Invoice {
·>    date: getInvoiceDate(...)
·>    contragent: getContragentDetails(..., securityContext, ...)// вот внутри этого метода и проверятся имеющиеся привилегии и вернутся только доступные данные конртагента.
·>    shipping: getShippingDetails(..., securityContext, ...)// вот внутри этого метода и проверятся имеющиеся привилегии и вернутся только доступные данные о доставке.
·>  }
·>}
·>

Прекрасно. Видна некоторая попытка факторизации. Которая, к слову, совершенно бесполезна в вашем подходе с чёрным ящиком: а вдруг завтра кто-то заменит всю вашу кунсткамеру на "питонячий код, который по рефлексии вываливает сразу всё"?
Ну, и вредна конечно тоже: потому что завтра кто-то в эксплуатации не нарулит кому-то такой набор привилегий, который не даёт выполнить реальный сценарий. Зачем так делать — непонятно. Ну, кроме "нам было лень проектировать, и мы свалили ответственность на кого-то другого.

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

Скорее наоборот: бывают задачи с низкой ответственностью, где можно игнорировать best practices и писать с надеждой на авось.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Отредактировано 13.04.2025 2:39 Sinclair . Предыдущая версия .
Re[4]: Помогите правильно спроектировать микросервисное приложение
От: busk  
Дата: 16.04.25 06:30
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Можем посмотреть на пример:


S>Сервис номер 2 расположен по адресу https://graph.microsoft.com/{version}/{resource}?{query-parameters}.

S>Токены для него получаем из сервиса номер 1 по адресу https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize

S>Наличие в сервисе 1 авторизации означает, что у вас сервис номер один возвращает в токене не просто идентити пользователя, а и некий набор привилегий, которые сервис номер 2 считывает для принятия решения о том, чего пользователю делать можно, а чего — нельзя. В частности, для Microsoft Graph мы прямо в запросе авторизационного токена сервису логина указываем список scopes, к которым хотим получить доступ. И в случае успеха, токен будет содержать информацию об этом.


а вот у меня получается 2 бэкенд сервиса, а на фронте тоже 2 реакт приложения, или на фронте одним можно разрулить?
Re[5]: Помогите правильно спроектировать микросервисное приложение
От: busk  
Дата: 16.04.25 07:11
Оценка:
Здравствуйте, busk, Вы писали:


S>>Наличие в сервисе 1 авторизации означает, что у вас сервис номер один возвращает в токене не просто идентити пользователя, а и некий набор привилегий, которые сервис номер 2 считывает для принятия решения о том, чего пользователю делать можно, а чего — нельзя. В частности, для Microsoft Graph мы прямо в запросе авторизационного токена сервису логина указываем список scopes, к которым хотим получить доступ. И в случае успеха, токен будет содержать информацию об этом.


B>а вот у меня получается 2 бэкенд сервиса, а на фронте тоже 2 реакт приложения, или на фронте одним можно разрулить?


вопрос еще связан с тем, что у меня SPA а если будет 2 фронт приложения то тут же получается будет обновление страницы после страницы логина на основное приложение
Re[6]: Помогите правильно спроектировать микросервисное приложение
От: Qulac Россия  
Дата: 16.04.25 07:26
Оценка:
Здравствуйте, busk, Вы писали:

B>Здравствуйте, busk, Вы писали:



S>>>Наличие в сервисе 1 авторизации означает, что у вас сервис номер один возвращает в токене не просто идентити пользователя, а и некий набор привилегий, которые сервис номер 2 считывает для принятия решения о том, чего пользователю делать можно, а чего — нельзя. В частности, для Microsoft Graph мы прямо в запросе авторизационного токена сервису логина указываем список scopes, к которым хотим получить доступ. И в случае успеха, токен будет содержать информацию об этом.


B>>а вот у меня получается 2 бэкенд сервиса, а на фронте тоже 2 реакт приложения, или на фронте одним можно разрулить?


B>вопрос еще связан с тем, что у меня SPA а если будет 2 фронт приложения то тут же получается будет обновление страницы после страницы логина на основное приложение


А зачем так делать? Фронт можно один оставить, просто сервис на беке будет сам вызывать сервис авторизации когда это надо.
Программа – это мысли спрессованные в код
Re[7]: Помогите правильно спроектировать микросервисное приложение
От: busk  
Дата: 16.04.25 11:39
Оценка:
Здравствуйте, Qulac, Вы писали:



B>>>а вот у меня получается 2 бэкенд сервиса, а на фронте тоже 2 реакт приложения, или на фронте одним можно разрулить?


B>>вопрос еще связан с тем, что у меня SPA а если будет 2 фронт приложения то тут же получается будет обновление страницы после страницы логина на основное приложение


Q>А зачем так делать? Фронт можно один оставить, просто сервис на беке будет сам вызывать сервис авторизации когда это надо.


а я думал что фронт тоже распиливают на отдельные сервисы, но подумал, что для SPA не получится тогда сделать без третьего агрегирующего фронт сервиса.
Тогда одно на фронте, понял
Re[8]: Помогите правильно спроектировать микросервисное приложение
От: Miroff Россия  
Дата: 16.04.25 11:44
Оценка:
Здравствуйте, busk, Вы писали:

B>а я думал что фронт тоже распиливают на отдельные сервисы, но подумал, что для SPA не получится тогда сделать без третьего агрегирующего фронт сервиса.


Бывает такое, микрофронтенд называется. Идея, в целом, довольно грамотная с точки зрения не превращать фронт в неподдерживаемое месиво. А еще бывает backend for frontend (BFF)
Re[8]: Помогите правильно спроектировать микросервисное приложение
От: Qulac Россия  
Дата: 16.04.25 11:55
Оценка:
Здравствуйте, busk, Вы писали:

B>Здравствуйте, Qulac, Вы писали:




B>>>>а вот у меня получается 2 бэкенд сервиса, а на фронте тоже 2 реакт приложения, или на фронте одним можно разрулить?


B>>>вопрос еще связан с тем, что у меня SPA а если будет 2 фронт приложения то тут же получается будет обновление страницы после страницы логина на основное приложение


Q>>А зачем так делать? Фронт можно один оставить, просто сервис на беке будет сам вызывать сервис авторизации когда это надо.


B>а я думал что фронт тоже распиливают на отдельные сервисы, но подумал, что для SPA не получится тогда сделать без третьего агрегирующего фронт сервиса.

B>Тогда одно на фронте, понял

Вариант с распиливанием фронта возможен, особенно для систем с устанавливаемыми плагинами.
Программа – это мысли спрессованные в код
Re[12]: Каких программ вам не хватает?
От: Константин Л. Франция  
Дата: 16.04.25 14:34
Оценка:
Здравствуйте, Miroff, Вы писали:

[]

M>Опять же, можешь раскрыть тему? Пейджинг это простая штука если перестать думать о нем, как о RPC и начать думать как об отдельном ресурсе. Ты СОЗДАЕШЬ отдельный объект "поисковый запрос" и в ответ получаешь список страниц с результатами этого запроса. И, внезапно, у тебя уже нет проблем со стабильностью, сортировки, изменению состава страниц, кэшированию и т.п. Результат фиксируется в момент создания запроса и далее до нового поиска уже не меняется.


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

[]
Re[13]: Каких программ вам не хватает?
От: Константин Л. Франция  
Дата: 16.04.25 14:40
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Например, можно воткнуть reverse proxy перед сервером приложения, и тогда он сможет снять значительную часть нагрузки с сервера.

S>Как только мы начинаем менять представление объекта в зависимости от пользователя, о кэшировании можно забыть.

чет мне кажется никто ничего уже давно не кеширует

ну и

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


тоже повсеместная практика
Re[15]: Каких программ вам не хватает?
От: Константин Л. Франция  
Дата: 16.04.25 14:48
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Вариантов три:

S>1. При отдаче текста постановления смотрим в токен пользователя, и либо заменяем все имена плейсхолдерами, либо вставляем как надо.
S>2. Делаем два ресурса: "анонимизированное постановление", "полноценное постановление". Анонимный доступ ко второму получает 401, аутентифицированный доступ без прав на данное дело получает 403.
S>3. Делаем два ресурса: постановление, в "тексте" которого есть ссылки на фигурантов, каждый из которых — самостоятельный ресурс. Постановления отдаём всем желающим, детали фигурантов — только авторизованным пользователям. Остальные получают 403.
S>Как по мне, так первый вариант, очевидно, самый-самый плохой. Он плохо масштабируется, и крайне плохо проверяется на корректность.


Он плохо масштабируется, и крайне плохо проверяется на корректность.


вообще не очевидно. в любом случае тебе надо сделать фильтр данных, как ты его сделал и на каком этапе не так важно. введением магического второго ресурса проблема фильтра никуда не уйдет. и про комбинаторный взрыв тебе правильно сказали. Номер 1 самый рабочий и адекватный — по токену получаем список пермиссий и по ним фильтруем резалтсет.

И вообще зря ты критикуешь "клиентскую секьюрити", просто она должна дублироваться серверной. Нормально возвращать на клиента список допустимых действий для оптимизации, но HATEOAS для этого не нужен и на сервере тоже должны быть чеки.
Re[16]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.04.25 16:37
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>вообще не очевидно. в любом случае тебе надо сделать фильтр данных, как ты его сделал и на каком этапе не так важно.

Не, не в любом. Только в том, если кому-то нужны дополнительные подробности.
КЛ>введением магического второго ресурса проблема фильтра никуда не уйдет.
Я не очень понимаю, что такое "проблема фильтра". Магический второй ресурс означает, что есть два ресурса: один даже join в базе не делает с таблицами "смежных сущностей", другой делает джойн, но проверяет ровно одну пермиссию в токене, а не отдаёт 2^10 вариантов в зависимости от хидера.

КЛ>и про комбинаторный взрыв тебе правильно сказали. Номер 1 самый рабочий и адекватный — по токену получаем список пермиссий и по ним фильтруем резалтсет.

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

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

Да, тут я согласен.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[18]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.04.25 06:15
Оценка:
Здравствуйте, Константин Л., Вы писали:
КЛ>ну когда не нужны тогда и фильтр не нужен, верно?
Вот эту фразу не понял.

КЛ>фильтр — это способ либо собрать либо очистить ресурс. принципиальной разницы между виртуальными ресурсами (как в твоем случае) и одним ресурсом нет вообще. все равно где-то придется ответить на вопрос какие данные возвращаем

Принципиальная разница тут только в надёжности. Меньше ветвлений в коде — меньше способов в них напороть.
В остальном — да, другие решения (типа расположение фильтра "перед запросом" или "после результата") сильнее влияют на параметры итогового сервиса.

S>>Ну я бы так дизайнить не стал. Соображения я привёл. У каждого они свои — вон кто-то хочет просто написать универсальный код на питоне, который через рефлексию всю базу наружу отдаёт, а пермиссии берёт из токена.

КЛ>это детали, можно и в базе пермиссии проверять
Ну... в целом-то да, можно и в базе. Но у меня возникают вопросы прежде всего к надёжности такой модели. Слишком много движущихся частей => слишком много возможных путей исполнения и вариантов, когда всё может пойти "не так". При этом большинство из возможных конфигураций как настроек, так и устройства кода, являются заведомо некорректными.
По большому счёту, это является одной из причин, по которой сейчас не принято выставлять в интернет напрямую базу данных.
Казалось бы — ачего, давайте пермиссий навесим, и алга. Что-то есть в СУБД из коробки, что-то можно докрутить при помощи хранимок и представлений. Если всё делать аккуратно, получим могучую REST-подобную систему.
Однакож, нет, не делают так. Обожглись, и клиент-сервер остался только внутри "безопасных периметров", а в открытый интернет торчит исключительно трёхзвенка.
Собственно, все эти идеи "давайте отдавать базу через рефлексию" и есть способ завернуть SQL в HTTP, и ничего полезного архитектуре не добавляют.
Более продуктивный способ, имхо, всё же делить логику по уровням так, чтобы на каждом уровне по максимуму использовать его преимущества.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[19]: Каких программ вам не хватает?
От: Константин Л. Франция  
Дата: 17.04.25 09:05
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Константин Л., Вы писали:

КЛ>>ну когда не нужны тогда и фильтр не нужен, верно?
S>Вот эту фразу не понял.

вот:

КЛ>вообще не очевидно. в любом случае тебе надо сделать фильтр данных, как ты его сделал и на каком этапе не так важно.

S>Не, не в любом. Только в том, если кому-то нужны дополнительные подробности.

не нужны подробности -> не нужен фильтр. нужны -> нужен фильтр или доп-ресурс.

КЛ>>фильтр — это способ либо собрать либо очистить ресурс. принципиальной разницы между виртуальными ресурсами (как в твоем случае) и одним ресурсом нет вообще. все равно где-то придется ответить на вопрос какие данные возвращаем

S>Принципиальная разница тут только в надёжности. Меньше ветвлений в коде — меньше способов в них напороть.

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

S>В остальном — да, другие решения (типа расположение фильтра "перед запросом" или "после результата") сильнее влияют на параметры итогового сервиса.


S>>>Ну я бы так дизайнить не стал. Соображения я привёл. У каждого они свои — вон кто-то хочет просто написать универсальный код на питоне, который через рефлексию всю базу наружу отдаёт, а пермиссии берёт из токена.

КЛ>>это детали, можно и в базе пермиссии проверять
S>Ну... в целом-то да, можно и в базе. Но у меня возникают вопросы прежде всего к надёжности такой модели. Слишком много движущихся частей => слишком много возможных путей исполнения и вариантов, когда всё может пойти "не так". При этом большинство из возможных конфигураций как настроек, так и устройства кода, являются заведомо некорректными.

я до сих пор не понимаю как добавление ресурсов принципиально что-то меняет в твоей модели и что это у меня за такая модель?

S>По большому счёту, это является одной из причин, по которой сейчас не принято выставлять в интернет напрямую базу данных.


а кто такое предлагает? я такое не предлагаю. и, кстати, популярный graphql именно это и делает, насколько я понимаю и я это осуждаю.

S>Казалось бы — ачего, давайте пермиссий навесим, и алга. Что-то есть в СУБД из коробки, что-то можно докрутить при помощи хранимок и представлений. Если всё делать аккуратно, получим могучую REST-подобную систему.


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

S>Однакож, нет, не делают так. Обожглись, и клиент-сервер остался только внутри "безопасных периметров", а в открытый интернет торчит исключительно трёхзвенка.

S>Собственно, все эти идеи "давайте отдавать базу через рефлексию" и есть способ завернуть SQL в HTTP, и ничего полезного архитектуре не добавляют.
S>Более продуктивный способ, имхо, всё же делить логику по уровням так, чтобы на каждом уровне по максимуму использовать его преимущества.

graphql! и да, это бред, но это не то, что я предлагаю
Re[27]: Каких программ вам не хватает?
От: Константин Л. Франция  
Дата: 17.04.25 11:46
Оценка:
Здравствуйте, Sinclair, Вы писали:

[]

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

S>Скорее наоборот: бывают задачи с низкой ответственностью, где можно игнорировать best practices и писать с надеждой на авось.

сколько систем ты так сделал и сколько у них юзеров и ролей?
Re[20]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.04.25 12:47
Оценка:
Здравствуйте, Константин Л., Вы писали:


КЛ>>вообще не очевидно. в любом случае тебе надо сделать фильтр данных, как ты его сделал и на каком этапе не так важно.

S>>Не, не в любом. Только в том, если кому-то нужны дополнительные подробности.
КЛ>не нужны подробности -> не нужен фильтр. нужны -> нужен фильтр или доп-ресурс.
Вы фильтром называете проекцию или что-то ещё?

КЛ>ну смотри, у тебя два юзкейса — полный ресурс или урезанный.

Строго говоря, у нас может быть и больше юзкейзов.

КЛ>даже если ты будешь разруливать их через отдельные ресурсы где-то будет ветвление на создание (фильтрацию, сборку, как угодно) одного и другого.

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

КЛ>я до сих пор не понимаю как добавление ресурсов принципиально что-то меняет в твоей модели и что это у меня за такая модель?

У вас модель, в которой заранее неизвестно, какая структура ресурса будет получена при обращении по тому или иному ендпоинту. Она типа "динамически" определяется где-то внутри кода непрозрачными правилами.

КЛ>а кто такое предлагает? я такое не предлагаю. и, кстати, популярный graphql именно это и делает, насколько я понимаю и я это осуждаю.

Нет, graphQL делает не это.

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

Как мы это будем тестировать?

КЛ>graphql! и да, это бред, но это не то, что я предлагаю

В graphQL принято несколько неудачных решений, но не потому, что он "выставляет наружу БД".
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[21]: Каких программ вам не хватает?
От: Константин Л. Франция  
Дата: 17.04.25 15:17
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Вы фильтром называете проекцию или что-то ещё?


да

КЛ>>ну смотри, у тебя два юзкейса — полный ресурс или урезанный.

S>Строго говоря, у нас может быть и больше юзкейзов.

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

КЛ>>даже если ты будешь разруливать их через отдельные ресурсы где-то будет ветвление на создание (фильтрацию, сборку, как угодно) одного и другого.

S>Если я это делаю явным образом, то у меня это ветвление покрывается системой типов, и его статически контролирует компилятор ещё до того, как запустятся тесты.

система типов это только про поля, а что со строками?
это не гибко

КЛ>>я до сих пор не понимаю как добавление ресурсов принципиально что-то меняет в твоей модели и что это у меня за такая модель?

S>У вас модель, в которой заранее неизвестно, какая структура ресурса будет получена при обращении по тому или иному ендпоинту. Она типа "динамически" определяется где-то внутри кода непрозрачными правилами.

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

пример — у юзера есть 5 основных воркфлоу, в один из которых входит создание внутренних отчетов из таблицы rows, в другой создание анонимизтированных отчетов для регулятора.
внутренний отчет показывает конфиденциальные данные, для регулятора отрезает их.
опиши security-модель для такого? сколько ролей? как все работает?


КЛ>>а кто такое предлагает? я такое не предлагаю. и, кстати, популярный graphql именно это и делает, насколько я понимаю и я это осуждаю.

S>Нет, graphQL делает не это.

а что он делает?

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

S>Как мы это будем тестировать?

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

КЛ>>graphql! и да, это бред, но это не то, что я предлагаю

S>В graphQL принято несколько неудачных решений, но не потому, что он "выставляет наружу БД".

да, но выставляет наружу псевдо-бд
Отредактировано 17.04.2025 15:38 Константин Л. . Предыдущая версия .
Re[28]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.04.25 17:10
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>и как и откуда в эту схему кладутся данные?

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

КЛ>я, кажется, начинаю понимать — по dto на роль, ORM, отдельные endpoints и вуаля?

Конечно.
КЛ>но тут есть 2 проблемы — работает только на простых security моделях,
Модели безопасности и должны быть простыми. Сложные модели снижают надёжность. Парадокс в том, что когда стоимость ошибки в секурити низкая, на неё можно просто забить. А когда высокая, то сложные модели слишком рискованны.
КЛ>и никак не решает проблем, когда внутри этого dto есть многокардинальные поля (массивы etc, которые тоже надо фильтровать по роли).
Их не надо фильтровать по роли. Это плохая идея — слишком легко напороть.
КЛ>ну есть еще конечно другой вариант — когда очень много денег и очень много ответственности и надо прям все по-красоте. но это не индустриальный стандарт
Да, я и говорю про серьёзные приложения, где ответственности много. А если её мало, то примерно любая секурити подойдёт.

КЛ>я вообще про микросервисы ничего не писал, я утверждаю, что ты делаешь ту же самую работу по проверке пермиссий для резалтсета, только криво, а мы прямо)

Ну, с моей точки зрения криво делаете вы.
Получившимся API совершенно невозможно пользоваться, кроме как напрямую выкладывать его в ГУЙ. Любой сервис, который пытается стать клиентом этого API, вынужден жить в постоянной готовности получить не данные, а фигу.
И как-то осмысленно объяснять пользователю, что "у тебя, брат, нет пермиссии на атрибут 'НДС', сходи к админу, попроси, чтоб выдал". Ну, либо (что скорее всего) внезапно падать с internal error 500, потому что внутрях там NullReferenceException. Разобраться, что там стало первопричиной, потребует привлечения дорогостоящего саппорта. Так что в пет проджектах, где пользователей меньше, чем ролей и пермиссий вместе взятых — велком, можно и так. А для чего-то серьёзного, где нужна предсказуемость работы — увольте.

КЛ>вот и начинается, часть пермиссий через средства субд, часть сбоку, чтд

Где это я предложил часть пермиссий через средства СУБД? Я вам привёл стандартный способ разделения доступа "построчно" без использования row-level security.

КЛ>так у вас нет row-level permission же

Я вроде дал пошаговое описание того, как решается проблема отсутствия row-level permissions в RDBMS. Причём не как рекомендацию использовать эту схему, а как пример реализации "послойной" безопасности.
Точно такие же рецепты применяются и в сервисах.
То есть токен пользователя у нас роляет только во фронт-сервисе. Когда пользователь U запрашивает API сервиса A, а сервис A в рамках этого запроса стучится в сервис B, то никакие токены U в этот B не передаются. У U вообще нет никакого доступа до сервиса B. В этот сервис обращается A, под собственным токеном.
Поэтому идея "а давайте у нас инвойс будет содержать данные контрагента если у вызывающего пользователя есть пермиссия на этого контрагента" сразу идёт навзничь.
У вызываюшего пользователя нет никаких пермиссий на контрагента — господь упаси. А вот право видеть реквизиты получателя платежа по выставленному счёту у него есть в силу федерального закона.


КЛ>" SQL исполнялся в контексте безопасности конечного пользователя " — вот это вообще что такое?

Это когда мы заводим для пользователя №44487 виндовый аккаунт, даём этому аккаунту права на SQL базу с табличками forums, topics, replies, и marks, при логине на сайт создаём виндовую сессию, и все запросы в SQL Server выполняем через новое соединение под правами этого виндового аккаунта.

КЛ>что тут ты понимаешь под контекстом? а когда ты делаешь эти свои лишние телодвижения из 3х пунктов, ты разве не мапишь "контексте безопасности конечного пользователя, пришедшего из интернета" на конкретную роль в базе?

Это был иллюстративный пример про послойную безопасность. Там как раз фишка в том и есть, что реальный select исполняется под правами админа, а не конкретного конечного пользователя.

КЛ>sql исполняется от админа всегда и точка. резалсеты зависят от пермиссий юзера из интернета.

Воот, уже лучше.

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

S>>"Его" — это кого? Поле?

КЛ>строку, опечатка конечно


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

S>>Можете привести пример такого select? Я вроде понимаю, о чём вы пишете, но уверенности нет.

КЛ>select * from rows r

КЛ>join rows_perms p on r.id = p.r_id
КЛ> where p.perm = 'row_read' and p.user_id = :userid
Прекрасно. Вы себе представляете производительность такого решения? Когда у нас табличка на пару миллионов строк, и есть тысяча пользователей с частично пересекающимися правами на эти строки?
КЛ>или
КЛ>select * from rows r where r.group_id in :user_groups
А как же "любое сочетание ролей и пермиссий"? Вы прибиваете доступ к r только к одной роли; невозможно выдать доступ к конкретной строке нескольким разным группам.
Собственно, вы изобретаете нормальную изоляцию на основе бизнес-правил, только задом наперёд.
Потому что в прямом направлении мы не стесняемся назвать этот абстрактный group_id своим именем.
Например,
select * from topics t where t.owner_id = :user_id

Или
select * from invoices i where i.sender_organization = :current_org_id


Это — совершенно нормальная история, которая работает и применяется.
КЛ>userid/user_groups резолвятся по токену из запроса
Ну, вы же только что собирались сделать универсальную схему, которая работает с любым количеством пермиссий и ролей. А получается вполне себе узкоспециализированная штука.

КЛ>да как угодно, при том, что работает тот самый швейцарский сыр, про который тут упоминали —

КЛ>возможность вообще что-то читать из таблицы rows проверяется до отправки sql в базу. все запросы от админа. в базе никакой встроенной security не используется, потому что, опять же, нет нормально row-level security встроенного. С полями — либо динамически генеришь строку sql, либо jooq (предпочтительнее)
КЛ>select fields from field_perm where field_perm.perm = 'row_read_for_report'
КЛ>и дальше ипользуешь результат для генерации верхних селектов с конкретными полями.
КЛ>либо уже просто в коде фильтруешь
Непонятно. Как я смогу получить разный набор полей для разных строк одной и той же таблицы? Речь-то шла именно об этом — что состав результата определяется не объектом, а правами пользователя на него.

КЛ>ABAC, это когда ты принимаешь решение не только от роли, но и контекста — времени запроса и пт. То есть довольно часто.

Я в курсе.

КЛ>да, но ничего с точки зрения трейдоффа разработка/результат не придумали. открываешь google aim и видишь и роли, и отдельные пермиссии.

Надо внимательно смотреть на то, как именно используются эти роли и пермиссии. Потому что я так-то не против ролей и пермиссий; я против смешивания мух и котлет.
И если я запрашиваю, допустим, GET /resources/{resourceId}?$include(usageHistory), а у меня нет пермиссий смотреть usageHistory по этому ресурсу, я получаю не пустую историю и не JSON с "вырезанным" атрибутом, а честный 403. А если у меня пермиссия есть, то я могу полагаться на то, что в результате будет атрибут usageHistory с описанной в схеме структурой.
В итоге сторонний сервис, который потребляет мой API, может выдавать осмысленные ошибки, которые можно быстро исправить. А не просто падать оттого, что его авторы тестировались с аккаунтом, у которого были все нужные пермиссии, и понятия не имели, что у кого-то пермиссия на usageHistory на какой-то отдельный объект может быть отобрана.

Обратите внимание — это то самое "разведение ресурсов по разным URL", над которым вы так потешались.


КЛ>много ролей, много разных пермиссий

Количество ни на что не влияет.

КЛ>ага, то есть любой смоук тест у нас в лобой системе обнаруживает любую проблему?

Нет, только детерминистические вещи.

КЛ>и никто ее не делает, потому что это невозможно поддерживать

Надо просто уметь это готовить.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[22]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.04.25 17:23
Оценка:
Здравствуйте, Константин Л., Вы писали:
S>>Вы фильтром называете проекцию или что-то ещё?
КЛ>да
Хорошо.

КЛ>вам и говорят, когда много, тогда у вас проблемы.

У нас нет никаких проблем.

КЛ>система типов это только про поля, а что со строками?

КЛ>это не гибко
Излишняя гибкость, в целом, только вредит. Но фильтрация, в отличие от проекции, не нарушает никаких инвариантов.
Поэтому в ней запросто можно учитывать предикаты, в том числе и построенные на токене пользователя.
По-прежнему у нас границы безопасности совпадают с границами ресурса.
Смотрите: вот я делаю какой-нибудь
GET /invoices/

И мне приезжает какой-то список инвойсов. Как правило — без деталей, только ссылки.
И если я пойду по этим ссылкам, типа GET /invoices/32423423423/, то скорее всего буду получать 200 Ok.
А вот те из инвойсов, на которые у меня прав нет, дадут при прямом обращении 403 либо 404, и в общем списке фигурировать не будут.

КЛ>еше раз — пермисии это такой же фильтр данных как и остальные. разрулить их системой типов хорошо не получится.

Прекрасно получится.

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

КЛ>внутренний отчет показывает конфиденциальные данные, для регулятора отрезает их.
КЛ>опиши security-модель для такого? сколько ролей? как все работает?
Пока что роль ровно одна. Всё работает так, как написано. Причин изобретать разные роли тут нет.
Для проектирования безопасности у нас недостаточно вводных.

КЛ>а что он делает?

Он делает возможность формировать запросы к иерархии объектов, без всех плюшек REST.

КЛ>а как вы тестируете все остальное, что отдает данные на основании пользовательского контекста?



КЛ>да, но выставляет наружу псевдо-бд

Есть много разных способов выставить наружу псевдо-бд, и не все из них одинаково полезны.
Надо понимать, какая проблема решается.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[29]: Каких программ вам не хватает?
От: Константин Л. Франция  
Дата: 17.04.25 18:02
Оценка:
Здравствуйте, Sinclair, Вы писали:

КЛ>>и как и откуда в эту схему кладутся данные?

S>Маппером, который сгенерирован по типу данных. Кладутся из DTO, который поднят из базы.

то есть пермисии определяются декларативно просто наличием полей в типе? ну-ну

КЛ>>я, кажется, начинаю понимать — по dto на роль, ORM, отдельные endpoints и вуаля?

S>Конечно.

вау

КЛ>>но тут есть 2 проблемы — работает только на простых security моделях,

S>Модели безопасности и должны быть простыми. Сложные модели снижают надёжность. Парадокс в том, что когда стоимость ошибки в секурити низкая, на неё можно просто забить. А когда высокая, то сложные модели слишком рискованны.

"хорошо это когда хорошо".

КЛ>>и никак не решает проблем, когда внутри этого dto есть многокардинальные поля (массивы etc, которые тоже надо фильтровать по роли).

S>Их не надо фильтровать по роли. Это плохая идея — слишком легко напороть.

тогда _какую_ проблему решают твои виртуальные ресурсы? никакую

КЛ>>ну есть еще конечно другой вариант — когда очень много денег и очень много ответственности и надо прям все по-красоте. но это не индустриальный стандарт

S>Да, я и говорю про серьёзные приложения, где ответственности много. А если её мало, то примерно любая секурити подойдёт.

серьезные приложения это софт для АЭС, там можно. В 99 процентах других случаев твоя модель не работает, такая моя оценка

КЛ>>я вообще про микросервисы ничего не писал, я утверждаю, что ты делаешь ту же самую работу по проверке пермиссий для резалтсета, только криво, а мы прямо)

S>Ну, с моей точки зрения криво делаете вы.
S>Получившимся API совершенно невозможно пользоваться, кроме как напрямую выкладывать его в ГУЙ. Любой сервис, который пытается стать клиентом этого API, вынужден жить в постоянной готовности получить не данные, а фигу.

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

S>И как-то осмысленно объяснять пользователю, что "у тебя, брат, нет пермиссии на атрибут 'НДС', сходи к админу, попроси, чтоб выдал".


Google Cloud так и делает если что

S>Ну, либо (что скорее всего) внезапно падать с internal error 500, потому что внутрях там NullReferenceException.


домыслы

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


дорогостоящий саппорт? дороже разработки?

КЛ>>вот и начинается, часть пермиссий через средства субд, часть сбоку, чтд

S>Где это я предложил часть пермиссий через средства СУБД? Я вам привёл стандартный способ разделения доступа "построчно" без использования row-level security.

ваши роли в субд и есть часть пермиссий через субд

КЛ>>так у вас нет row-level permission же

S>Я вроде дал пошаговое описание того, как решается проблема отсутствия row-level permissions в RDBMS. Причём не как рекомендацию использовать эту схему, а как пример реализации "послойной" безопасности.

а что тогда надо использовать в твоем случае?

S>Точно такие же рецепты применяются и в сервисах.

S>То есть токен пользователя у нас роляет только во фронт-сервисе. Когда пользователь U запрашивает API сервиса A, а сервис A в рамках этого запроса стучится в сервис B, то никакие токены U в этот B не передаются. У U вообще нет никакого доступа до сервиса B. В этот сервис обращается A, под собственным токеном.
S>Поэтому идея "а давайте у нас инвойс будет содержать данные контрагента если у вызывающего пользователя есть пермиссия на этого контрагента" сразу идёт навзничь.
S>У вызываюшего пользователя нет никаких пермиссий на контрагента — господь упаси. А вот право видеть реквизиты получателя платежа по выставленному счёту у него есть в силу федерального закона.

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

КЛ>>" SQL исполнялся в контексте безопасности конечного пользователя " — вот это вообще что такое?

S>Это когда мы заводим для пользователя №44487 виндовый аккаунт, даём этому аккаунту права на SQL базу с табличками forums, topics, replies, и marks, при логине на сайт создаём виндовую сессию, и все запросы в SQL Server выполняем через новое соединение под правами этого виндового аккаунта.

кто так вообще делает? выглядит как полная дичь если честно

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

S>>>Можете привести пример такого select? Я вроде понимаю, о чём вы пишете, но уверенности нет.

КЛ>>select * from rows r

КЛ>>join rows_perms p on r.id = p.r_id
КЛ>> where p.perm = 'row_read' and p.user_id = :userid
S>Прекрасно. Вы себе представляете производительность такого решения? Когда у нас табличка на пару миллионов строк, и есть тысяча пользователей с частично пересекающимися правами на эти строки?

да, индекс на rows_perms.user_id и будет быстро, плюс там еще в 99 процентах будет предикат на индексированное поле как часть фильтра поискового запроса. да, часто данные для всех лежать в одной таблице и когда нужен row-level security у тебя просто нет выбора. либо копии данных (твои views видимо) либо так.

но это на запрос коллекции, а на запрос одного ресурса вообще все быстро потому что индекс и на rows_perms.id

select * from rows r
join rows_perms p on r.id = p.r_id
where p.perm = 'row_read' and p.user_id = :userid and r.id = :id

КЛ>>или

КЛ>>select * from rows r where r.group_id in :user_groups
S>А как же "любое сочетание ролей и пермиссий"? Вы прибиваете доступ к r только к одной роли; невозможно выдать доступ к конкретной строке нескольким разным группам.
S>Собственно, вы изобретаете нормальную изоляцию на основе бизнес-правил, только задом наперёд.

ты просил примеры, я привел сложный и простой (для твоей модели где есть только роли)

S>Это — совершенно нормальная история, которая работает и применяется.

КЛ>>userid/user_groups резолвятся по токену из запроса
S>Ну, вы же только что собирались сделать универсальную схему, которая работает с любым количеством пермиссий и ролей. А получается вполне себе узкоспециализированная штука.

первый пример довольно универсален, он иллюстрирует подход "на основании токена фильтруем резалтсет и тп"

S>Непонятно. Как я смогу получить разный набор полей для разных строк одной и той же таблицы? Речь-то шла именно об этом — что состав результата определяется не объектом, а правами пользователя на него.


на чистом sql очевидно никак, для некоторых строк в резалтсете надо фильтровать поля (будут null), если ты об этом
а в твоем случае как? у тебя же схема прибита гвоздями

КЛ>>да, но ничего с точки зрения трейдоффа разработка/результат не придумали. открываешь google aim и видишь и роли, и отдельные пермиссии.

S>Надо внимательно смотреть на то, как именно используются эти роли и пермиссии. Потому что я так-то не против ролей и пермиссий; я против смешивания мух и котлет.
S>И если я запрашиваю, допустим, GET /resources/{resourceId}?$include(usageHistory), а у меня нет пермиссий смотреть usageHistory по этому ресурсу, я получаю не пустую историю и не JSON с "вырезанным" атрибутом, а честный 403. А если у меня пермиссия есть, то я могу полагаться на то, что в результате будет атрибут usageHistory с описанной в схеме структурой.

как тут помогают роутеры?

S>В итоге сторонний сервис, который потребляет мой API, может выдавать осмысленные ошибки, которые можно быстро исправить. А не просто падать оттого, что его авторы тестировались с аккаунтом, у которого были все нужные пермиссии, и понятия не имели, что у кого-то пермиссия на usageHistory на какой-то отдельный объект может быть отобрана.


да ну я тебе сделаю отдельный endpoint, но внутри будет один движок по доставке данных, который может тебе отдавать 403 в когда надо

S>Обратите внимание — это то самое "разведение ресурсов по разным URL", над которым вы так потешались.


мы потешаемся не над ним, а над тем, что ты полагаешься только на него

КЛ>>много ролей, много разных пермиссий

S>Количество ни на что не влияет.

на комбинаторный взрыв сущностей

КЛ>>ага, то есть любой смоук тест у нас в лобой системе обнаруживает любую проблему?

S>Нет, только детерминистические вещи.

это что? каков критерий?

КЛ>>и никто ее не делает, потому что это невозможно поддерживать

S> Надо просто уметь это готовить.


сколько раз мы уже это слышали по поводу всего. похоже на отмазку для неадекватного задаче решения
Отредактировано 17.04.2025 19:26 Константин Л. . Предыдущая версия . Еще …
Отредактировано 17.04.2025 18:57 Константин Л. . Предыдущая версия .
Re[23]: Каких программ вам не хватает?
От: Константин Л. Франция  
Дата: 17.04.25 18:11
Оценка:
Здравствуйте, Sinclair, Вы писали:

КЛ>>система типов это только про поля, а что со строками?

КЛ>>это не гибко
S>Излишняя гибкость, в целом, только вредит. Но фильтрация, в отличие от проекции, не нарушает никаких инвариантов.

не понял

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

S>По-прежнему у нас границы безопасности совпадают с границами ресурса.
S>Смотрите: вот я делаю какой-нибудь
S>
S>GET /invoices/
S>

S>И мне приезжает какой-то список инвойсов. Как правило — без деталей, только ссылки.
S>И если я пойду по этим ссылкам, типа GET /invoices/32423423423/, то скорее всего буду получать 200 Ok.
S>А вот те из инвойсов, на которые у меня прав нет, дадут при прямом обращении 403 либо 404, и в общем списке фигурировать не будут.

ну у нас так же, в чем поинт?

S>Для проектирования безопасности у нас недостаточно вводных.


смешно

КЛ>>а что он делает?

S>Он делает возможность формировать запросы к иерархии объектов, без всех плюшек REST.

да не, по сути он дает тебе query language к базе

КЛ>>а как вы тестируете все остальное, что отдает данные на основании пользовательского контекста?


S>


отвечай!

КЛ>>да, но выставляет наружу псевдо-бд

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

ну начинается! отлыниваешь )
Re[30]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 18.04.25 05:31
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>то есть пермисии определяются декларативно просто наличием полей в типе? ну-ну

Не уверен, что я понял ваш вопрос, но скорее всего ответ "нет".
КЛ>"хорошо это когда хорошо".
А то.
КЛ>тогда _какую_ проблему решают твои виртуальные ресурсы? никакую
Конечно. Они не создают проблему. А решают они задачу — задачу ограничения доступа к определённым атрибутам для определённых групп пользователей.

КЛ>серьезные приложения это софт для АЭС, там можно. В 99 процентах других случаев твоя модель не работает, такая моя оценка

Софт для АЭС тут ни при чём. А серьёзные приложения — это те, к примеру, которые автоматизируют деятельность, подлежащую регулированию каким-нибудь FinCEN.
Когда у вас есть реальная перспектива продолбать крипты суммарной стоимостью под миллиард, рассуждения в стиле "у меня в коде всё было правильно, это тупой админ нечаянно выдал лишнюю пермиссию на один из атрибутов одного из объектов одному из пользователей" не сильно помогают избежать кусания локтей.

КЛ>при чем здесь вообще апи, когда мы говорим про то, как делать секьюрити внутри?

С чего это вдруг?
Мы всю дорогу говорили именно про то, как должен выглядеть API снаружи. То, что там внутри, в первую очередь определяется контрактом протокола, затем — общей архитектурой решения. А уже дальше идут подробности реализации. Собственно, спор-то и идёт о том, то ли выставлять наружу 1 ресурс, схема которого сложным образом зависит от погоды на Венере, то ли выставлять наружу N ресурсов с предсказуемыми схемами.

КЛ>Google Cloud так и делает если что

Не знаком с Google Cloud, поэтому не могу осмысленно обсуждать его поведение. Если приведёте пример API-запроса, и пример клиента этого API, который этот запрос отправляет и его результатами пользуется, можно будет что-нибудь конструктивно обсудить.

КЛ>домыслы

А то. Основанные на многолетнем опыте проектирования, изготовления, и использования различных сервисов

КЛ>дорогостоящий саппорт? дороже разработки?

Естественно. Потому что разработка делается 1 раз, а саппорт — всю жизнь. Вы себе представляете себестоимость 1 инцидента в саппорте?

КЛ>ваши роли в субд и есть часть пермиссий через субд

Какая-то путаница. У меня нет никаких "ролей в СУБД".

КЛ>а что тогда надо использовать в твоем случае?

Запросы.
Пишем
  IQueryable<OutboundInvoice> InvoicesSentBy(CompanyID currentCompany) =>  
    from i in db.OutboundInvoices where i.originator = currentCompany select i;
  IQueryable<InboundInvoice> InvoicesSentTo(CompanyID currentCompany) =>
    from i in db.InboundInvoices where i.destination = currentCompany select i;

Всё. Поверх этого в контроллере проверяем, что у текущего пользователя есть пермиссия на доступ к InboundInvoices/OutboundInvoices. Всё.

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

Это очень странно. Топик называется "помогите спроектировать микросервисное приложение". Как мы ухитрились выкинуть из контекста API для взаимодействия между микросервисами?
И что тогда вообще осталось в контексте?

КЛ>кто так вообще делает? выглядит как полная дичь если честно

Я не знаю. Но если вы вдруг захотите применить Row Level Security из любой СУБД, в которой она есть, вам так и придётся делать.

КЛ>>>select * from rows r

КЛ>>>join rows_perms p on r.id = p.r_id
КЛ>>> where p.perm = 'row_read' and p.user_id = :userid
S>>Прекрасно. Вы себе представляете производительность такого решения? Когда у нас табличка на пару миллионов строк, и есть тысяча пользователей с частично пересекающимися правами на эти строки?

КЛ>да, индекс на rows_perms.user_id и будет быстро,

Ну ок.

КЛ>плюс там еще в 99 процентах будет предикат на индексированное поле как часть фильтра поискового запроса.

И это всё ещё будет медленнее, чем прямой поиск по предикату, который применяется к единственной таблице (см. пример кода с Invoices выше).
КЛ>да, часто данные для всех лежать в одной таблице и когда нужен row-level security у тебя просто нет выбора. либо копии данных (твои views видимо) либо так.
Эмм, views никаких "копий данных" не создают. Если хотите — могу рассказать, как они работают.

Да, если вам некомпететный продакт навязал вот эту вот модельку "кому угодно можно выдавать доступ на что угодно", то выбора действительно нет. Ну, точнее, даже там бывают возможности поиграть с оптимизацией, но не очень большие. Тут вопросов нет. Вопрос как раз в том, как проектировать API, чтобы вот таких вот необходимостей не возникало.
КЛ>но это на запрос коллекции, а на запрос одного ресурса вообще все быстро потому что индекс и на rows_perms.id


КЛ>первый пример довольно универсален, он иллюстрирует подход "на основании токена фильтруем резалтсет и тп"

Нет конечно. В первом примере нет решительно никакой возможности управлять видимостью отдельных атрибутов на уровне отдельных объектов.
КЛ>а в твоем случае как? у тебя же схема прибита гвоздями
Во-первых, в моём случае этого не надо, т.к. я против самой идеи разделять доступ "по-объектно". Это ухудшает сразу примерно всё: и эффективность, и безопасность, и удобство использования.
Во-вторых, если даже нам такое припёрло, у меня состав заказанных полей известен в момент получения запроса, и мне не надо пытаться "доставать всё, для чего довольно пермиссий", с риском достать что-то не нужное или неожиданное.

КЛ>как тут помогают роутеры?

Кто такие роутеры и почему они должны мне помогать?

КЛ>да ну я тебе сделаю отдельный endpoint, но внутри будет один движок по доставке данных, который может тебе отдавать 403 в когда надо

Ну так и слава байту. С чем спорим-то тогда?

КЛ>мы потешаемся не над ним, а над тем, что ты полагаешься только на него

Непонятно, что значит "только".

КЛ>на комбинаторный взрыв сущностей

Комбинаторный взрыв сущностей у нас случился в тот момент, когда кто-то решил разрешать доступ к различным атрибутам ресурса при помощи независимых пермиссий. Дальше вопрос только в том, признаём мы его или нет, и что мы с ним делаем.
Когда у нас состав атрибутов явно заказывается в урле, нам очень легко такое тестировать:
1. делаем запрос к ?$include(attribute1) с токеном без пермиссии на attribute1, убеждаемся, что получаем 403
2. делаем запрос к ?$include(attribute1) с токеном с пермиссией на attribute1, убеждаемся, что получаем 200.
3. делаем запрос к ?$include(attribute1) с токеном с полными пермиссиями, убеждаемся, что получаем 200 и в ответе нет никаких лишних атрибутов.
4. Повторяем так для всех атрибутов, доступ к которым контролируется пермиссиями.
третье — факультативно: это если мы не верим в то, что код контроллера факторизован на предмет запрошенных атрибутов. Факторизацию можно отдельно проверять юнит-тестами.
Это гораздо надёжнее, чем пытаться перебирать все комбинации пермиссий и смотреть, какой получится результат.

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

Как скажете.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[24]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 18.04.25 05:46
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>не понял

А что тут понимать? Когда я делаю запрос, я ожидаю получить результат типа
{
  id: number;
  senderId: string;
  senderName: string;
  amount: number;
  expiresAt?: Date;
}[]

Если мне вдруг приезжает массив, где у каких-то объектов нет senderName, то это нарушает приведённую здесь спецификацию типа.
Можно, конечно, принудительно приписать вопросики ко всем свойствам этого интерфейса, и написать обработку в приложении на каждый такой случай, но это, скажем так, непрактично.
А вот если мне приезжает массив, в котором не 100, а 10, или 0 элементов, инвариант сохранён. Я в любом случае не ожидаю, что мне вернётся ровно 100 элементов.

КЛ>ну у нас так же, в чем поинт?

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

КЛ>смешно

А вы всегда проектируете безопасность на основании описаний вроде "у нас есть пять типов отчётов, один из них внутренний, другой внешний". Вам сразу всё понятно, и можно бежать нарезать таблички в базе?
Я раньше и сам выяснял подробности проекта на основании телепатии и ясновидения, но лет 15 тому мне их за неуплату отключили, поэтому я предпочитаю проектировать на основании установленных фактов, а также вероятных будущих изменений.

КЛ>да не, по сути он дает тебе query language к базе

По сути там вообще может не быть никакой базы.

КЛ>отвечай!

Зависимость от контекста называется "модальностью" и является одним из признаков плохого проектирования. Такой зависимости нужно по возможности избегать.
Если уж никак-никак от неё избавиться не удалось, нужно факторизовывать пространство состояний для этого контекста. И следить за тем, чтобы факторизация была корректной, т.е. изоляция между ортогональными классами состояний должна сохраняться.
Успешная факторизация позволяет нам перейти от K*M тестов к K+M тестам. Всё.

КЛ>ну начинается! отлыниваешь )

Если вы хотите конструктивного обсуждения, можно попытаться взять какую-нибудь практическую задачу и посмотреть, как её решать в стиле REST — как с помощью микросервисов, так и без оных.
Можно попытаться понять, ради чего вообще может в голову прийти "выставлять наружу псевдо-бд", и как это делать правильно, и чем это отличается от неправильного решения.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[31]: Каких программ вам не хватает?
От: Константин Л. Франция  
Дата: 18.04.25 09:29
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Константин Л., Вы писали:


КЛ>>то есть пермисии определяются декларативно просто наличием полей в типе? ну-ну

S>Не уверен, что я понял ваш вопрос, но скорее всего ответ "нет".
КЛ>>"хорошо это когда хорошо".
S>А то.
КЛ>>тогда _какую_ проблему решают твои виртуальные ресурсы? никакую
S>Конечно. Они не создают проблему. А решают они задачу — задачу ограничения доступа к определённым атрибутам для определённых групп пользователей.

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

КЛ>>серьезные приложения это софт для АЭС, там можно. В 99 процентах других случаев твоя модель не работает, такая моя оценка

S>Софт для АЭС тут ни при чём. А серьёзные приложения — это те, к примеру, которые автоматизируют деятельность, подлежащую регулированию каким-нибудь FinCEN.
S>Когда у вас есть реальная перспектива продолбать крипты суммарной стоимостью под миллиард, рассуждения в стиле "у меня в коде всё было правильно, это тупой админ нечаянно выдал лишнюю пермиссию на один из атрибутов одного из объектов одному из пользователей" не сильно помогают избежать кусания локтей.

ла-ла-ла

КЛ>>при чем здесь вообще апи, когда мы говорим про то, как делать секьюрити внутри?

S>С чего это вдруг?
S>Мы всю дорогу говорили именно про то, как должен выглядеть API снаружи. То, что там внутри, в первую очередь определяется контрактом протокола, затем — общей архитектурой решения. А уже дальше идут подробности реализации. Собственно, спор-то и идёт о том, то ли выставлять наружу 1 ресурс, схема которого сложным образом зависит от погоды на Венере, то ли выставлять наружу N ресурсов с предсказуемыми схемами.

ты сам себе противоречишь. невозможно говорить про апи без того, зачем он такой нужен. мы тут не про форму, а про сочетание ее с сожержанием

КЛ>>домыслы

S>А то. Основанные на многолетнем опыте проектирования, изготовления, и использования различных сервисов

ну, люди много лет умудряются делать всякую фигню, это не показатель.

КЛ>>дорогостоящий саппорт? дороже разработки?

S>Естественно. Потому что разработка делается 1 раз, а саппорт — всю жизнь. Вы себе представляете себестоимость 1 инцидента в саппорте?

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

КЛ>>ваши роли в субд и есть часть пермиссий через субд

S>Какая-то путаница. У меня нет никаких "ролей в СУБД".
ну у тебя там есть юзер, у которого явно есть роль или зачем там была написана вся та бесполезная портянка

КЛ>>а что тогда надо использовать в твоем случае?

S>Запросы.
S>Пишем
S>
S>  IQueryable<OutboundInvoice> InvoicesSentBy(CompanyID currentCompany) =>  
S>    from i in db.OutboundInvoices where i.originator = currentCompany select i;
S>  IQueryable<InboundInvoice> InvoicesSentTo(CompanyID currentCompany) =>
S>    from i in db.InboundInvoices where i.destination = currentCompany select i;
S>

S>Всё. Поверх этого в контроллере проверяем, что у текущего пользователя есть пермиссия на доступ к InboundInvoices/OutboundInvoices. Всё.

в контроллере? ты серьезно? вот это ты гений проектирования безопасных приложений — поля отрезаем декларативно через поля в объекте (твой факторинг), пермиссии проверяем в контроллерах (кстати как?). такое где-то работает да — в очень простых системах.

это читерство. у тебя одна таблица, а не две. зачем сюда писать какой-то детский сад?

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

S>Это очень странно. Топик называется "помогите спроектировать микросервисное приложение". Как мы ухитрились выкинуть из контекста API для взаимодействия между микросервисами?
S>И что тогда вообще осталось в контексте?

какая разница как называется топик, когда эта ветка давно уже про rest levels?

КЛ>>кто так вообще делает? выглядит как полная дичь если честно

S>Я не знаю. Но если вы вдруг захотите применить Row Level Security из любой СУБД, в которой она есть, вам так и придётся делать.

у тебя windows головного мозга

КЛ>>>>select * from rows r

КЛ>>>>join rows_perms p on r.id = p.r_id
КЛ>>>> where p.perm = 'row_read' and p.user_id = :userid
S>>>Прекрасно. Вы себе представляете производительность такого решения? Когда у нас табличка на пару миллионов строк, и есть тысяча пользователей с частично пересекающимися правами на эти строки?

КЛ>>да, индекс на rows_perms.user_id и будет быстро,

S> Ну ок.

КЛ>>плюс там еще в 99 процентах будет предикат на индексированное поле как часть фильтра поискового запроса.

S>И это всё ещё будет медленнее, чем прямой поиск по предикату, который применяется к единственной таблице (см. пример кода с Invoices выше).

да да, а твои проверки row-level секьюрити в контроллере стоят ноль да? и ты поташищь весь резалтсет для всех юзеров из базы да?
и пейджинг от этого у тебя не будет работать

КЛ>>да, часто данные для всех лежать в одной таблице и когда нужен row-level security у тебя просто нет выбора. либо копии данных (твои views видимо) либо так.

S>Эмм, views никаких "копий данных" не создают. Если хотите — могу рассказать, как они работают.

да ты тут уже нарассказывал

S>Да, если вам некомпететный продакт навязал вот эту вот модельку "кому угодно можно выдавать доступ на что угодно", то выбора действительно нет. Ну, точнее, даже там бывают возможности поиграть с оптимизацией, но не очень большие. Тут вопросов нет. Вопрос как раз в том, как проектировать API, чтобы вот таких вот необходимостей не возникало.


ну спроектируй тут, только без хаков с db.OutboundInvoices, db.InboundInvoices — одна таблица, row-level security и тп. я тебе набросал _примерную_ схему, ты
же мне ответил "недостаточно вводных данных".

КЛ>>но это на запрос коллекции, а на запрос одного ресурса вообще все быстро потому что индекс и на rows_perms.id

S>

ну смейся

КЛ>>первый пример довольно универсален, он иллюстрирует подход "на основании токена фильтруем резалтсет и тп"

S>Нет конечно. В первом примере нет решительно никакой возможности управлять видимостью отдельных атрибутов на уровне отдельных объектов.

это уже хоть что-то для иллюстрации. у тебя же нет вообще ничего

КЛ>>а в твоем случае как? у тебя же схема прибита гвоздями

S>Во-первых, в моём случае этого не надо, т.к. я против самой идеи разделять доступ "по-объектно". Это ухудшает сразу примерно всё: и эффективность, и безопасность, и удобство использования.

а, ну да. теперь понятно какие ты там приложения годами делаешь

S>Во-вторых, если даже нам такое припёрло, у меня состав заказанных полей известен в момент получения запроса, и мне не надо пытаться "доставать всё, для чего довольно пермиссий", с риском достать что-то не нужное или неожиданное.


какая чушь

S>Это гораздо надёжнее, чем пытаться перебирать все комбинации пермиссий и смотреть, какой получится результат.


это все слова, которые ты не готов обратить в код

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

S>Как скажете.

был гораздо лучшего мнения о тебе
Re[25]: Каких программ вам не хватает?
От: Константин Л. Франция  
Дата: 18.04.25 09:47
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Константин Л., Вы писали:


S>Если мне вдруг приезжает массив, где у каких-то объектов нет senderName, то это нарушает приведённую здесь спецификацию типа.


охо-хо, ну-ну. спецификацию типа

S>Можно, конечно, принудительно приписать вопросики ко всем свойствам этого интерфейса, и написать обработку в приложении на каждый такой случай, но это, скажем так, непрактично.


это, скажем так, реальность

S>А вот если мне приезжает массив, в котором не 100, а 10, или 0 элементов, инвариант сохранён. Я в любом случае не ожидаю, что мне вернётся ровно 100 элементов.


какая-то чушь

КЛ>>ну у нас так же, в чем поинт?

S>Не знаю, как "у вас", а у исходного оппонента, судя по всему, в JSON будет список не ссылок, а объектов, причём состав объектов произвольно зависит не от самих объектов или аргументов запроса, а от наличия в токене тех или иных пермиссий.

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

кому нужен пустой список только с ссылками? на вебе его не покажешь. будут легкие объекты и ссылки если надо взять конкретный полный.

КЛ>>смешно

S>А вы всегда проектируете безопасность на основании описаний вроде "у нас есть пять типов отчётов, один из них внутренний, другой внешний". Вам сразу всё понятно, и можно бежать нарезать таблички в базе?

а вы всегда бегаете по форумам с заявлениями (цитирую) "Во-первых, в моём случае этого не надо, т.к. я против самой идеи разделять доступ "по-объектно"".
То есть вы проектируете так — "знаете, я выяснил требования и учел вероятные будущие изменения и я против".

S>Я раньше и сам выяснял подробности проекта на основании телепатии и ясновидения, но лет 15 тому мне их за неуплату отключили, поэтому я предпочитаю проектировать на основании установленных фактов, а также вероятных будущих изменений.


какой-то бред

КЛ>>да не, по сути он дает тебе query language к базе

S>По сути там вообще может не быть никакой базы.

а по факту в 99 случаев она там есть

КЛ>>отвечай!

S>Зависимость от контекста называется "модальностью" и является одним из признаков плохого проектирования. Такой зависимости нужно по возможности избегать.

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

S>Если уж никак-никак от неё избавиться не удалось, нужно факторизовывать пространство состояний для этого контекста. И следить за тем, чтобы факторизация была корректной, т.е. изоляция между ортогональными классами состояний должна сохраняться.


мне кажется я начинаю понимать, откуда такой казеный язык и нажим на систему типов — многолетнее преподавание и .net?

S>Успешная факторизация позволяет нам перейти от K*M тестов к K+M тестам. Всё.


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

КЛ>>ну начинается! отлыниваешь )

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


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


S>Можно попытаться понять, ради чего вообще может в голову прийти "выставлять наружу псевдо-бд", и как это делать правильно, и чем это отличается от неправильного решения.



да мне это все неинтересно, потмому что в 99 случаев я против выставления хоть правильно, хоть неправильно. да и в "правильно" я не верю
jfyi
Re[11]: Каких программ вам не хватает?
От: Miroff Россия  
Дата: 18.04.25 11:38
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>PUT без параметров?


С параметрами, которые GET вернул. Структура ресурса не должна зависеть от метода

КЛ>а если ссылки поменялись между GET и PUT? "и вообще конкурентные обновления" — какие ужасы ты пишешь


А ты дизайни систему так, чтобы ссылки не менялись между GET и PUT. Идемпотентность, версии объекта и все дела. Ссылки не отменяют, а дополняют коды ошибок.
Re[25]: Каких программ вам не хватает?
От: Miroff Россия  
Дата: 18.04.25 11:47
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Можно, конечно, принудительно приписать вопросики ко всем свойствам этого интерфейса, и написать обработку в приложении на каждый такой случай, но это, скажем так, непрактично.


Вполне практично, в Swagger спеке ты так или иначе должен для каждого поля указать обязательное оно или опциональное. И, соответственно, в имплементации обработать все случаи. У тебя не может быть такой ситуации, когда поле обязательное, а сервер его по какой-то причине не отдает. По-хорошему, у тебя даже код не должен скомпилироваться.
Re[12]: Каких программ вам не хватает?
От: Константин Л. Франция  
Дата: 18.04.25 12:34
Оценка:
Здравствуйте, Miroff, Вы писали:

M>Здравствуйте, Константин Л., Вы писали:


КЛ>>PUT без параметров?


M>С параметрами, которые GET вернул. Структура ресурса не должна зависеть от метода


контракт на базе возвращаемых полей для конкретного инстанса ресурсы, а не на основе сваггера?
это ты какой-то очень простой crud описываешь. а что если мне надо заполнить пустое поле, которого нет в GET? или ты всегда
null возвращаешь для всех полей? допустим

КЛ>>а если ссылки поменялись между GET и PUT? "и вообще конкурентные обновления" — какие ужасы ты пишешь


M>А ты дизайни систему так, чтобы ссылки не менялись между GET и PUT. Идемпотентность, версии объекта и все дела. Ссылки не отменяют, а дополняют коды ошибок.


ты пишешь "Правильно делать GET перед PUT, потому что ссылки могут измениться, и вообще конкурентные обновления. ".
так вот между GET и PUT ты залил на сервер новую версию, клиент при этом не в курсе и держит у себя в текущем состоянии твой старый PUT.
Твои действия? меняешь версию апи в url и PUT идет на старый url?

"вообще конкурентные обновления" — что это значит в контексте ссылок, раскрой тему
Отредактировано 18.04.2025 12:40 Константин Л. . Предыдущая версия .
Re[6]: Помогите правильно спроектировать микросервисное приложение
От: Ziaw Россия  
Дата: 18.04.25 12:38
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Поэтому MSA это техническое решение, а организационное. Если у вас много команд, каждая со своим подходом, технологическим стеком, архитектурой итд, то подружить их в рамках монолитного приложения будет технически невозможно.


У Линуса получилось. Ядро линукса это монолит. Лично я считаю, что МСА возникла от нехватки времени на тщательное проектирование. В текущих бизнес процессах никто не хочет давать время на проектирование и перепроектирование кода и процессов в командах. Поскольку это слабо предсказуемые и сложно планируемые активности, а ЛПР хотят понимать, что происходит и не готовы просто доверять технарям по вполне понятным человеческим причинам. Ну или это очень одаренные ЛПР.

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

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

Например есть опердень на котором работает более тысячи организаций и несколько сотен тысяч человек (не менее сотни тысяч в день). За тысячу форм, процессов и отчетов, интеграции с десятками других систем. И этот монолит способен развиваться и поддерживаться командой в составе которой один программист, годовой бюджет которой единицы миллионов для заказчика. Коллеги, как думаете, насколько счастлив заказчик, что для него это все настолько дешево? Про счастье этого незаменимого программиста я тоже боюсь писать.
Re[7]: Помогите правильно спроектировать микросервисное приложение
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 18.04.25 13:01
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Здравствуйте, gandjustas, Вы писали:


G>>Поэтому MSA это техническое решение, а организационное. Если у вас много команд, каждая со своим подходом, технологическим стеком, архитектурой итд, то подружить их в рамках монолитного приложения будет технически невозможно.


Z>У Линуса получилось. Ядро линукса это монолит.

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

Z>Лично я считаю, что МСА возникла от нехватки времени на тщательное проектирование. В текущих бизнес процессах никто не хочет давать время на проектирование и перепроектирование кода и процессов в командах. Поскольку это слабо предсказуемые и сложно планируемые активности, а ЛПР хотят понимать, что происходит и не готовы просто доверять технарям по вполне понятным человеческим причинам. Ну или это очень одаренные ЛПР.

Много причин использования МСА, далеко не все они оправданы с точки зрения экономики.
Re[32]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 18.04.25 13:04
Оценка:
Здравствуйте, Константин Л., Вы писали:


КЛ>задача ограничения доступа это и есть по сути то, что решают пермиссии. то есть ответ да, просто ты не понимаешь уже что пишешь

Нет, но я не совсем понимаю, что мне пишете вы. Да, теперь понятно — ответ "да".

КЛ>ла-ла-ла



КЛ>ты сам себе противоречишь. невозможно говорить про апи без того, зачем он такой нужен.

Ну так мы про это и говорим, а вы вдруг начинаете "при чём тут АПИ"

КЛ>ну, люди много лет умудряются делать всякую фигню, это не показатель.

Отож.

КЛ>всю жизнь? да твой код будет переписан через пару лет. сколько стоит индийский саппорт? представляю. но не надо мне зубы заговаривать — тейк про баги

Не было никакого тейка про баги. Я, наверное, плохо объяснил сценарий.
Вот у нас есть какая-нибудь экзотическая пермиссия на атрибут "НДС". Зачем? Да низачем. Просто пришёл в своё время суперуверенный в себе архитект, и набросал "универсальное RBAC-решение на все времена".
На практике следуюшие 10 лет никто не задурялся настройкой этой пермиссии, потому что нафиг никому не упёрлись инвойсы без атрибута НДС. Нет такого бизнес-сценария.
Внешние разработчики, которые писали интеграцию с этим АПИ, всегда видели этот атрибут в JSON. Да и в OpenAPI спецификации этот атрибут приведён. Где-то, в какой-то доке, наверное, кто-то упомянул, что этот атрибут требует пермиссию Invoice.VAT.Read для конкретного инвойса. Но поскольку доки никто не читает, а в тестах интеграция работало в 100% случаев, этот сторонний сервис выкачен в эксплуатацию.
И вот ещё через несколько лет какой-нибудь шибко активный админ решает поубирать у какого-нибудь пользователя "лишние" пермиссии на какие-то отдельные объекты.
Пользователь выполняет свой привычный workflow, и внезапно обнаруживает 500 internal error. Потому что сервису вдруг попался экземпляр инвойса с атрибутом НДС=null, а на это никто не рассчитывал.

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

Я вроде три раза объяснил, в четвёртый уже не буду.

КЛ>в контроллере? ты серьезно? вот это ты гений проектирования безопасных приложений — поля отрезаем декларативно через поля в объекте (твой факторинг), пермиссии проверяем в контроллерах (кстати как?). такое где-то работает да — в очень простых системах.

Ну, научите же меня, как всё это правильно делать. А то по моей практике, простые решения — они самые надёжные.

КЛ>это читерство. у тебя одна таблица, а не две. зачем сюда писать какой-то детский сад?

Да, у меня одна таблица. Читерство-то в чём? Детский сад — это ваша манера общаться. Я что-то начал от неё уставать.

КЛ>какая разница как называется топик, когда эта ветка давно уже про rest levels?

Прекрасно.

КЛ>у тебя windows головного мозга

Windows тут ни при чём. Row-level security в каком-нибудь Постгрес устроены ровно так же.
Пример, который я привёл, про этот сайт — поэтому упомянут Windows и SQL Server.

КЛ>да да, а твои проверки row-level секьюрити в контроллере стоят ноль да? и ты поташищь весь резалтсет для всех юзеров из базы да?

Вот зачем вы пишете бред. Я же показал вам тремя абзацами выше код запросов — где там "весь резалтсет для всех юзеров из базы"?

КЛ>и пейджинг от этого у тебя не будет работать

Прекрасно он будет работать.

КЛ>да ты тут уже нарассказывал

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

КЛ>ну спроектируй тут, только без хаков с db.OutboundInvoices, db.InboundInvoices — одна таблица, row-level security и тп.

Непонятно, что такое "хаки".

КЛ>я тебе набросал _примерную_ схему, ты

КЛ>же мне ответил "недостаточно вводных данных".
Вы жульничаете. Схему вы набросали про фильтрацию строк, а задачу, про которую я ответил "недостаточно данных" — про какую-то (непонятно какую) обрезку атрибутов.
И ни в одном из случаев нет ничего про постановку задачи. Выглядит так, что вы стараетесь сначала придумать решение, а уже потом любой ценой его защитить, вообще не задумываясь, а зачем такое решение нужно.

КЛ>ну смейся

А то.



КЛ>какая чушь

Не, беру свои слова по поводу "поделиться всем, чем знаю" обратно.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[8]: Помогите правильно спроектировать микросервисное приложение
От: Ziaw Россия  
Дата: 18.04.25 14:45
Оценка:
Здравствуйте, gandjustas, Вы писали:

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


Про лучший вариант архитектуры соглашусь. Если взять что-то сравнимое по сложности, типа Яндекс 360, то релизный цикл похожий. Более того, подозреваю, что именно микросервисная архитектура этого изделия сделала невозможной его доводку до приличного состояния. То же можно сказать и про интерфейс яндекс облака, там уши всяких узкосервисных проблем торчат регулярно, но там хотя бы бабло идет. Интересно, есть тут кто-то близкий к этим командам Яндекса, чтобы прокомментировать.

G>Много причин использования МСА, далеко не все они оправданы с точки зрения экономики.


Я могу назвать только одну — борьба со сложностью, но, имхо, это фикция. На уровне конечного продукта сложность возрастает. Иногда мне кажется, что на это всем пофиг, главное работой обеспечены.
Re[14]: Каких программ вам не хватает?
От: Константин Л. Франция  
Дата: 18.04.25 15:04
Оценка:
Здравствуйте, Miroff, Вы писали:

M>Здравствуйте, Константин Л., Вы писали:


КЛ>>это ты какой-то очень простой crud описываешь


M>Именно! В этом и смысл REST, выражать сложную логику через очень простой CRUD


это очень упрощенный взгляд на вещи
Re[33]: Каких программ вам не хватает?
От: Константин Л. Франция  
Дата: 18.04.25 15:27
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Нет, но я не совсем понимаю, что мне пишете вы. Да, теперь понятно — ответ "да".


ну так ведь это же даже не секьюрити а костыль.

S>Не было никакого тейка про баги. Я, наверное, плохо объяснил сценарий.

[]
S>Пользователь выполняет свой привычный workflow, и внезапно обнаруживает 500 internal error. Потому что сервису вдруг попался экземпляр инвойса с атрибутом НДС=null, а на это никто не рассчитывал.

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

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

S>Я вроде три раза объяснил, в четвёртый уже не буду.

я реально не понял, видимо потмоу что мне в голову такое не приходило делать

S>Ну, научите же меня, как всё это правильно делать. А то по моей практике, простые решения — они самые надёжные.


простые — да. но мир сложен. учим вот но ты ни в какую)

КЛ>>это читерство. у тебя одна таблица, а не две. зачем сюда писать какой-то детский сад?

S>Да, у меня одна таблица. Читерство-то в чём? Детский сад — это ваша манера общаться. Я что-то начал от неё уставать.

я тоже, сори

КЛ>>у тебя windows головного мозга

S>Windows тут ни при чём. Row-level security в каком-нибудь Постгрес устроены ровно так же.
S>Пример, который я привёл, про этот сайт — поэтому упомянут Windows и SQL Server.

какой сайт? rsdn? ужас.

Вы писали "Это когда мы заводим для пользователя №44487 виндовый аккаунт, даём этому аккаунту права на SQL базу с табличками forums, topics, replies, и marks, при логине на сайт создаём виндовую сессию, и все запросы в SQL Server выполняем через новое соединение под правами этого виндового аккаунта."

в постгрес так никто делать не будет в здравом уме

КЛ>>да да, а твои проверки row-level секьюрити в контроллере стоят ноль да? и ты поташищь весь резалтсет для всех юзеров из базы да?

S>Вот зачем вы пишете бред. Я же показал вам тремя абзацами выше код запросов — где там "весь резалтсет для всех юзеров из базы"?

а где там фильтрация по юзеру? Это:

 IQueryable<OutboundInvoice> InvoicesSentBy(CompanyID currentCompany) =>  
    from i in db.OutboundInvoices where i.originator = currentCompany select i;
  IQueryable<InboundInvoice> InvoicesSentTo(CompanyID currentCompany) =>
    from i in db.InboundInvoices where i.destination = currentCompany select i;


КЛ>>да ты тут уже нарассказывал

S>Я как-то не рассчитывал встретить в архитектурной дискуссии незнание основ RDBMS. Поэтому надеюсь на то, что я просто вас не так понял. Но, на всякий случай выражаю готовность поделиться всем, что знаю сам.

ты про то, что я написал views вместо materialized views? жестко

КЛ>>ну спроектируй тут, только без хаков с db.OutboundInvoices, db.InboundInvoices — одна таблица, row-level security и тп.

S>Непонятно, что такое "хаки".

разбиение на 2 таблицы, потому что по коду неочевидно, что у тебя одна таблица

КЛ>>я тебе набросал _примерную_ схему, ты

КЛ>>же мне ответил "недостаточно вводных данных".
S>Вы жульничаете. Схему вы набросали про фильтрацию строк, а задачу, про которую я ответил "недостаточно данных" — про какую-то (непонятно какую) обрезку атрибутов.
S>И ни в одном из случаев нет ничего про постановку задачи. Выглядит так, что вы стараетесь сначала придумать решение, а уже потом любой ценой его защитить, вообще не задумываясь, а зачем такое решение нужно.

да я просто рассказываю что я видел в своей практике

КЛ>>какая чушь

S>Не, беру свои слова по поводу "поделиться всем, чем знаю" обратно.

"Вот зачем вы пишете бред." — твои слова выше. Но согласен, я мог бы и помягче, сори
Отредактировано 18.04.2025 15:31 Константин Л. . Предыдущая версия .
Re[34]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 18.04.25 16:12
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>ну так ведь это же даже не секьюрити а костыль.

Хотелось бы более внятных обоснований такого утверждения.

КЛ>вы ошибку использования переносите на ошибку проектирования.

Подобное проектирование означает "давайте я не буду разбираться в сценариях пользователя, а перевалю ответственность за них на тех, кто моё творение будет эксплуатировать". Примерно так же, как "настраиваемый пользователем
гуй". Да, бывают ситуации, когда мы не можем заранее спроектировать все нужные сценарии — потому что собственно поставляем не приложение, а конструктор.
Но это не потому, что это хорошая практика — это вынужденное решение. Есть возможность его избежать — надо его избегать.

КЛ>простые — да. но мир сложен. учим вот но ты ни в какую)

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


КЛ>я тоже, сори




КЛ>Вы писали "Это когда мы заводим для пользователя №44487 виндовый аккаунт, даём этому аккаунту права на SQL базу с табличками forums, topics, replies, и marks, при логине на сайт создаём виндовую сессию, и все запросы в SQL Server выполняем через новое соединение под правами этого виндового аккаунта."

КЛ>в постгрес так никто делать не будет в здравом уме
И нигде не будет. Этот подход придуман в SQL-92, расширен в SQL-99, и примерно тогда же устарел навсегда.
Я приводил его как пример применения принципа, который был уместен в клиент-серверных приложениях эпохи девяностых.
Сейчас технологическая основа изменилась, а принципы — нет.
Вместо "таблицы" у нас "микроссервис с сырыми данными", вместо "хранимой процедуры" или "представления" у нас "микросервис фасада", а в остальном всё так же и есть.

Оппонент предлагает таскать токен внешнего пользователя сквозь всю иерархию сервисов — типа я обращаюсь к микросервису "invoices", а тот, в свою очередь, бежит за подробностями отправителя инвойса к микросервису "counteragents", отдавая туда мой же токен. И вот тут-то у нас и возникает чудо голодания: микросервис "counteragents" возвращает ему 403/404, если у меня нет привилегии смотреть запрошенного контрагента. И, соответственно, фасадный микросервис отдаёт мне инвойс без атрибута sender.

Я пытаюсь объяснить, что такое решение не вполне удачно.

КЛ>а где там фильтрация по юзеру? Это:


КЛ>
КЛ> IQueryable<OutboundInvoice> InvoicesSentBy(CompanyID currentCompany) =>  
КЛ>    from i in db.OutboundInvoices where i.originator = currentCompany select i;
КЛ>  IQueryable<InboundInvoice> InvoicesSentTo(CompanyID currentCompany) =>
КЛ>    from i in db.InboundInvoices where i.destination = currentCompany select i;
КЛ>

Да. В исходной задаче не было никакого требования "разделять инвойсы по конкретным пользователям". В 99% случаев такого бизнес-сценария вовсе нет.
Например, на сайте RSDN нет никаких ручек для выдачи произвольным пользователям произвольных пермиссий на конкретные сообщения. И ничего, за 25 лет никто не умер от этого.
Так и тут — мы провели анализ предметной области, выяснили сценарии пользователей, и обнаружили, что нужно всего два набора пермиссий — на "инвойсы, выставленные компанией, где пользователь работает", и на "инвойсы, полученные компанией, где пользователь работает". (Это ещё сложный случай, сервис для B2B взаимодействия. Если мы пилим сервис P2P, то там модель безопасности будет ещё проще).
Откуда взялись эти наборы пермиссий? Да из того, что в исследованных нами компаниях-клиентах встречаются следующие случаи:
1. One person does all accounting
2. One department does all accounting
3. There are accounts payable and accounts receivable departments
Случаев "право оплатить конкретный один инвойс нам нужно назначить одному конкретному сотруднику" мы обнаружить не смогли, как ни старались.
Тем более у нас не нашлось случаев "надо выдать доступ к каким-то инвойсам, выставленным компанией X компании Y, сотруднику какой-то посторонней компании Z"
Поэтому мы делаем так, как описано в коде выше.
И это обеспечивает одновременно высокую безопасность (нет возможности напороть с настройками при эксплуатации), высокую производительность (все поисковые запросы можно ускорить путём построения подходящих индексов), и высокое удобство пользования.

На всякий случай, если непонятно: вот у нас сотрудник компании X (с соответствующими правами) выставляет инвойс компании Y.
Этот инвойс виден всем уполномоченным сотрудникам компании X, а особо уполномоченные могут даже его отзывать и редактировать.
Но с момента, когда он переведён в статус "отправлен получателю", он должен стать виден всем уполномоченным сотрудникам компании Y.

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

КЛ>ты про то, что я написал views вместо materialized views? жестко

Я вообще не понимаю, откуда в рассуждениях взялись materialized views.

КЛ>разбиение на 2 таблицы, потому что по коду неочевидно, что у тебя одна таблица

Ну хорошо, давайте поговорим об этом подробнее.
public class PaypalDb : LinqToDB.Data.DataConnection
{
  public PaypalDb() : base("everything") { }

  public ITable<OutboundInvoice>  OutboundInvoices => this.GetTable<OutboundInvoice>();
  public IQueryable<InboundInvoice> Category => from oi in this.OutboundInvoices select Mapper<OutboundInvoice, InboundInvoice>.DefaultMapper.Map(oi);
  // ... other tables ...
}

Если бы речь шла не о дотнете, а о чём-то более убогом, то я бы, наверное, создал в БД
create view InboundInvoices as
select 
    originator, 
    originatorName, 
    amount, 
    sentDate, 
    status
    expirationDate, 
    destination, 
    destinationName, 
    amount, 
    amountVAT
from Invoices

КЛ>да я просто рассказываю что я видел в своей практике
Отлично.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[14]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 18.04.25 16:22
Оценка:
Здравствуйте, Miroff, Вы писали:

M>Именно! В этом и смысл REST, выражать сложную логику через очень простой CRUD

Именно поэтому у Paypal — не REST.
На основе их API, вы никак не можете "сделать GET" на рефанд, потому что у них рефанд — это POST на магический урл.
И никто вам параметров этого рефанда не подскажет, кроме, собственно, документации.
А если у вас есть документация, то вам нафиг не упала ссылка на рефанд в каждом пейменте. Вы и так поймёте, куда нужно отправить те параметры, которые описаны в документации.

Вообще, первый REST API, в разработке которого я участвовал, был устроен как раз примерно так.
Только мы были ещё более радикальны: в зависимости от того, какое расширение было в конце запрошенного URL (.xml, .json, .html), отдавалось разное представление ресурса.
И вот в HTML представлении в тех местах, откуда можно было делать параметризованные запросы (включая POST), приезжала форма с полями и соответствующим action.
И если у параметров было конечное количество значений, то они там в input type=select указывались.
Так что по API можно было бродить обычным браузером. HATEOASнее уже некуда.
Даже и не помню, какой это был год. Наверное, что-то вроде 2008 или 2009.

Потом оказалось, что нафиг это всё никому не упало.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[9]: Помогите правильно спроектировать микросервисное приложение
От: TG  
Дата: 18.04.25 17:59
Оценка:
Здравствуйте, Ziaw, Вы писали:

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

Z>Про лучший вариант архитектуры соглашусь. Если взять что-то сравнимое по сложности, типа Яндекс 360, то релизный цикл похожий. Более того, подозреваю, что именно микросервисная архитектура этого изделия сделала невозможной его доводку до приличного состояния. То же можно сказать и про интерфейс яндекс облака, там уши всяких узкосервисных проблем торчат регулярно, но там хотя бы бабло идет. Интересно, есть тут кто-то близкий к этим командам Яндекса, чтобы прокомментировать.

А зачем сравнивать ядро линукса и современные бизнес-приложения (вернее бизнес-сервисы)? У них же разная, скажем так, архитектурная топология. Бизнес-сервисы это уже распределенные системы как минимум по причине наличия БД.
Re[35]: Каких программ вам не хватает?
От: Константин Л. Франция  
Дата: 18.04.25 18:05
Оценка:
Здравствуйте, Sinclair, Вы писали:

[]

я понял, dto/so на роль, вьюха на роль и все. и мы приходим к первоначальному конфликту — такое не работает, когда ролей много, когда нужны fine-grained permission etc. В смысле, не работает только у нас, у тебя — работает!
Re[36]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 19.04.25 04:29
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>я понял, dto/so на роль, вьюха на роль и все. и мы приходим к первоначальному конфликту — такое не работает, когда ролей много, когда нужны fine-grained permission etc. В смысле, не работает только у нас, у тебя — работает!

Вы сначала расскажите, что за задача. А там уже можно обсуждать, какие решения лучше, а какие — хуже.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[28]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 19.04.25 05:02
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>сколько систем ты так сделал и сколько у них юзеров и ролей?

Ну, я участвовал в системах, где у одной "инсталляции" до 1.5 миллиона пользователей. Типичный размер — около 100к.
Ролей — в пределах нескольких десятков. Это прямо максимум-максимум.
Не сказать, чтобы прямо "я сделал" — но наблюдал и участвовал в процессе проектирования изнутри компании.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[10]: Помогите правильно спроектировать микросервисное приложение
От: Ziaw Россия  
Дата: 21.04.25 07:54
Оценка:
Здравствуйте, TG, Вы писали:

TG>А зачем сравнивать ядро линукса и современные бизнес-приложения (вернее бизнес-сервисы)? У них же разная, скажем так, архитектурная топология. Бизнес-сервисы это уже распределенные системы как минимум по причине наличия БД.


Где я сравнивал? Я привел пример, что сложная система в виде монолита может существовать и хорошо управляться. Пример хорош тем, что все открыто и изучаемо.

Если у тебя есть поинт, что оно может существовать только потому, что там нет БД или "распределения", то раскрой тему. И тут бы уточнить, что ты имеешь в виду, уж распределеннее линуксов что-то придумать крайне сложно.
Re[9]: Помогите правильно спроектировать микросервисное приложение
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 21.04.25 08:05
Оценка:
Здравствуйте, Ziaw, Вы писали:

G>>Много причин использования МСА, далеко не все они оправданы с точки зрения экономики.

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

Простите, не видел чтобы внедрение МСА сложность уменьшало. Сложность системы обычно кратно возрастает после такого, а небольшой бонус в виде независимого деплоя и ускорения сборки отдельных компонент зачастую не сможет перекрыть увеличение сложности системы и проблем для конечных пользователей
Re[10]: Помогите правильно спроектировать микросервисное приложение
От: Ziaw Россия  
Дата: 21.04.25 08:08
Оценка:
Здравствуйте, gandjustas, Вы писали:

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


Конечно прощу, я тоже не видел. Зато видел, как этим успешно мотивировали выбор МСА, ведь монолит сложно поддерживать.
Re[28]: Каких программ вам не хватает?
От: Ziaw Россия  
Дата: 21.04.25 12:00
Оценка:
Здравствуйте, ·, Вы писали:


S>>Ну вот так и не выносим. Оракл является подробностью реализации этого "питонячьего сервиса" и ниоткуда больше не виден. Впрочем, это может быть и не оракл — "питонячьему сервису" с запасом может хватить sqlite.

·>Он виден с т.з. анализа безопасности.

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

Что передаете в БД в качестве субьекта авторизации? id юзера? Набор ролей? Есть ли роли, которые действуют на определенные сущности (например в этой организации юзер админ, а в этой простой гость)?

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

Как поступаете, если в какое-то поле юзер может писать только если это конкретный бизнес процесс со своими правилами, предусловиями и постусловиями? К примеру храним стейт из развесистой стейт-машины и от этого стейта зависит очень многое в плане можем писать/не можем писать. Как например будет выглядеть правило "посты редактируются редактором и корректором, никто, кроме суперадмина не может удалять ссылки и фотографии из опубликованного поста, заархивированный пост нельзя увидеть в ленте никому, но в админке его видят все сотрудники и суперадмин может его вернуть в ленту"?
Re[29]: Каких программ вам не хватает?
От: · Великобритания  
Дата: 21.04.25 12:56
Оценка:
Здравствуйте, Ziaw, Вы писали:

S>>>Ну вот так и не выносим. Оракл является подробностью реализации этого "питонячьего сервиса" и ниоткуда больше не виден. Впрочем, это может быть и не оракл — "питонячьему сервису" с запасом может хватить sqlite.

Z>·>Он виден с т.з. анализа безопасности.
Z>Коллега, я немного запутался в вашей дискуссии, подскажи, я не ошибся, ты действительно топишь за обеспечение секьюрити данных на уровне БД?
Если в том смысле, что используются средства БД типа как встроенные механизмы row level security, аккаунты в самой бд, вьюшки и т.п. (о чём писал Sinclair) — то нет.

Z>Что передаете в БД в качестве субьекта авторизации? id юзера? Набор ролей? Есть ли роли, которые действуют на определенные сущности (например в этой организации юзер админ, а в этой простой гость)?

В бд формируются запросы в зависимости от пермиссий... Т.е. это просто ещё как бы один критерий поиска, как тут Константин Л писал.

Z>На каком языке пишете код правил доступа, сколько страниц текста он занимает, как его храните, ревьюите, тестируете, разворачиваете?

На оснвном ЯП, обычно java, как и любой другой код.

Z>Как поступаете, если в какое-то поле юзер может писать только если это конкретный бизнес процесс со своими правилами, предусловиями и постусловиями? К примеру храним стейт из развесистой стейт-машины и от этого стейта зависит очень многое в плане можем писать/не можем писать. Как например будет выглядеть правило "посты редактируются редактором и корректором, никто, кроме суперадмина не может удалять ссылки и фотографии из опубликованного поста, заархивированный пост нельзя увидеть в ленте никому, но в админке его видят все сотрудники и суперадмин может его вернуть в ленту"?

Это же несколько независимых правил.
Отдельно есть пермиссии "редактирование поста", "удаление ссылок", "удаление фот", "просмотр архива" и т.п. И отдельно роли: "редактор", "корректор", "админ", "суперадмин"... и маппинг — что какая роль может.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[30]: Каких программ вам не хватает?
От: Ziaw Россия  
Дата: 21.04.25 13:04
Оценка:
Здравствуйте, ·, Вы писали:

·>Если в том смысле, что используются средства БД типа как встроенные механизмы row level security, аккаунты в самой бд, вьюшки и т.п. (о чём писал Sinclair) — то нет


Ок. На языке высокого уровня это примерно понятно как решается.