Как стать автором
Обновить

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

реализация технологии стирающей различия между вызовами локального и удаленного кода


Не увидел ни одного теста производительности в статье.
Тема производительности выходит за рамки «первого приложения». Эту тему планирую раскрыть позднее.

Тогда почему хаб "высокая производительность"?

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

Так это утверждение вроде бы нуждается в доказательстве, разве нет?

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

Значит, в рамках простого приложения этот хаб указан безосновательно.

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

Это утверждение нуждается в доказательстве.


В рамках простого приложения этот хаб относится к фремворку,

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

Зачем ходить по кругу, возвращаясь многократно к одному и тому же? Этот вопрос за рамками этой статьи.

Если этот вопрос за рамками этой статьи, то эта статья — за рамками хаба "Высокая производительность". О чем, собственно, я сразу и написал.

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


DemoCascadeFunction

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

Постараюсь раскрыть эту тему в следующей статье.

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

Никогда такого не было и вот опять?


Признайтесь, как вы решили проблему обледенения chatty vs chunky?

Тут упорно избавляются от JSP и сервлет-конфигов последние лет 10, про RMI только в кГовавом энтеГпГайзе помнят.
А тут мало того, что напиши remotable bean, зарегистрируй его в конфиге, так еще и интерфейс ручками там же свяжи.
Ради всего святого — зачем?
Жизненный цикл программного обеспечения имеет несколько периодов, самый продолжительный из которых — эксплуатационный. У эксплуатирующей организации возникает много разных непредвиденных ранее требований к программному обеспечению. Файл конфигурации позволяет эксплуатирующей организации самостоятельно реагировать на часть возникающих новых требований.

На мой взгляд, вынос параметров в конфигурационный файл — это «правило хорошего тона».

«Зачем?» — ограничено только вашей фантазией. Допустим, что нужно 100% зарезервировать функционал DemoFunction. Что для этого нужно? Опубликовать DemoFunction на множестве узлов и поменять конфигурацию системы. Все. Допустим, что Вам нужно поймать событие вызова метода getInfo() класса DemoFunction. Создаете «каскадную» функцию, которая вызывает DemoFunction и отдает результат DemoApplication попутно выполнив требуемые Вам действия и меняете конфигурацию. Допустим изменился технологический процесс и часть функций вашей информационной системы потеряла актуальность. Для вывода из эксплуатации этой часть достаточно убрать ее из конфигурации системы.
Допустим изменился технологический процесс и часть функций вашей информационной системы потеряла актуальность. Для вывода из эксплуатации этой часть достаточно убрать ее из конфигурации системы.

И информационная система магически перестанет вызывать эту "часть системы"?

Перестанет и пользователи перестанут видеть эту часть в своем интерфейсе.

Благодаря описанной в посте технологии? Что случится при обращении к first.jsp при такой конфигурации?

Прошу не путать приложение «Hello world» c промышленным приложением.

Значит, эта часть мотивации неактуальна.

Это уже дело вашей фантазии как Вы реализуете эту функциональность. Например, 2 года назад, в одном из своих приложений подобным образом была отключена часть утратившей актуальность функций, находящееся в эксплуатации с 2007 года. Приложение, при старте "видит" список объектов в своей конфигурации и на основании этого списка строит пользовательский интерфейс. Отключение одного из элементов в конфигурации привело и к изменению в пользовательском интерфейсе, все связанные с этим элементом пункты меню "чудесным образом" пропали.

Это уже дело вашей фантазии как Вы реализуете эту функциональность

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

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


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

Использовать для этих целей конфигурацию приложения очень удобно

Конфигурацию приложения в общем понимании? Да. Конфигурацию, как вы ее подаете? Не обязательно.


Риск внести ошибку или "сломать" ИС минимальный.

Минимальный из каких вариантов?

Минимальный по сравнению с внесением изменений в ПО

Я еще раз повторю: внесение изменений в конфигурацию — это и есть внесение изменений в ПО, поэтому ваше противопоставление бессмысленно.

Изменение конфигурации — это не изменение ПО. Конфигурация — переменная составляющая. ПО — неизменная составляющая.

Изменение конфигурации — это не изменение ПО.

Почему это?


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


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

Разница огромная! Для изменения конфигурацию достаточно любого текстового редактора. Для приведенного примера достаточно закомментарить или удалить секцию конфигурации. А что нужно для внесения изменений ПО, потрудитесь описать.

Для изменения конфигурацию достаточно любого текстового редактора.

Я не зря написал про Python. Для внесения изменений достаточно того же самого текстового редактора.


Или вот возьмите AWS Lambda (или API Gateway, не важно): когда я там что-то меняю — это изменение настройки или ПО? И как вы отличаете одно от другого?


Разница огромная!

Напомню вопрос: "Какая для конечного пользователя разница". Разве он вообще видит, каким редактором вы пользовались для внесения изменений?

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

Не важно, какой язык Вы используете, важно трудаемкость процесса.

И почему вы утверждаете, что для конфигурации она меньше?


Сколько строк кода Вам потребуется вычистить в случае отключения какой то части системы?

В правильно спроектированной системе? Одну.


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

Нет, конечно. Но и человек, правящий конфигурацию, не может быть в этом уверен.


А вам не приходилось слышать, что "этот код написан очень давно и никто толком не помнит как он работает и лучше его не трогать"?

А вам не приходилось слышать "эта строчка в конфигурации написана очень давно, и лучше ее не трогать"?

  1. Конфигурацию может поправить любой специалист.


  2. У Вас такой не найдется


  3. Может. 100% выполнить эту операцию без ошибки.


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


НЛО прилетело и опубликовало эту надпись здесь
Конфигурацию может поправить любой специалист.

Код может поправить любой специалист.


У Вас такой не найдется

Не найдется чего, простите?


Может. 100% выполнить эту операцию без ошибки.

Если он может, то и я могу. Удалить одну строчку кода — просто.


Не приходилось!

Вам повезло. А мне приходилось, и неоднократно.

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

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


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

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

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


А главное, все это не имеет никакого отношения к тому, является ли изменение конфигурации изменением ПО.

Наши разные взгляды на обязанности администратора системы выходят за рамки рассматриваемой теме

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


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

Моя точка зрения остается неизменной — изменение конфигурации не является изменением ПО. Для меня ваши аргументы не убедительны. Давайте закроем эту тему, она не относится к теме публикации.

Для меня ваши аргументы не убедительны.

… однако опровергнуть их вам не удалось.


Давайте закроем эту тему, она не относится к теме публикации.

Да нет, напрямую относится. Если из вашего решения выкинуть конфигурацию, что останется?

А Вы доказать вашу правоту не можете. И кто из нас прав?

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

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

Доказано практикой.

Чьей практикой? Конкретные примеры, исследования, case studies — в студию.


Не сталкивались вы с подобными проблемами

Какими "подобными"?

Чьей практикой?

многолетней практикой эксплуатации распределенных систем


Какими "подобными"?

с проблемами эксплуатации распределенных систем

многолетней практикой эксплуатации распределенных систем

Я, мне кажется, спрашивал чьей.


с проблемами эксплуатации распределенных систем

Вы этого знать не можете, и, как следствие, ошиблись.

ответил ниже


Вы этого знать не можете, и, как следствие, ошиблись.

Тогда странно слышать от Вас некоторые вопросы, при наличии опыта то.

Тогда странно слышать от Вас некоторые вопросы, при наличии опыта то.

Мне тоже странно слышать ваши утверждения, "при наличии опыта-то". Что лишний раз показывает, что (а) опыт у всех отличается и (б) опыт ничего не гарантирует.

У Вас свое представления — как правильно, у меня — свое. возможно мы оба правы. Но у меня пока нет причин менять свою точку зрения.

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

В 2003 году развернул свою первую распределенную систему — реального времени. Масштаб развертывания — вся страна (напомню, у нас много часовых поясов). Система находится в эксплуатации до сих пор. Узлов системы много. С тех пор многократно менялось ПО системы. Происходила миграция узлов на другие аппаратные средства. Узлы меняли свою дислокацию на территории страны. И ни разу не было зафиксировано ни одно сбоя по причини ошибок установки ПО или изменения конфигурации узлов. "Косяки" при обслуживании БД были, проблемы связи — были, внесенные ошибки в отдельную функциональность — были, проблемы со смежными системами, влияющими на работоспособность — были.

Ну то есть вы опираетесь в качестве доказательства на свою собственную практику?

"опыт ошибок трудных"

… и вас это не смущает, я понял.


Я вам честно скажу: при выборе между вашим опытом эксплуатации распределенных систем и аналогичным опытом Google я выберу Google.

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

Вы предлагаете мне считать, что вероятность того, что вы ошибаетесь, меньше, чем вероятность того, что — раздельно друг от друга — ошибаются Google и Хамбл/Фарли (ну и, очень скромно, мой опыт тоже)?

Ни в коем случае, лишь отметил, что они тоже могут ошибаться.

Несомненно, могут. Однако, мое утверждение выше о выборе авторитета остается в силе.

Любите Вы ходить "по кругу"

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

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

Оч смешно.
Я когда-то в одно щачло поднял интеграционную платформу с таким низким уровнем вхождения, что типовые скрипты служба поддержки клиентов сама разрабатывала и внедряла чуть ли не копипастя с известного. и объем редко превышал сотню строк.
На мой взгляд, вынос параметров в конфигурационный файл — это «правило хорошего тона».

Параметров — да. А связывание классов — это уже ответственность слоя бизнес-логики. Был бы у вас целевой класс имплементором удаленного интерфейса — можно было бы применять autodiscovery. Постойте-ка… Но это же RMI!

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

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


Второе, предложенное решение как раз и раскладывает все "по полочкам". И это называется "модифицируемостью" — простотой модификации промышленной системы. Каждый программный слой выполняет только свою функцию. Бизнес логика постоянно меняется. Предложенное решение позволяет IT подразделению заказчика более гибко реагировать на требование бизнеса, а не ждать "у моря погоды", когда будут выделен бюджет на модификацию ПО для удовлетворения "неожиданно" возникших новых требований или изыскивать другие "обходные" решения, например: — "Вы нам сделаете сейчас, а оплатим мы вам из бюджета следующего года".

Предложенное решение позволяет IT подразделению заказчика более гибко реагировать на требование бизнеса, а не ждать "у моря погоды", когда будут выделен бюджет на модификацию ПО

Реагировать на требования без модификации ПО? Ну то есть пришел бизнес и говорит "хочу, чтобы курс валют теперь брался из сервиса ЦБРФ, а не вбивался руками", и?..

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

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


А в-третьих, и в самых важных, когда вы говорите "эксплуатируемое ПО не изменяется", вы лукавите. Конфигурация — такая же часть эксплуатируемого ПО, как и код, и изменения в ней должны проходить тот же самый цикл при развертывании; с практической точки зрения нет (не должно быть) разницы, выкатываете вы изменения в коде или изменения в конфигурации.


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

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


  2. "Ручной ввод" он же куда сохраняет результаты свой работы, из конфигурации исключаем функцию "ручного ввода" и включаем функцию "загрузки с сайта" с сохранением "в то же место".


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


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

Ну так что же мешает внести их прямо в ПО?


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

Гм. А как вы из удаленно выполняющейся "функции" получите доступ к "тому же месту"?


(Я даже не спрашиваю, как вы собираетесь вызывать это по расписанию)


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

Нет, не соглашусь. Для кода обычно доступно больше средств проверки, чем для конфигурации.

А зачем? При вносе изменений прямо в ПО есть риск внести какую то ошибку? Есть. Для изменения ПО необходимо наличие IDE? Необходимо. И т.п. и т.д. Этот процесс гораздо сложнее и "дороже".


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


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

Вот только при вашем способе есть ещё больше способов внести какую-то ошибку.

При вносе изменений прямо в ПО есть риск внести какую то ошибку? Есть.

… такой же, как при написании "функции" отдельно.


Для изменения ПО необходимо наличие IDE? Необходимо.

… так же, как и для написания "функции" отдельно.


Этот процесс гораздо сложнее и "дороже".

Нет, почему бы? Он точно такой же, как при написании "функции" отдельно.


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


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

Это еще надо доказать.


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


А уж по реализацию шедуллера я вообще молчу.

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


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

В смысле — рантайм сообщений? Так это дважды поздно. Меня интересует проверка на этапе разработки, если не получится — на этапе сборки, если и это не получится — на этапе тестирования.


В своих системах предпочитаю реализовывать подобный подход.

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

НЛО прилетело и опубликовало эту надпись здесь

В логе будет зафиксировано предупреждение


SYS0103W Экземпляр класса "ru.funsys.demo.avalanche.DemoAdapterr" узла <adapter> не создан (класс не найден).

НЛО прилетело и опубликовало эту надпись здесь

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


Сообщения информативны и однозначны.


В промышленных системах система диагностики "многоярусная", ошибка находиться и устраняется.

НЛО прилетело и опубликовало эту надпись здесь

Преимущества в другом — готовый сервис для создания распределенных масштабируемых систем.


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

НЛО прилетело и опубликовало эту надпись здесь

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

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

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

Все без исключения ошибки инициализации ловятся.

… на этапе инициализации.


А я говорю про более ранний этап.

На каком? На этапе написания кода? Код не изменялся, ловить там нечего!

На каком?

Написания конфигурации, сборки пакета или развертывания пакета.

Пакет собран и развернут, конфигурация внешний объект по отношению в собранному и развернутому пакету. Тем более речь идет о системе с множеством узлов и у каждого узла может быть собственная индивидуальная конфигурация. ПО везде одинаковое, а конфигурация везде разная. Будете ваши пакеты под каждый узел собирать? А если их 40 штук? А завтра заказчик захочет 1000 иметь? Что будете делать?

конфигурация внешний объект по отношению в собранному и развернутому пакету.

Это противоречит практикам стабильного развертывания. Вы Хамбла/Фарли не читали?..


Будете ваши пакеты под каждый узел собирать?

Конечно. Это же очень просто.


А если их 40 штук? А завтра заказчик захочет 1000 иметь? Что будете делать?

Версионнику более-менее все равно, хранить один файл конфигурации, 40 или 1000.


Простите за прямой вопрос: а как вы меняете конфигурацию в продакшн-системах?

Это противоречит практикам стабильного развертывания. Вы Хамбла/Фарли не читали?..

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


Простите за прямой вопрос: а как вы меняете конфигурацию в продакшн-системах?

В продакшен, а каких же еще?

В промышленных системах непрерывной доступности не нужно быстрое развертывание.

А я где-то что-то сказал про быстрое развертывание?


Там нужна плановость и управляемость

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


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

Нет, я обращаюсь к тому, кто отвечает за развертывание этого участка (это могу быть и я сам), и он собирает новый пакет.


В продакшен, а каких же еще?

Я спросил как вы это делаете. Ну, по шагам, в смысле.

Так как же вы меняете конфигурацию системы в продакшн?

Да в продакшен, на пассивных узлах — узлах не несущих нагрузки. После внесения изменений в конфигурацию и проверки функционирования узла он возвращается в систему.

Я уточню еще раз, вдруг я неправильно понял: вы просто меняете (руками, в редакторе или копированием) файлы конфигурации на узлах системы, не несущих нагрузки?

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

Но операция все равно та, которую я описал — ручное изменение конфига на узле?

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

Не важно, какие изменения, просто ответьте на прямой вопрос: да, меняют руками, или нет, меняют как-то иначе?

Давно ответил, в любом текстовом редакторе. Да, меняют руками. Я "за" более простые схемы эксплуатации, если можно не использовать в эксплуатации дополнительное ПО, то значит его НЕ НУЖНО использовать. Это понижает требования к сменному персоналу. В критической ситуации какой сотрудник будет ее устранять предсказать невозможно. У сменного персонала сотни разных систем в зоне ответственности.

Подводя итог, я вижу следующее:


  1. 1000 экземпляров.
  2. Настраиваются вручную.
  3. У каждого, потенциально, своя уникальная конфигурация.

И это всё как бы надёжно работает?


Да вас вообще даже близко подпускать к построению архитектуры нельзя!

работает

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

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

С версионностью нет проблем

Правда? И как же вы обеспечиваете версионность конфигураций, которые правятся вручную в текстовом редакторе на продакшн-серверах?

Так же как и ваше система версионности, создается копия файла. При желании могут вставляется соответствующий комментарий. Это не существенный вопрос и выходит за рамки темы.

Так же как и ваше система версионности, создается копия файла.

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


Это не существенный вопрос и выходит за рамки темы

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

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


Вы ушли от темы статьи.

Вам остается только поверить мне на слово.

Зачем мне это? Я предпочту работать с решениями, где не надо верить на слово, а все можно проверить.


Архитектура система разработана так, что хранить копии конфигурационных файлов не нужно

Мы говорим про конкретную технологию, предлагаемую вами в статье. И как там это "разработано"?


хранить копии конфигурационных файлов не нужно

Вы только что писали "создается копия файла".


Вы ушли от темы статьи.

Нет. Подавляющая часть статьи о том, как можно прописать привязки в комментариях. Я, как и некоторые другие комментаторы, считаю, что это плохо и неправильно. Следовательно, дискуссия, почему это неправильно — по теме статьи.

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

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

Рекомендация — это то, что люди могут проигнорировать.


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


Но если по каким либо причинам она не будет сделана, ни какой трагедии не произойдет. Система в целом останется в рабочем состоянии.

В общем случае это утверждение заведомо ложно.

жаль. что тут нет смайликов.


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

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

В общем случае это утверждение заведомо ложно.

В общем случае это утверждение заведомо ложно.

Вот это уже с вашей стороны перебор.

Конечно, нет. Я же говорю про общий случай.

Конечно, нет. Я же говорю про общий случай.

Это ложное утверждение

Утверждение "я говорю о"? О нет.

Да вас вообще даже близко подпускать к построению архитектуры нельзя!

Это не Вам судить.


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


Так что работает НАДЕЖНО и не требует постоянного "присмотра"

Это не Вам судить.

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

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


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


И да, вернемся к вашему примеру. Вот у вас есть кластер из тысячи узлов (масштабируемость/отказоустойчивость). Вам надо поменять на всем кластере одну настройку. Сколько усилий на это уйдет, и какова вероятность ошибки? А теперь внезапно выяснилось, что настройку менять было не надо, и надо весь кластер откатить обратно. Сколько усилий, какова вероятность ошибки?

Сменный персонал не лазит в конфиги от скуки

А я, вроде бы, и не говорил ничего про скуку. Это рутинная работа по обслуживанию.

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

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

При плановых изменениях все прописано — что делать, как откатывать. С этим нет проблем.

"Все прописано" — это хорошо, но кто это делает?


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


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

Автоматизировать можно все! Лететь на Марс можно хоть сейчас — только сейчас это очень дорого стоить!


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

только сейчас это очень дорого стоить!

Лететь на Марс, возможно, "очень дорого". Автоматизировать доставку ПО — не очень.


Если текущий процесс не требует затрат, зачем "изобретать велосипед"

Никто не предлагает изобретать велосипед, есть готовые работающие решения.


А зачем? Затем, что вы получаете стабильный и воспроизводимый процесс изменения системы. Вы знаете, в каком состоянии система сейчас, и почему, когда и кем была внесена та или иная настройка.


В каком-то смысле это вопрос того же толка, что и "зачем нужно управление версиями кода". Правда, а зачем?

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

для системы это "изобретение велосипеда"

Конечно, нет. "Изобретение велосипеда" — это вполне конкретный антипаттерн, подразумевающий повторное придумывание уже существующей функциональности. Я же предлагаю взять готовое.


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

С равным успехом в нужный момент может не оказаться доступа к продакшн-серверу.


Я повторю свой вопрос: зачем нужно управление версиями кода? Текущий процесс не требует затрат, в нужный момент система управления версиями (и сборщик) могут оказаться недоступными… зачем?

С точки зрения системы — это именно именно велосипед. При этом — велосипеда, повышающего вероятность отказа системы!


Сравнили тоже версионность кода и конфига! Конфиг в течении жизненного цикла меняется не существенно. Изменения конфига редкая операция и, как правило, меняются какие то значения атрибутов, добавляются или удаляются какие строки.


Изменения исходника может затронуть весь файл. И таких файлов тьма тьмущая. И таких изменений может быть каждый день, несколько раз на дню.

С точки зрения системы — это именно именно велосипед.

Докажите это утверждение.


Конфиг в течении жизненного цикла меняется не существенно.

В течение жизненного цикла чего?


Изменения конфига редкая операция

Это утверждение в общем случае неверно. Особенно оно неверно в контексте предлагаемого вами "не хватает ресурсов — переразвернули на кластере и поправили конфиг".


Изменения исходника может затронуть весь файл. И таких файлов тьма тьмущая. И таких изменений может быть каждый день, несколько раз на дню.

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


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

Есть одна система многолетней эксплуатации, вы предлагаете другую. Что из этого вытекает? (Оставлю это Вам на размышление.)


"жизненного цикла" эксплуатации системы


Да ежедневно и ежечасно только и вносят изменения в конфиги из "нехватки" ресурсов.


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

Есть одна система многолетней эксплуатации, вы предлагаете другую. Что из этого вытекает?

Что у существующей есть видимые мне недостатки.


"жизненного цикла" эксплуатации системы

В таком случае, это утверждение в общем случае неверно.


Да ежедневно и ежечасно только и вносят изменения в конфиги из "нехватки" ресурсов.

Вы про эластичное масштабирование не слышали?


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

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

Что у существующей есть видимые мне недостатки.

Это ложное утверждение.


В таком случае, это утверждение в общем случае неверно.

Это ложное утверждение.


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

Про то, что Вы написали при обсуждении, у меня сложилось впечатление, что ваша работа "носить воду в ступе".

Это ложное утверждение.

А теперь докажите это высказывание.


Про то, что Вы написали при обсуждении, у меня сложилось впечатление, что ваша работа "носить воду в ступе".

… ошибочное.

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


Это все равно, что художник, который каждый свой день начинает писать одну и ту же картину заново.


Дискуссия на эту тему закрыта.

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

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


Это все равно, что художник, который каждый свой день начинает писать одну и ту же картину заново.

Это называется "эскизы".

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


Носите "воду в ступе" и далее. Всего хорошего. Дискуссия закрыта!

Еще раз — речь идет о конфигурациях системы, а не ее исходных кодах.

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

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


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

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

Операция изменения кода — разовая операция. Она может потребоваться раз в месяц, раз в полгода или вообще никогда не потребуется ее выполнять.


И еще утверждаете, что это верх совершенства.

Нет, не утверждаю (в противном случае вы легко можете найти цитату, где я это утверждаю, не правда ли?)


Но я задал вам вопрос:


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

И вы снова на него не ответили.

Не пишите глупости.

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

Вы откровенно занимаетесь троллингом. Не надо.

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

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

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

Ни кто Вам не мешает написать статью и поделиться своим решением. Пишите.

Ну вот я и пишу. Просто не вижу смысла писать статью исключительно для критики чужих решений.

Вы напишите о своем решении

А зачем мне это?

не хоте как хотите

Простой тест, кстати.


Это код или конфигурация? (только сразу объясните, почему)


Текст
{
  "StartAt": "select-task",
  "States": {
    "select-task": {
      "Type": "Choice",
      "Choices": [
        {
          "Variable": "$.startAt",
          "StringEquals": "describe-endpoint",
          "Next": "describe-endpoint"
        },
        {
          "Variable": "$.startAt",
          "StringEquals": "deploy-model",
          "Next": "deploy-model"
        }
      ],
      "Default": "train"
    },
    "train": {
      "Type": "Task",
      "Resource": "arn:aws:states:::sagemaker:createTrainingJob.sync",
      "Parameters": {
        "TrainingJobName.$": "$.inputs.TrainingJob.TrainingJobName",
        "Tags.$": "$.inputs.Tags",
        "AlgorithmSpecification.$": "$.inputs.TrainingJob.AlgorithmSpecification",
        "RoleArn.$": "$.inputs.TrainingJob.RoleArn",
        "ResourceConfig.$": "$.inputs.TrainingJob.ResourceConfig",
        "HyperParameters.$": "$.inputs.TrainingJob.HyperParameters",
        "StoppingCondition.$": "$.inputs.TrainingJob.StoppingCondition",
        "InputDataConfig.$": "$.inputs.TrainingJob.InputDataConfig",
        "OutputDataConfig.$": "$.inputs.TrainingJob.OutputDataConfig"
      },
      "ResultPath": "$.outputs.TrainingJob",
      "Next": "deploy-model"
    },
    "deploy-model": {
      "Type": "Task",
      "Parameters": {
        "Model": {
          "ModelName.$": "$.inputs.Model.ModelName",
          "Tags.$": "$.inputs.Tags",
          "ExecutionRoleArn.$": "$.inputs.Model.ExecutionRoleArn",
          "PrimaryContainer": {
            "ModelDataUrl.$": "$.outputs.TrainingJob.ModelArtifacts.S3ModelArtifacts",
            "Environment.$": "$.inputs.Model.Environment",
            "Image.$": "$.inputs.Model.Image"
          }
        },
        "EndpointConfig": {
          "EndpointConfigName.$": "$.inputs.EndpointConfig.EndpointConfigName",
          "Tags.$": "$.inputs.Tags",
          "InitialInstanceCount.$": "$.inputs.EndpointConfig.InitialInstanceCount",
          "InstanceType.$": "$.inputs.EndpointConfig.InstanceType"
        },
        "Endpoint": {
          "EndpointName.$": "$.inputs.Endpoint.EndpointName",
          "Tags.$": "$.inputs.Tags"
        }
      },
      "ResultPath": "$.outputs.Deployment",
      "Next": "describe-endpoint"
    },
    "describe-endpoint": {
      "Type": "Task",
      "Parameters": {
        "EndpointName.$": "$.outputs.Deployment.Endpoint.EndpointName"
      },
      "ResultPath": "$.Endpoint",
      "Next": "check-endpoint-status"
    },
    "check-endpoint-status": {
      "Type": "Choice",
      "Choices": [
        {
          "Variable": "$.Endpoint.EndpointStatus",
          "StringEquals": "InService",
          "Next": "endpoint-deployed"
        },
        {
          "Or": [
            {
              "Variable": "$.Endpoint.EndpointStatus",
              "StringEquals": "Creating"
            },
            {
              "Variable": "$.Endpoint.EndpointStatus",
              "StringEquals": "Updating"
            }
          ],
          "Next": "wait-check"
        }
      ],
      "Default": "fail"
    },
    "wait-check": {
      "Type": "Wait",
      "Seconds": 60,
      "Next": "describe-endpoint"
    },
    "endpoint-deployed": {
      "Type": "Succeed"
    },
    "fail": {
      "Type": "Fail"
    }
  }
}

это некоторый аналог файла pom.xml, используемого maven для сборки проекта. В конфигурации эксплуатируемой системы ни то ни другое не имеет какого либо отношения. Путаете кислое с пресным.

это некоторый аналог файла pom.xml, используемого maven для сборки проекта.

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


Так это код или конфигурация?

И что, ваша работа и заключается в постоянном и ежедневном изменении этого файла?

Не ежедневном, а тогда, когда меняется соответствующий процесс. Сейчас вот AWS выкатили multi-model hosting — будем править соответствующим образом.


Но вы так и не ответили на вопрос: это код или конфигурация?

не вижу ответа на мой вопрос. Вопрос напомнить?

Напомните.

не проблема
И что, ваша работа и заключается в постоянном и ежедневном изменении этого файла?

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


Ваша очередь: это код или конфигурация?

напишите статью

Ээээ… нет.


Если у вас нет ответа на этот вопрос, мне придется считать, что ваше разделение между кодом и конфигурацией — произвольно (проще говоря, "как мне хочется"), а, следовательно, никакой формальной логики за вашими построениями "конфигурацию надо делать вот так, а не так как код" — просто нет.

Ваше решение осуждать бессмысленно, оно здесь не опубликовано. Опубликуйте, по обсуждаем.

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

… потому что это вы утверждаете, что изменение конфигурации не является изменением ПО. Вот мне и интересно: изменение этого файла — это изменение ПО, или нет?

статью в студию

А смысл, мы тут-то пока с вопросами не разобрались. Статья только увеличит их число.

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


/**
     * Определение поля для хранения экземпляра адаптера
     */
    private DemoAdapter info;

Это про инициализированная переменная или нет?

Понятия не имею, я не настолько хорошо знаком с терминологией Java.

Мне продублировать ваш ответ на ваш вопрос?

Откуда ж я знаю, подходит этот ответ к вашей ситуации, или нет?

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

Ага, то есть вы говорите, что вы понятия не имеете, является мой пример кодом или конфигурацией, и вы не настолько знакомы с терминологией Java. Окей, так и запишем (это хорошо сочетается с тем, как вы сначала уверенно отписались, что "это некоторый аналог файла pom.xml").


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

Очень не хватает тут смайликов.
Статью в студию.

Повторюсь, смысла в статье нет, мы с простыми вопросами разобраться не можем.

Вы задаете вопрос, образно, что в черном ящике.


Мое видение описано в статье, где ваше?

Вы задаете вопрос, образно, что в черном ящике.

Ну так если вам не хватает информации для ответа на вопрос — вы спросите, я отвечу.


Мое видение описано в статье, где ваше?

В этой цепочке комментариев.


И, кстати, ваше видение того, что считать кодом, а что — конфигурацией, и, что важнее, почему, в статье не описано.

Уже десть раз попросил, статью в студию

"статья в студию" — это не вопрос. Я же не понимаю, чего вам не хватает для ответа.

Хорош, дискуссия уже давно потеряла какой либо конструктивный характер.

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


Ура, что и требовалось доказать.

в статье все расписано, читайте и найдете ответы на ваши вопросы.

Нет, не расписано. Там нет ответа на вопрос, почему изменение конфигурации не является изменением ПО.


(если есть, вы легко можете его процитировать)

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


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


Поэтому программный код должен быть отделен от конфигурации приложения. Если программный код смешан с конфигурацией он теряет переносимость.

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

То есть как это? Я бы понял "может быть не привязан", но часто привязан же.


среде выполнения

То есть любой код, который ожидает конкретную БД, автоматически перестают быть программным кодом?


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

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


Конфигурация не переносима из среды в среду.

Это тоже не всегда так. Иногда вполне себе переносима (например, если мы говорим о конфигурации модулей приложения).


Это, собственно, на примере доступа к БД видно. Вот есть приложение, оно умеет работать с двумя СУБД — MySQL и Oracle. Во-первых, оно не переносимо в среду выполнения, где стоит MS SQL. Во-вторых, конфигурация, которая говорит "для MySQL использовать этот адаптер, а для Oracle — вон тот", прекрасно переносима между всеми средами. И поэтому ваш формальный критерий между тем, что является кодом, а что конфигурацией, здесь работает плохо.


Но, что важнее, это не все отвечает на вопрос, почему изменение конфигурации не является изменением ПО.

Я описал в общем виде.


СУБД в "коробке" программный код? Да. Привязан к предметной области? Нет.


Установили, сконфигурировали, создали таблицы предметной области — создали конфигурацию в среде выполнения. Если это все (весь сервер с установленной СУБД и БД) выдернуть и поставить, условно, из Газпрома Роскосмосу. Будет это работать? Нет. Сервер конечно включиться и СУБД запуститься. Но даже подключиться к нему будет нельзя, как минимум надо сетевой интерфейс переконфигурировать.


Но если сервер и СУБД переконфигурировать, базу снести и создать другую — создать новую конфигурацию, то будет.

Я описал в общем виде.

Ну вот как раз в общем виде это и не верно. В частных случаях, иногда — да.


СУБД в "коробке" программный код? Да. Привязан к предметной области? Нет.

На самом деле, привязан, просто ее предметная область — управление БД. Но даже если не вдаваться в эти тонкости, разработанная на заказ система управлением предприятия привязана к предметной области? Да. Программный код?


Установили, сконфигурировали, создали таблицы предметной области — создали конфигурацию в среде выполнения.

А теперь посмотрим на это с точки зрения приложения, которое с этой СУБД взаимодействует. Ему нужны таблицы, и именно такие. Для него код, создающий эти таблицы — конфигурация или код?


Но если сервер и СУБД переконфигурировать, базу снести и создать другую — создать новую конфигурацию, то будет.

В чем, в таком случае, отличие между конфигурацией и данными?

СУБД само по себе имеет какую то ценность? Нет и управлять ей нечем, если БД предметной области не будет.


Первоначально, большинство программ разрабатывается на заказ. Затем результат и требования от разных заказчиков анализируется и предметная область отделяется от программного кода. Результат предлагается другим заказчикам. Так появились ОС (Билл Гейтс первую свою ОС по заказу IBM сделал), СУБД, брокеры сообщений и много чего другого.

СУБД само по себе имеет какую то ценность?

Конечно.


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

Прекрасно. В этом случае привязаны ли они к предметной области?


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

Совершенно не обязательно.


(У меня создается ощущение, что все направление domain-driven design прошло мимо вас.)


Но предположим. Чем в этом случае становится отделенная от программного кода "предметная область"?

Ну не хватает мне смайликов ...


Я высказал свою точку зрения, ваши реплики к ней это уже частности.

Ваша точка зрения — она и выше была высказана. От того, что вы ее высказали, она более аргументированной не становится, к сожалению.

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

Дело как раз в том, что вопрос про разделение кода и конфигурации имеет прямое отношение к вашей статье. Если из нее убрать конфигурацию — что останется-то?

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

Останется код, которому можно "подать" при запуске совершенно другую конфигурацию

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


(Позднее связывание, плагинные архитектуры — имя им легион.)


Вы, однако, утверждаете, что получение "другой информационной системы" путем подачи на вход загрузчика конфигурации менее рисковано, чем получение "другой информационной системы" путем подачи на вход загрузчика кода.


Почему?

Я что то пропустил? Мы уже ведем речь о загрузчике кода?

Мы ведем речь о вашем фреймворке. Который, если верить вашему описанию:


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

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


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

Вам нужно почитать статьи о загрузчиках Java.


Динамическое связывание классов во время выполнения — да на этом построена вся идеология среды выполнения JVM.

Вам нужно почитать статьи о загрузчиках Java.

Зачем бы? Я не делал о них никаких утверждений.


Динамическое связывание классов во время выполнения — да на этом построена вся идеология среды выполнения Java.

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


Собственно, в каком-то широком смысле так работает любая среда выполнения. И… что?

Подали эту конфигурацию и получили SOAP-сервис


Подали эту и уже REST-сервис имеем

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


А теперь объясните, почему вы считаете, что ваша конфигурация приносит меньше риска, нежели:


app.ExposeSoap()

и


app.ExposeRest()

О каких рисках идет речь?
И что за код тут опубликован?


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

О каких рисках идет речь?

О тех, о которых вы говорили выше: "Риск внести ошибку или "сломать" ИС минимальный."


И что за код тут опубликован?

Альтернативный вашему вариант "сказать" системе, что мы хотим выставлять ее сервисы как REST или как SOAP.


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

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

При готовой конфигурации, риск отсутствует.


Я опять что то пропустил? И мы уже перешли на обсуждение альтернатив публикаций SOAP и REST сервисов? И какое отношение ваши фрагменты кода имеют к распределенным средам?

При готовой конфигурации, риск отсутствует.

Ну так и при готовом коде риск тоже отсутствует.


И мы уже перешли на обсуждение альтернатив публикаций SOAP и REST сервисов?

Это был ваш пример, вообще-то.


И какое отношение ваши фрагменты кода имеют к распределенным средам?

Самое что ни на есть прямое. Один из способов конфигурации микросервисов.

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


У меня хоть есть весь исходный успешно выполняемый код на GitHub. У Вас вообще ни чего нет. Обрывки непонятно чего, непонятно откуда. Я же верю Вам на слово.

В этих то примерах что править? Тут нет ни одного "переменного" параметра.

Вот была "конфигурация" для REST. Мы теперь хотим заменить на SOAP. Что нужно править в файле конфигурации? Желательно вот прямо в виде инструкции: такой-то текст заменить на такой-то.


(это, повторюсь, ваш пример)

Кстати, в конфигурации нет кода, публикующего сервисы. Более того, и в примерах кода вы не найдете строк публикации сервисов. Это делается внутри используемых сторонних библиотек. То есть сравнивать ваш код и конфигурационные файлы просто не корректно.


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


А что если я усложню задачу! Условный заказчик очень хочет RMI протокол использовать, ну или его "брата" CORBA. И в придачу на почтовые запросы отвечать.


Подробную пошаговую инструкцию опубликуете вашего примера.

Кстати, в конфигурации нет кода, публикующего сервисы.

А откуда же берутся сервисы?


То есть сравнивать ваш код и конфигурационные файлы просто не корректно.

Да нет, корректно. Мой код ведь тоже не публикует сервисы сам, за это отвечают используемые библиотеки.


Это разные конфигурации, править ни чего не нужно.

Так как же перейти из состояния REST в состояние SOAP? Или вы просто имели в виду, что это два вообще разных приложения?


Подробную пошаговую инструкцию опубликуете вашего примера.

  1. разработать адаптер для протокола X
  2. добавить адаптер в стартап: app.ExposeX
  1. Изменить у REST-класса аннотации
  2. Добавить библиотеки реализующие спецификацию JAX-WS

… это все в конфигурации делается? Можете все-таки показать, как изменяется конфигурация, когда вы решаете перейти с предоставления REST на предоставление SOAP для одного и того же сервиса?

Для REST-сервиса меняется код класса, конфигурация не затрагивается.


Пример SOAP сервиса сделан на более ранних реализациях спецификации SOAP (API). Под более свежей спецификацией JAX-WS, думаю потребовалось бы, тоже пометь только аннотации класса.


По сути — аннотация, встроенная в код конфигурация. Что мне очень не нравиться. Из-за этого приходиться править исходный код, а не конфигурационный файл чтобы переключиться на другой протокол.

То есть получается, что нельзя просто взять и поменять REST-сервис на SOAP в конфигурации, надо трогать код?

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

Надо трогать зашитую в код конфигурацию.

Ну то есть вашего решения недостаточно?


Что же означал комментарий выше:


Подали эту конфигурацию и получили SOAP-сервис
Подали эту и уже REST-сервис имеем

… просто два разных приложения? Или что-то другое?

Ну то есть вашего решения недостаточно?
Что же означал комментарий выше:

Еще раз — эта фраза относится к внешнему ПО по отношению к решению, описанному в статье !!!


В комментарии выше относится к этому же внешнему ПО. В этом внешнем ПО можно использовать аннотации Java, которые по своей сути являются встроенной в код конфигурацией. Этот подход (встроенной в код конфигурации) я отвергаю.


… просто два разных приложения? Или что-то другое?

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


  • GUI приложение
  • WEB приложение
  • Кластерное приложение
  • распределенное приложение
  • отказоустойчивые приложения
  • приложения непрерывной доспности
  • фоновый процесс операционной системы
  • SOAP, REST и прочие приложения
  • и т.д. и т.п. (все определяется вашей фантазией, вашими требованиями и вашими желаниями)
Еще раз — эта фраза относится к внешнему ПО по отношению к решению, описанному в статье !!!

Внешнему. Значит, ваше решение не позволяет выставить произвольный компонент как REST или SOAP, как я изначально подумал по вашему комментарию.


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

Вы же понимаете, что это как раз наиболее тривиальная часть? В широком смысле слова, любая платформа разработки позволяет создавать "любое приложение...". В более узком понимании, вы можете подавать на вход dotnet run -p разные каталоги, и будут запускаться разные приложения. invoke будет запускать разный код в зависимости от того, какие tasks.py и invoke.yml лежат рядом. Веб-сервера будут поднимать разные приложения в зависимости от того, что им подано как home directory. Это повсеместно. Это тривиально.

Опять вы путаете "кислое с пресным". Не можете Вы раскладывать все "по полочкам". Валите все "в кучу" и потом не понимаете, что с этой "кучей" делать. Еще не хватает вашего заявления для полной картины, что рассмотренное в статье решение все же не позволяет лететь на Марс.

Опять вы путаете "кислое с пресным"

Я? Нет. Я просто пытаюсь следовать за логикой ваших утверждений.


Валите все "в кучу"

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

Отделите "кислое" от "пресного" и логика будет у вас перед глазами.

Повторюсь, у меня нет проблем с логикой. Это вы меня обвиняете в том, что я что-то с чем-то путаю.

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

Какой пример вы привели, такой я и обсуждаю.

В моем примере нет упоминаний о REST и SOAP сервисах. Мои ссылки на эти сервисы были опубликованы в ответ на ваши вопросы. Почему то упорно хотели сравнивать описанное в статье решение с этими сервисами.

Нет.


В моем вопросе нет ничего про REST или SOAP, вы совершенно самостоятельно решили привести их в пример.

У меня хоть есть весь исходный успешно выполняемый код на GitHub.

Хм. Вот в этом репозитории?

Да

Там есть строчка, которая меня смущает:


Для успешного выполнения проекта требуется наличие следующих библиотек в ./WebContent/WEB-INF/lib:

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

Все библиотеки в открытом доступе, кроме библиотек avalanche*.jar.
Интересует?

Неа. Просто проверяю фразу "есть весь исходный успешно выполняемый код на GitHub".


Нету.

В публиковать библиотеки в репозиторий дурной тон

Ну да, обычно исходники публикуют.


(впрочем, когда библиотеки — это зависимости, их тоже включают, не в сам репозиторий, так в releases)


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

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

Именно, что в равном, а не "У меня хоть есть весь исходный успешно выполняемый код на GitHub. ".

Демонстрация проекта


Ролик готовился для выступления на конференции, звука нет. Комментировался во время доклада.

НЛО прилетело и опубликовало эту надпись здесь

Пример вызовов по различным протоколам с использованием решения описанном в статье


Локальный вызов


info.getInfo();


Вызов по RMI


info.getInfo();


Вызов по HTTP


info.getInfo();


и т.д. и т.п.


Попробуйте найти отличие.

Гм. Это выглядит как тривиальный полиморфизм.


Вы, наверное, хотите сказать, что можно переключить вызов с локального на HTTP, изменив только конфигурацию, не трогая ни строчки кода вызывающего приложения, да?


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

Да. Пример же рассмотрен (в общем виде) в статье.


Но можно и продублировать


Начальная конфигурация вызова локальной функции


<?xml version="1.0" encoding="UTF-8"?>
<avalanche name="Demo Application">

    <function class="ru.funsys.demo.avalanche.DemoFunction" name="info-function" description="Сведения об узле системы" />

    <application class="ru.funsys.demo.avalanche.DemoApplication" name="DemoApp" >
        <adapter class="ru.funsys.demo.avalanche.DemoAdapter" name="info" uri="info-function" />
    </application>

</avalanche>

Вызов по HTTP удаленного объекта — на удаленном узле должен "присутствовать" коннектор c именем http-connector, в котором опубликована функция info. Локальная функция не нужна.


<?xml version="1.0" encoding="UTF-8"?>
<avalanche name="Demo Application">

        <interface name="http-interface" uri="http://localhost:8080/demo/connector/http-connector" />

      <application class="ru.funsys.demo.avalanche.DemoApplication" name="DemoApp" >
        <adapter class="ru.funsys.demo.avalanche.DemoAdapter" name="info" uri="http-interface/info" />
    </application>

</avalanche>

Ну то есть поменять надо две строчки:


  1. добавить interface (не знаю, обязательно ли удалять function)
  2. поменять uri в adapter (что занятно, часть этого uri должна совпадать с name в interface, но только часть)

А теперь давайте сравним с неким (полумифическим) фреймворком.


Настройка для локального вызова:


builder
.Register<DemoFunction>()
.As<Function>()

Настройка для удаленного вызова:


builder
.RegisterHttpAdapter("http://localhost:8080/demo/connector/http-connector")
.As<Function>()

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


  1. проще
  2. имеет меньший риск внести ошибку или сломать ИС?

Приведите код "работоспособной" функции и код который ее использует хотя бы.


Ваше решение (на вскидку):


  • Конфигурация зашита в код — плохое решение.
  • HttpAdapter регистрируется как функция, который таковым не является — это больше протокол обмена
  • Данного кода не достаточно для успешного вызова удаленного класса
  • Для отказоустойчивости нужно наворачивать еще код
Приведите код "работоспособной" функции и код который ее использует хотя бы.

"Функция":


public string DemoFunction(int someInput)
{
  //делайте что угодно
  return someOutput;
}

Точка вызова:


[Inject]
Function _function;
//...
Show(_function(42));

Обычный DIP, проще говоря, ничего нового или необычного.


Конфигурация зашита в код — плохое решение.

Ну как так? Я специально написал комментарий, в котором два решения рядом, чтобы попробовать понять, почему это плохое решение, а вы опять пишете "плохое решение", необъясняя. Почему это плохое решение?


HttpAdapter регистрируется как функция, который таковым не является — это больше протокол обмена

Пожалуйста, специально для вас:


builder
.RegisterHttpAdapter("http://localhost:8080/demo/connector/http-connector")
.For<Function>()

Данного кода не достаточно для успешного вызова удаленного класса

Ровной в той же мере, в которой вашей конфигурации недостаточно для успешного вызова удаленного класса. Где-то дальше лежит фреймворк, да.


Для отказоустойчивости нужно наворачивать еще код

Да нет:


builder
.RoundRobin(
  Http("http://node1:8080/demo/connector/http-connector"),
  Http("http://node2:8080/demo/connector/http-connector"),
  Http("http://node3:8080/demo/connector/http-connector")
)
.For<Function>()

(Это даже не вдаваясь в те детали, что, по моему скромному мнению, за отказоустойчивость должен отвечать поставщик, т.е. http://service:8080/demo/connector/http-connector, где прекрасно можно навернуть любой балансировщик миллионом способов, а не получатель. Инкапсуляция, вот это все.)

Так где связь то между функций DemoFunction и HttpAdapter

А где она в вашей конфигурации?


<?xml version="1.0" encoding="UTF-8"?>
<avalanche name="Demo Application">

        <interface name="http-interface" uri="http://localhost:8080/demo/connector/http-connector" />

      <application class="ru.funsys.demo.avalanche.DemoApplication" name="DemoApp" >
        <adapter class="ru.funsys.demo.avalanche.DemoAdapter" name="info" uri="http-interface/info" />
    </application>

</avalanche>

Перед вашими глазами

Там нет ни одного упоминания DemoFunction. Если бы было, я бы не спрашивал.

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


Описано это и в статье


<?xml version="1.0" encoding="UTF-8"?>
<avalanche name="Demo Application">

    <function class="ru.funsys.demo.avalanche.DemoFunction" name="info-function" description="Сведения об узле системы" />

    <connector class="HTTPConnector" name="http-connector" >
        <publish name="info" function="info-function" />
    </connector>

</avalanche>

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

так функция вызывается с другого узла, ее нет на вызывающем узле. Вызывающий узел не знает какой класс он вызывает. Он знает узел к которому он должен обратиться, имя экземпляра и метод который вызывается. Остальное его "не интересует". Аналогично вызывается и локальный объект.

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

В предложенном решении — это не имеет значения (поставщик или потребитель). Предложенное решение позволяет реализовывать распределенные или кластерные приложения, т.е создавать приложение, работающие на множестве узлов — это просто одно приложение.

В предложенном решении — это не имеет значения (поставщик или потребитель).

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

Это конфигурации двух разных узлов одного приложения. Приложение одно, код на узлах одинаковый.

Я стараюсь ограничить свои вопросы одной конфигурацией, просто чтобы упростить обсуждение. Вы настаиваете, чтобы мы обсуждали обе?

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

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

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

предложенное решение может, пусть (даже соглашусь, что "чуть"), "чуть больше" конкурентных технологий

Это не отвечает на вопрос, почему ваше изменение — не фреймворк за ним! — проще и имеет меньшие риски, чем мое.


"Больше может" — не значит "более надежное".

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

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

так нет проблем с конфигами

Вы утверждали, что решение с конфигами проще и имеет меньшие риски. Это не то же самое, что "нет проблем с конфигами". Так все-таки "проще и имеет меньшие риски", или "нет проблем с конфигами"?

продолжаю утверждать. Только не нужно начинать дискуссию по этому вопросу заново. Здесь "все ходы записаны".

Только не нужно начинать дискуссию по этому вопросу заново.

"Начинать заново" — это если бы она хоть раз завершилась. А вы пока ни разу не смогли ответить на вопрос "почему".

а балансировщик кто будет от сбоев "балансировать"?


А в распределенных одноранговых системах сколько вам балансировщиков понадобиться?

а балансировщик кто будет от сбоев "балансировать"?

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


А в распределенных одноранговых системах сколько вам балансировщиков понадобиться?

Столько, сколько нужно для достижения необходимой надежности.

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


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

Чем больше добавите, тем меньше надежность

Скажем так, в общем случае это неверно. Иначе бы вообще системы с балансировщиками нагрузок работали хуже, чем без них.


не управляете всеми элементами системы

Во-первых, почему? Если я за всю систему отвечаю, я и управляю.
Во-вторых, почему это плохо? Если удаленный сервис — не моя ответственность, то почему я должен им управлять?


В предложенном решении

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


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

чем балансировать балансировщики — это тоже точка отказа


все узлы ваши — предложенное решение предназначено для создания распределенных или кластерных приложений

все узлы ваши — предложенное решение предназначено для создания распределенных или кластерных приложений

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


Но, повторюсь, это не важно.

Верно, не обязательно, но контролировать "чужие" узлы все равно обязаны

Нет, не обязан.


Но, повторюсь, это не важно.

Значит ваше приложение будет проседать в производительность когда "чужие узлы не доступны"

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

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

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


Поскольку он чужой, вы все равно ничего не можете с этим сделать.

С "чужим" нельзя, со своим можно. Зная что чужой узел не доступен, можно вообще не обращаться к нему, пока он снова не станет работоспособным.

С "чужим" нельзя, со своим можно.

Вы не можете (в рамках разумных расходов) построить систему, состоящую только из "своих" узлов.


Зная что чужой узел не доступен, можно вообще не обращаться к нему, пока он снова не станет работоспособным.

Для этого вам нужен достоверный критерий "доступности".


Самый простой пример: предположим, ваш "удаленный узел" — это HTTP-эндпойнт, с одним методом POST, и временем ответа меньше 0.5с для 95-го персентиля. Вы, конечно, можете просто поставить circuit breaker на 0.5с, и обрубать все, что дольше, но что вы будете делать с тем одним запросом из 20, который будет считаться вами неуспешным?

Кто мне мешает? Могу и построил, на своих технологиях.

Могу и построил, на своих технологиях.

У вас свои сетевые каналы, свои хранилища данных, своя электроэнергия, свои микросхемы?..

Не у меня, там где работаю мои системы да — свои каналы, свои хранилища, свои ЦОДы, своя электроэнергия на случай отсутствия ее в "розетке". Микросхемы вот чужие.

Свои каналы — сами произвели кабели? Свои хранилища — сами произвели диски или что у вас там используется? Генераторы тоже сами произвели?


Микросхемы вот чужие.

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

это уже не имеет значения.

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

моя не будет, при вашем подходе — ваша будет

моя не будет

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

серьезно, утверждаю

Видимо, у вас очень свое понимание термина "проседать в производительности", никак не совпадающее с моим. Как следствие, не вижу смысла обсуждать этот критерий к системе.

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

Это уже не имеет значения


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

Если под "ошибка не сказывалась" вы подразумеваете "мы ее доставим пользователю и умоем руки", тогда да, это достижимо.

Нет, Вы опять не поняли.


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

"Провесить" сообщение об ошибке мало, нужно делать это без просадки производительности, а это невозможно делать без контроля состояния узлов системы

Возможно. Паттерн circuit breaker.

Пора закругляться. Благодарю за дискуссию.

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

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

Почему ко мне? К тому, кто отвечает за поддержку и развертывание его системы.


ваше решение будет просто ужас для заказчика

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

такого решения ни где нет

Это, очевидно, неправда. Есть как минимум в Serilog.

Не знаком с этим продуктом, может вы и правы. Я подобных решений не видел.

НЛО прилетело и опубликовало эту надпись здесь

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

Следовательно a thread-safe implementation is not needed и, как следует из рекомендаций it is recommended to use HashMap in place of Hashtable.
НЛО прилетело и опубликовало эту надпись здесь

Это всего лишь пример. В однопоточном варианте класс отлично работает. И даже в документации JDK 13 нет упоминания, что этот класс @Deprecated

НЛО прилетело и опубликовало эту надпись здесь

Это не существенный вопрос. Да использовать при многопоточном доступе к экземпляру этого объекту — нельзя. Если посмотреть исходный код экого класса, то ничего особенного в нем нет.

Миллениалы придумали remote ejb?
Вообще «стирающей различия между вызовами локального и удаленного кода», не то, чтобы прям однозначно преимущество

Зато какие перспективы оно открывает вашему приложению, если не Вам лично, то вашему заказчику уж точно. Запустил он ваше приложение и радуется. Но время идет, интенсивность использования приложения растет, объемы хранения данных тоже увеличиваются. И в один "прекрасный" момент приложение начинает упираться в производительность аппаратной платформы. Что делать заказчику? Покупать новое более мощное железо? А можно взять и растащить приложение на множество узлов, поменяв его конфигурацию. И снова у заказчика наступит "век счастья".


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


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

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

OpenMosix, в котором эта концепция реализовывалась на уровне ядра — задохлился много лет назад почему-то.
GridGain, который вообще обещал zero deployment уровня «воткни питание и сеть, остальное воспоследует автомагически», ичсх тоже для джава-приложений — тоже немного не смог в автомагию без некоторого количества ручной работы.

Видимо масштабируемость не так линейна как хочется верить.

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

А можно взять и растащить приложение на множество узлов, поменяв его конфигурацию.

Неа, нельзя. Если в приложении заранее не заложена такая возможность — и нет, не с помощью вашего транспорта, а на уровне архитектуры, — то не получится такого счастья.

Неа, нельзя. Если в приложении заранее не заложена такая возможность — и нет, не с помощью вашего транспорта, а на уровне архитектуры, — то не получится такого счастья.

Рассмотренное решение реализует модель MVFA (Model — View — Function — Application), которая и предоставляет несколько иной взгляд на архитектуру приложения
Про архитектуру коснусь чуть позднее.

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

Ну вот вы коснулись:


  • Любые объекты (типы), декларируемые в адаптерах (входные и возвращаемые параметры), [...] должны реализовывать интерфейс…
  • Не все объекты могут быть переданы по сети.

Из этого явно следует, что нельзя просто "взять и растащить приложение", если оно внутри себя не использует ваши (ненужные для локального исполнения) ограничения.

Любая технология имеет какие либо ограничения и, несмотря на их наличие, они же используются. Учитывая эти ограничения, можно построить систему так, что любые объекты системы можно растащить на любое число узлов. ResultSet, например, можно передать на любой узел системы, хотя он тоже привязан узлу создания экземпляра класса. Для этого достаточно создать собственный класс "обертку", реализующий этот интерфейс.

Учитывая эти ограничения, можно построить систему так

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

Предложенное решение значительно упрощает этот процесс, предоставляя для использования готовую функциональность.

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

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

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

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

А вот здесь вам поможет еще одно замечательное свойство предложенного решения — режим разноверсионности

Нет, не поможет.


(Я говорю о консистентности данных, если что)


Это не критично для системы.

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

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


Правда, правда. Обновление узлов системы не критично.

Поможет, консистентность данных здесь вообще ни причем.

Что значит — не при чем? Система-потребитель ожидает, что данные будут консистентны.


Два узла системы при разнесении на них разных ее "частей" по "определению" имеют разное состояние.

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


Правда, правда. Обновление узлов системы не критично.

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


Теперь вы поменяли эту логику, и стали накатывать ее на разные узлы. В некий момент времени на узле А старый алгоритм расчета, на узле Б — новый. Система потребитель, ничего об этом не зная, получает разный расчет скидок для двух разных строк в одном заказе. Пользователь в шоке.

НЛО прилетело и опубликовало эту надпись здесь

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

НЛО прилетело и опубликовало эту надпись здесь
А где за этими RMI / EJB / web.xml сам фреймворк? Он сам хоть что-то делает полезное или только рыбу в газету заворачивает?

Фреймворк предоставляет:


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

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

Публикации