Как стать автором
Обновить
30
0
Владимир Плизга @Toparvion

Инженер-программист

Отправить сообщение

Вот ссылка на этот пост: https://t.me/llm_under_hood/230

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

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

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

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

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

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

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

мама дорогая

Полагаю, здесь смутило сочетание слов "стационарные объекты" и "сообщают географическое положение". Согласен, без пояснения формулировка дурацкая. Имеются в виду суда, вставшие в порт на обслуживание/ремонт/разгрузку/... и остающиеся неподвижными 95+% времени пребывания в порту. Несмотря на это, они включаются в число отслеживаемых объектов.

через N условных лет библиотеки намного лучше будут приспособлены к наличию реактивности в проекте?

С одной стороны, можно с уверенностью, что библиотеки совершенно точно будут (и уже давно начали) поддерживать реактивный подход: тот же Spring в каком-то смысле задал этот тренд, адаптировав свои фреймворки WebMVC (в виде WebFlux), Security и частично Integration; другие тоже на подхвате, например, feign-reactive и различные поставщики драйверов к БД. С другой стороны, их усилия, как правило, не нацелены именно на "скрещивание" сервлетного (а в более общем случае - императивного) подхода с реактивным; вместо этого они предлагаю самостоятельную реактивную альтернативу своим же собственным разработкам. Поэтому именно ждать N условных лет не стоит.

Однако это не значит, что ответ на вопрос:

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

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

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

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

Если надо тестировать поведение одного конкретного бина зачем вообще поднимать контейнер? В чём проблема создавать его в тесте вручную?

Дело как раз в том, что далеко не всегда задача сводится к тестированию одного бина; нередко возникает потребность модификации сквозных поведений или функционала, не обёрнутого в бины. Больше того, применение Side Effect Injection отнюдь не сводится к одному лишь тестированию. Слово "тестовый" в названии доклада означает, в первую очередь, принадлежность к тестовому (не production) окружению. Например, когда нужно временно поменять что-то в библиотечном коде или на определенном этапе отключить проверки безопасности.


Именно в src/test/… и хранить, если мы говорим про тесты

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


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

Да, полностью, и да, можно (хоть и не обязательно) выделять в отдельный артефакт, так как SEI — это не разновидность тестов, а альтернативный подход к troubleshooting'у и воспроизведению сложных тестовых кейсов. Его можно использовать как в составе интеграционных тестов, так и самостоятельно.

AlexeyOs, привет!
1) Иногда кажется)) Но от идеи не отказываемся, потому что:


  • Работа с бинами — это специфика IoC, которого может не быть в приложении вовсе (и это не всегда значит, что приложение плохое, а разработчики — бракоделы)
  • Даже если всё-таки закладываться на наличие IoC-контейнера, то какого? Только лишь Spring? А может, Guice? А вдруг там CDI? Поддерживать каждый — такое себе решение. Гораздо целесообразнее не наступать себе на горло и не зависеть от этой переменной составляющей.
  • И потом, а где тогда хранить mock-бины? В src/test/java не пойдёт, потому что модифицированное поведение нам нужно не в тестах, а в обычном режиме работы приложения. Класть к основным исходникам, конечно, можно, но это возвращает нас к обычному подходу "If'ы+настройки", а значит, эти тестовые поделки снова уедут на production и защита от их случайного срабатывания снова ляжет на совесть людей, а не на формальный механизм выкашивания лишнего. Впрочем, буду честен, пару раз, в особо накуренных нетривиальных случаях мы сами так делали, но только подключение тестового бина обеспечивали не настройкой, а дроплетом, т.е. в отсутствие модицификации тестовый бин вообще никак не попадал в IoC-контейнер и даже не загружался как класс в JVM. Это пример комбинации подходов, о которой я говорил в конце доклада. Другой пример см. на этих слайдах другой версии доклада.

2) Для AspectJ и Byteman специальных тестов по этой части не делал, разве что чисто визуально кажется, что AspectJ стартует чуть медленнее. Что касается jMint, то у нас в тестовом окружении большинство приложений по умолчанию стартуют одновременно и с отладчиком (в режиме suspend=n, разумеется), и с Java-агентом jMint, но на времени старта это не сказывается. С точки зрения подкапотной механики, отладчик не привносит здесь ничего нового, поэтому и не вызывает задержек. Единственная особенность — в порядке подключения агентов (ведь отладчик — тоже агент, только "нативный"). Если в команде запуска JVM указать агентов не в том порядке, то отладчик не сможет ходить по исполняемому коду jMint (впрочем, вряд ли этого кого-то волнует).

Согласен, всерьез полагаться на "закрытость" формата архива не стоит. Равно как и не стоит (по крайней мере, пока) ожидать от него встроенных средств защиты от модификаций. Поэтому, повторюсь, я считаю, что защищать архив нужно средствами другого уровня, и в фиксированной адресации внутри него действительно нет ничего плохого.
Что касается приведенной ссылки, то мы увидели одно и то же: "динамическая" адресация оставляет заметный негативный отпечаток на производительности CDS в целом, поэтому JVM будет избегать ее по возможности. Сравнение с вариантом без CDS здесь нерелевантно, так как этот вариант сейчас вне нашего фокуса.
Спасибо, что обратили внимание на вопрос безопасности; как обычно, он важен, но не очевиден.

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

Не разбор багов, конечно, но всё же кое-что накопал про JEP-350 Dynamic CDS Archives применительно к Spring Boot: https://m.habr.com/ru/post/472638/

tsypanov, спасибо за статью — интересные кейсы и приятное изложение.
Вот уж правда обширная тема! Особенно про LDAP — хоть в музей относи)
Держите в курсе — с удовольствием почитаю и поделюсь с коллегами.
Спасибо, что поделились!
У меня был схожий опыт с JPA, только нужно было отвязать прикладной код от походов в БД статическими методами Play 1.x, чтобы покрыть код unit-тестами без PowerMockito. Впрочем, тогда машстаб вышел более широким — таки пришлось задеть пару сотен классов. К счастью, правки оказались простыми.

Зависит от проекта. В нашем случае он состоит только из Java-подпроектов, лишь один из которых не является Spring Boot приложением. А всё, что не на Java, мы держим в других репозиториях.

ещё не переехал на СБ2 именно из-за Актуатора

А что конкретно не дает переехать? Интересно узнавать о новых граблях от коллег по цеху.


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


  • Если не заходит, то стоит покопать в сторону того, как регистрируется CustomAttributeSource: точно ли его видят регистрирующие бины (в том числе самописные), и точно ли эти бины сами активны (намекаю на соответствующие классы *AutoConfiguration).
  • Если же выполнение заходит сюда, то надо убедиться, не обёрнуто ли целевое исключение в какое-либо другое (каковых в Spring'е целая иерархия). В случае обёртки (да и не только в нем) следует проверять на instanceof не само исключение, а его корень, например, через Throwables#getRootCause() из Guava.
Спасибо! Рад, что статья Вам понравилась.
Та работа, о которой сказано в заключении, как раз и имеет целью создание некой утилитки, которая сможет принять на вход любой лог, а на выходе выдать готовый NSS-файл для предоставления Wireshark'у. Только это будет не скрипт, а именно программка (исполняемый JAR), так как, во-первых, мне по профессии ближе Java, во-вторых, я хочу научить ее учитывать возможные отклонения в форматах логов (от версии JVM к версии), а также разные режимы логирования (значения опции javax.net.debug). Все это позволит сделать ее пригодной не только нам с Вами, но и, надеюсь, многим другим. Планирую закончить работу над ней в течение ближайших 1-2 недель.

Информация

В рейтинге
Не участвует
Откуда
Новосибирск, Новосибирская обл., Россия
Зарегистрирован
Активность

Специализация

Backend Developer
Lead
Java
Docker
Spring Boot
Kubernetes
RabbitMQ