(java || kotlin) && devOps
369 subscribers
6 photos
1 video
6 files
306 links
Полезное про Java и Kotlin - фреймворки, паттерны, тесты, тонкости JVM. Немного архитектуры. И DevOps, куда без него
Download Telegram
Всем привет!

Редко даю ссылки на другие каналы, но сейчас сделаю исключение.
Папка с каналами коллег из Сбера - https://t.me/addlist/Hjh12dzfjzhmY2Qy
Сразу скажу - Java и в целом бэк-разработку тут не ищите.
А вот если хотите расширить кругозор - аналитика, тестирование, веб-разработка, облака, AI, менеджмент - есть из чего выбрать.
Выбирайте!)
Всем привет!

Вопрос - где применяется подход DDD?
Аналитика, разработка, тестирование. Конечно архитектура АС, с нее все начинается.
Но это еще не все.
Есть такой класс систем как Data Warehouse (DWH) или аналитическое хранилище данных. В это хранилище попадают данные из всех бизнес-сервисов компании для дальнейшего анализа. Т.об. мы разделяем оперативную БД и аналитическую, снимая лишнюю нагрузку с оперативной БД. Особенность Data Warehouse - технологии обработки и хранения данных отличаются от используемых в системах оперативной обработки данных. Hadoop, Greenplum, ClickHouse... А значит нужны специалисты, которые подготовят хранилище под ваши данные и настроят синхронизацию с оперативной БД. Но эти специалисты не знают ваш домен, в отличие от команды. Плюс они часто становятся "бутылочным горлышком". Плюс структура данных постоянно меняется...
Что делать?
Data Warehouse специалисты готовят инфраструктуру, а за подготовку и синхронизацию данных, актуальность их структуры и способ предоставления этих данных потребителям отвечает бизнес команда. Это же ее bounded context. Подход называется Data Mesh. Вот неплохая статья на эту тему https://habr.com/ru/companies/vk/articles/720652/
P.S. На самом деле DevOps в своем идеальном виде о том же - DevOps инженеры готовят инфраструктуру, а за сборку и деплой отвечает команда.

#ddd #data_mesh
Всем привет!

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

Более 10 лет назад. Стартап. Я на данный момент и СТО, и разработчик в одном лице. Есть задача, задача в целом понятна. Декомопзирую на микросервисы и подзадачи, начинаю пилить. Дохожу до XML binding - преобразования XML в объекты и обратно. Да, тогда API в основном были XML. Решил погуглить - что сейчас есть на рынке. Кроме известного многим JAXB нахожу JiXB. Не известный тогда, и тихо умерший сейчас. Читаю описание и нахожу бенчмарк, показывающий что он ... не помню точно, но скажем в 1.5 раза быстрее JAXB. Думаю - о, круто, надо брать. Начинаю прикручивать к Spring приложению. Наталкиваюсь на кучу подводных камней - это не работает, то не работает, документации мало, ошибки не информативные и не гуглятся, т.к. сообщества особо нет. В общем убил неделю на прикручивание к проекту одной библиотеки. В итоге все заработало, конечно. А проект не был доведен до работающего состояния и так и не взлетел - как по бизнесовым причинам, так и по причине неготовности к нужному моменту.

Итоги. До сих пор стыдно за такое проектное решение. Стыдно по следующим причинам:
1) напомню, речь про стартап, т.е. нужно быстро создать работающий прототип, а не исследовать новые технологии
2) преждевременная оптимизация - данных по требуемому RPS и доступному железу на тот момент у меня не было. Нагрузочное тестирование не проводилось. Стал бы JAXB узким местом - далеко не факт
3) использовать в промышленной разработке новые, не доказавшие свою зрелость библиотеки - это риск. Очень важны сообщество (ответы на stackoverflow, а сейчас в AI чате) и работающие без бубна связки, например, Spring+конкретная технология. А риск во-первых должен быть оправдан - см. предыдущий пункт, а во-вторых - должен быть сценарий отката. Если библиотека по факту оказалась сырой - не надо заниматься реверс-инжинирингом, плодить костыли, героически превозмогать трудности. Лучше откатится на какой-то надежный вариант.

#fuckup #xml #java
Всем привет!

Наткнулся сегодня на еще одну книжку про AI. Что опять?)
Для начала у нее интересное название - "Охота на электроовец" https://markoff.science/#book
Но есть еще две причины, по которым я решил про нее написать.
1) книжка научно-популярная - история развития AI и обзор текущего состояния. До сих пор не встречал таких. При этом написана программистом (бывшим программистом судя по текущей должности). Кажется, для вкатывания в тему, если есть пробелы\проблемы в математическом образовании - неплохой вариант.
2) автор - Сергей Марков - из России, что встречается не часто. Более того - автор живет в России на данный момент. Т.е. его можно в теории встретить на какой-либо конференции и позадавать вопросы. Ну и проблем перевода точно не будет)

Скачать можно бесплатно, бумажную версию скоро выпустят тут https://dmkpress.com/catalog/computer/data/978-5-93700-333-1/
Я лично планирую прочитать.
Да, о минусах - иллюстрация на обложке для электронной версии .. ну такое. Ну и 2 тома, 1200 страниц - не всякую дорогу осилит идущий)

P.S. Угадайте, в какой компании работает автор?)

#ai #books
Всем привет!

Давненько не было постов на канале, что поделать - конец квартала, авральный режим on.
Но я вернулся) К делу.

Java всегда славилась своим boiler plate кодом. Ремарка - конечно же не только boiler plate, но сейчас про него и про борьбу с ним. Борьба идет, и в Java 16 (а точнее в Java 14 но в режиме preview) появились records, они же записи.
Делаешь вот такое объявление:
public record Point(int x, int y) {}
и получаешь из коробки конструктор, getter, equals(), hashСode() и toString().
Т.е все то, что раньше приходилось писать руками или использовать Lombok. Ага, Lombok. Т.е. он стал не нужен? Не совсем. Если внимательно глянуть на список того, что под капотом делает record, то можно заметить, что там нет setter-а. Т.е. record - это иммутабельный объект и value object. Две записи с одним и тем же набором полей всегда равны. Это не баг, это фича. Маленькое дополнение - record еще меняет классический getter c getXyz на просто xyz(), но это детали. Еще дополнение - вот тут среди прочих фичей Java 17 достаточно интересно о работе с record https://habr.com/ru/companies/jugru/articles/652821/

Т.е. получается, что record заменяет @Value из Lombok.

Но не заменяет:
1) полноценный @Data - изменяемый класс без boiler plate

2) кейс, когда мы не хотим все сразу getter, toString() ... а хотим только часть этих методов

3) @Builder - тут проще показать, чем объяснять:
Person.builder()
.name("Adam Savage")
.city("San Francisco")
.build();

4) @Log - простое добавление логгера в класс

5) и наконец @SneakyThrows - если вы не любите checked exception

#java #lombok #boiler_plate_free
Небольшое дополнение по Java records. Как известно, Java - это огромное количество библиотек и фреймворков и, следовательно, вопросы совместимости.
Так вот. Spring Boot Web записи поддерживает, как в контроллере, так и в http клиентах. Java сериализация естественно, это же часть спецификации Java. Jackson сериализация. Mapstruct. И Spring Data JPA, там где это возможно, учитывая иммутабельность https://www.baeldung.com/spring-jpa-java-records
Что я забыл? Наверное забыл, но 3 года прошло - поддержку должны были уже запилить)

#java #spring
Всем привет!

Увидел у коллеги аналитика в канале интересное мнение. Разработка - это синоним унижения, т.к. у вас всегда что-то не будет работать.
С мнением не согласен)
Посыл, что что-то всегда не будет работать - абсолютно верный. Причём сломаться может даже сборка проекта, в котором ещё ничего не меняли. Т.е. разработка ещё не началась, а уже что-то сломалось) Обидно)
Только на мой взгляд такая ситуация - это вызов. И в т.ч. и в этом кайф от разработки.

P.S. Но как я писал ранее в посте примере про внедрение проблемной технологии (крепостное слово Jixb): если решение вызова занимает неделю или две, вместо пары дней, и все это время команда ждёт - вы свернули не на ту дорогу. Не всякие вызовы стоит принимать)

#dev
Please open Telegram to view this post
VIEW IN TELEGRAM
Всем привет!

Продолжим про тестовые библиотеки. Достаточно часто возникает задача проверить в тесте структурированные текстовые данные. Я про XML, json и yaml как самые распространённые варианты. XML первым указан по старшинству, а не распространённости) И он пока ещё жив.

Зачем для этого нужно специализированная библиотека:
1) текст может отличаться формированием - пробелами и переносами строк. Иногда это важно при сравнении, но часто нужно проигнорировать
2) могут быть «лишние» тэги/атрибуты - которые не должны участвовать в сравнении
3) может отличаться порядок тэгов
4) может стоят задача проверить только отдельные элементы в дереве, или их количество

Одной библиотеки для всех форматов нет, но есть две - XMLUnit и JsonAssert. Так думал я, пока не начал копать тему глубже. И искать, чем же можно проверить yaml. Оказывается, есть «более лучшая» замена JsonAssert, которая:
1) умеет и в json, и в yaml, причём может сравнивать json и yaml. И также сравнивать с Java обьектом
2) умеет все это делать в стиле Assert/Truth, он же method chaining. А это облегчает как написание условий проверки благодаря auto competition в IDE, так и их чтение. А возможно в некоторых случаях позволит отказаться от BDD фреймворка.
3) прозрачно работает с разными источниками данных - строка и файл
Встречайте - ModelAssert https://github.com/webcompere/model-assert
И более подробно https://www.baeldung.com/json-modelassert
Что интересно - автор сам написал статью на baeldung и ссылается на неё в документации.
Ещё важный момент - подчеркивается совместимость библиотеки со Spring MockMvc и Mockito. Возможно даже ради этой поддержки автор и запилил совместимость с Hamcrest. И последнее - отдельно продумано тестирование json с guid. Во-первых можно игнорировать различия конкретных значений uuid (они могут генерироваться в каждом тесте), во-вторых легко написать проверку формата uuid.

А что же XML - вот хорошая статья по XMLUnit https://www.baeldung.com/xmlunit2
Он может примерно то же самое, но без method chaining. Но зато с валидацией по схеме (xsd). Что кстати неплохо характеризует отличия в подходах к работе с XML и json)

#unittests #rare_test_libs #XML #json #yaml
Всем привет!

Продолжение про тесты, на этот раз интеграционные.
Доминирующий протокол для интеграции сейчас - http(s). REST, GraphQL, разные кастомные реализации. Если мы получаем данные по http - значит где-то есть http client. Он куда-то стучится. Как можно протестировать эту часть интеграционной цепочки?
На первый взгляд, самый простой вариант - развернуть в TestContainers реальный экземпляр сервиса поставщика. Но у нас же микросервисы, а значит он, возможно, вызывает ещё кого-то. И т.д. Даже если не вызывает - ходит в БД.
Поэтому для теста, да и для отладки, нужна заглушка. Кстати, в большинстве случаев это может быть одна и та же заглушка.
Заглушка может быть standalone и встроенная. Я за встроенную, т.к. удобно держать в одном репозитории с кодом и сам код, и все необходимые настройки для его отладки и работы. Кроме стендозависмых конечно.
Что нас нужно от заглушки:
1) возможность старта на произвольном порту и передачи этого порта в код (сервер всегда localhost). Захардкодить порт можно, но тесты запускаются на CI конвейере, в т.ч. на используемом совместно сервере. И вообще не должны зависеть от среды запуска.
2) удобная возможность задавать разные ответы для разных path, например, method chaining
3) учёт параметров в URL
4) возможность задать http код ответа
5) возможность задать http заголовки ответа
6) возможность эмулировать таймаут
Ну и в идеале простая инициализация в тесте, например, с помощью аннотации.

И вот наконец кандидаты.
1) Wiremock. Главные плюсы - большое число возможностей, накопленных за время существования, и возможность работы как во встроенном режиме, так и standalone. Примеры фишек Wiremock - сценарный режим, когда можно задать ответ в зависимости от предыдущего запроса. Встроенный генератор случайных данных в полях ответа. Возможность использовать данные запроса в ответе (templating). Статья как подружить Wiremock с тестами https://www.baeldung.com/spring-webclient-wiremock-integration-testing
2) @RestClientTest - это «магическая» аннотация Spring Boot, автоматически связывающая добавленный в класс теста RestTemplate с сервером заглушки. Т.е. настройку порта делать не нужно. Вот статья по использованию https://www.baeldung.com/restclienttest-in-spring-boot
Если используете Spring и RestTemplate или его наследника RestClient - наверное оптимальный вариант. Для WebClient - асинхронщины и реактивщины - не годится, соответствующий тикет был отклонен командой Spring https://github.com/spring-projects/spring-boot/issues/8404
3) А рекомендует Spring для WebClient использовать MockWebServer. Вот статья https://howtodoinjava.com/java/library/mockwebserver-junit-webclient/
Из интересных фишек я заметил возможность получения информации о последнем запросе, пришедшем на сервер. И простейший сценарный режим, когда можно настроить очередь ответов для ряда последовательных запросов. Настраивать сложнее, чем предыдущие два варианта.

Итого: рекомендую @RestClientTest для синхронного Spring и Wiremock для остального.

#integration_tests #rare_test libs
Всем привет!

Продолжим тему тестирования http взаимодействий. Кроме http клиента приложение может выставлять API. Этот пост про REST API, как наиболее распространённое. В мире победившего Spring endpoint обычно создаётся с помощью Spring @RestController, но в теории может быть и JAX-RS контроллер или что-то другое, даже «голый» сервлет.

Можно рассмотреть 4 случая.

1) модульное тестирование слоя контроллеров Spring приложения. В этом случае все сервисы в контроллере «мокаются», а Spring context загружается в ограниченном объёме, необходимом для эмуляции контроллера. Это кстати крутая фишка Spring - эмуляция контроллера без реального сетевого взаимодействия для модульных тестов. Ключевые слова - MockMvc и @WebMvcTest. Хорошее описание тут: https://sysout.ru/testirovanie-kontrollerov-s-pomoshhyu-mockmvc/, надо смотреть п. 2
Как я уже писал ранее - встроенные assert-ы MockMvc для json можно при желании заменить на ModelAssert, см. мой пост https://t.me/javaKotlinDevOps/343

2) интеграционное тестирование всех слоёв Spring приложения, но без сети. Вообще говоря, что считать интеграционным тестом - отдельная большая тема, но в большинстве статей, что я видел, такие тесты называются интеграционными. Используется тот же MockMvc, но уже с @SpringBootTest. Основное отличие - загружается весь Spring Context. Поэтому тест медленнее, чем больше приложение, тем медленнее. Если надо - в контексте можно поменять бины для тестового режима через Spring Profiles. Пример такого текста - в статье выше см. п. 1

3) интеграционное тестирование Spring приложения с сетью. Используется @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) и TestRestTemplate. Сервер для тестов запускается на произвольном порту, порт можно получить в тесте. Тесты этого типа ещё медленнее. Когда может быть полезен - нужно приближённое «к бою» тестирование. Или какие фишки http протестировать, типа редиректа. Вот пример https://sysout.ru/testirovanie-spring-boot-prilozheniya-s-testresttemplate/
А вот сравнение всех 3 подходов https://www.baeldung.com/spring-mockmvc-vs-webmvctest

4) у нас не Spring контроллер. Или уже есть опыт использования RestAssured, и он сугубо позитивный) Или нужны какие-то фишки RestAssured. А их много - xsd/json валидация, проверка длительности выполнения, встроенное логирование запроса и ответа, в т.ч. условное - в случае ошибки, использование Groovy для получения данных из тела запроса (!). Также данная библиотека рекомендуется для BDD тестов, т.к придерживается принятой там терминологии Given-When-Then https://en.m.wikipedia.org/wiki/Given-When-Then Для выполнения теста приложение нужно вначале запустить, например, через фазу pre-integration-test цикла сборки Maven. Вот неплохой tutorial https://www.baeldung.com/rest-assured-tutorial

Итого - как всегда в Java есть хорошие инструменты для разных задач.

#unittests #integration_test #rare_test_libs
Всем привет!

Небольшое дополнение про Given When Then из предыдущего поста. Данная формулировка пошла из BDD тестирования - Behavior driven development. BDD - это приемочное тестирование. Но в модульных (юнит) тестах существует аналогичная концепция - AAA - Arrange - Act - Assert. Суть та же - тест делится на 3 этапа: подготовка данных - вызов тестируемого метода - проверка результата.
Обычно эти три части в тесте разделяются пустой строкой для читаемости. В случае RestAssured и method chainig так не выйдет, но стоит разделить этапы переводом на новую строку. Arrange опционален, Act и Assert - обязательны. Act и Assert стоит разделить, даже если тянется рука сразу проверить результат вызова метода.

#unittests
Всем привет!

Есть такое известное правило - DRY - Don't Repeat Yourself. Оно касается кода, оно касается и настроек. Окей, задали мы настройки в одном месте - например, в корневом pom файле или build.gradle(.kts). Как пробросить их во все необходимые файлы при сборке? Этот процесс называется property expansion. К слову - в Maven есть понятие resource filtering. Это нечто большее - проход по всем ресурсным файлам, их фильтрация и кастомизация. Но обычно как раз таки используется для property expansion. Так вот, нашел неплохую статью как сделать это в Maven и Gradle https://www.baeldung.com/spring-boot-auto-property-expansion Что интересно - решение Maven выглядит более продуманным.

#gradle #maven #buildtool
Всем привет!

Давно не писал про Kotlin, а в названии канала он есть на почетном втором месте) Исправляюсь.

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

Вот например inline методы и связанный с ним reified https://www.baeldung.com/kotlin/reified-functions
При беглом знакомстве возникают 2 вопроса:
1) разработчики Kotlin загрязняют язык, ведь компилятор, а скорее JVM, сами справятся с inline?
2) Kotlin хакнул type erasure для generic?

Ответ на оба вопроса - нет.
И есть отличная статья на эту тему https://habr.com/ru/articles/775120/ Автора знаю лично, рекомендую почитать эту и другие его статьи про Kotlin.

Для ленивых ))) ответы:
1) inline нужен только для методов с параметрами функционального типа, чтобы избежать обвертывания функции в объект. Java компилятор не умеет работать с функциональными типами, увы
2) reified не нарушает спецификации Java, компилятор Kotlin лишь сохраняет тип там, где он его знает, и это касается только inline методов

И про простоту Kotlin в целом и сложность inline. Как выглядит процесс со стороны:
1) у нас полноценные функциональные типы
2) в коде их будет много
3) Java не умеет с ними работать
4) сделаем inline, чтобы не снизить производительность при работе с такими типами
5) появляются баги из-за inline, приходится вводить ключевые слова noinline и crossinline. Подробнее об этом есть в статье выше.
6) кто-то просит: раз при inline мы знаем исходный тип generic - давайте дадим возможность работы с ним, появляется reified
7) возникают новые баги, их фиксят
...

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

P.S. Ну и да, получается, во всем виновата Java)

#kotlin #java
Всем привет!

Одна из моих любимых тем: разработка - искусство компромиссов. Поиск по тэгам #dev_compromises и #arch_compromises. Следствие этого подхода, принцип, который я бы назвал - "не все так однозначно".

Вопрос - как вы относитесь к рефлексии в Java?

Досрочный ответ: рефлексия - это плохо, лучше не использовать. Если дошло до рефлексии - значит в архитектуре проблема.

Чтобы лучше разобраться в теме надо ответить на вопрос: а почему плохо?
Ответа два:

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

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

Окей, инкапсуляция нарушается, код работает медленно. Не используем?

А что с поиском аннотаций по коду? Не своих - до них мы еще дойдем - чужих, чтобы получить некие метаданные об объекте. Большинство вариантов вот тут основано на рефлексии https://www.baeldung.com/java-scan-annotations-runtime

Или у нас есть аннотации, созданные с помощью Spring AOP - это проще, чем AspectJ, если у вас используется Spring. А Spring AOP использует динамические прокси, создаваемые в runtime https://www.baeldung.com/spring-aop-vs-aspectj А с помощью чего создается прокси в runtime - правильно, рефлексии.

Да что там AOP - создание бинов из @Configuration - это тоже вызов методов @Bean через рефлексию.

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

Вернемся к двум ее недостаткам:

1) не надо использовать рефлексию для вызова private методов или доступа к private полям. Если такая задача встала - у вас в самом деле проблемы с архитектурой

2) не надо использовать рефлексию часто и при этом в высоконагруженных приложениях. Тот же Spring использует рефлексию только при старте приложения для инициализации прокси и бинов. И к слову в т.ч. и поэтому старт Spring приложения может быть долгим, и люди с этим борются, см. мой цикл статей про ускорение старта #java_start_boost Более того, разработчикам Spring для поддержки native image пришлось серьезно допиливать его в т.ч. из-за динамических прокси и @Configuration https://docs.spring.io/spring-boot/reference/packaging/native-image/introducing-graalvm-native-images.html

Итого: рефлексию стоит рассматривать как возможность получить метаданные о классе. Помня при этом о производительности.

И если вопрос упирается в производительность - всегда есть альтернативы рефлексии. Это работа с байт-кодом не в runtime:
1) compile time (свой компилятор, см. статью про AspectJ)
2) post-compile time (свой плагин для сборки, см. Jandex для поиска аннотаций https://smallrye.io/jandex/jandex/3.2.2/index.html)
3) load-time (свой агент+classloader, см. статью про AspectJ)
Все варианты сложнее в реализации и подключении к проекту, зато вносят минимальное влияние в runtime.

P.S. Да, если при упоминании о динамических прокси вы вспомнили про задачку с собесов о вложенном @Transactional - это оно. И ответ на этот вопрос не так очевиден https://habr.com/ru/articles/347752/

#java #reflection #dev_compromises
Всем привет!

Как можно масштабировать нагрузку в облаке? Под облаком я понимаю k8s как некий стандарт.

1) "ручками". Простой, но не надежный способ. Отягощающий фактор - не всегда у сопровождения ПРОМ есть права на смену настроек Deployment, тогда требуется отдельный деплой

2) выставить число подов и limits, соответствующими максимальной нагрузке. Еще проще, но совсем не рационально в плане использования ресурсов

3) HorizontalPodAutoscaler https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/ Позволяет менять число подов сервиса при превышении некого порога нагрузки по cpu и memory. Порог - это не процент использования, а соотношения заданного requests с текущим значением. Подходит если требуемая нагрузка может превышать возможности 1 пода, и если сервис поддерживает горизонтальное масштабирование - т.е. stateless.

4) VerticalPodAutoscaler https://habr.com/ru/companies/flant/articles/541642/ Как следует из название - масштабирует поды вертикально. Тут есть нюанс - на данный момент k8s не позволяет менять requests и limits у пода "на ходу". Данная фича называется In-Place Update of Pod Resources и пока находится в бета-версии https://github.com/kubernetes/enhancements/issues/1287
Сейчас VerticalPodAutoscaler может следующее:
а) на основе истории использования подом ресурсов рассчитать и выдать рекомендуемые значения
б) применить эти значения при очередном плановом рестарте
в) самому рестартовать под
Подходит для следующих случаев:
а) statefull сервисы типа хранилища данных в облаке StatefullSet, для которых горизонтальное масштабирование или невозможно, или не приветствуется
б) "легкие" сервисы, которым достаточно одной реплики (или двух по требованиям надежности)
Из особенностей - не гарантируется корректная работа совместно с HorizontalPodAutoscaler по одним и тем же метрикам cpu и memory. И не работает с Java приложениями в плане нагрузки по памяти, т.к. Java сама управляет памятью, а VerticalPodAutoscaler эти данные не видит.
Ну и главный минус - необходимость рестарта для применения настроек

5) как избавиться от необходимости рестарта? Дождаться полноценного внедрения In-Place Update of Pod Resources и доработки VerticalPodAutoscaler. Или использовать бета-версию In-Place Update of Pod Resources реализовать соответствующий k8s controller самому. Это уже сделано: https://piotrminkowski.com/2023/08/22/resize-cpu-limit-to-speed-up-java-startup-on-kubernetes/
Данная реализация не умеет сама рассчитывать рекомендуемые значения requests. Зато позволяет красиво проблему JVM приложений, о которой я уже писал ранее - проблему долгого старта. Java, а точнее Spring приложение, при старте производит достаточно ресурсоемкую настройку контекста. Речь идет про обычный Spring Boot без применения всех возможных способов ускорить запуск. Если память после первоначальной настройки так и остается занятой созданными бинами, то cpu при старте требуется сильно больше, чем при обычной работе. Что с этим делать?
а) Не выделять лишние cpu - время старта увеличивается в разы
б) Пойти по пути, описанному в п.2 - выдать максимум ресурсов. Тогда может получиться, что мы тратим cpu на быстрый старт приложения, а далее ресурсы не утилизируются
в) In-Place Update of Pod Resources
Конкретно по данной реализации - мне она кажется не идеальной, т.к. ресурс по cpu настраивается в 2 манифестах, это не наглядно и способствует внесению несогласованных правок. Но решение в целом - полезное.

#k8s #cloud #scalability
Всем привет!

Не так давно ChatGPT начала тестировать "умный поиск" - назвав его SearchGPT. В отличие от AI чата умный поиск ищет по существующим в интернете источникам, после чего делает выжимку из источника, оставляя ссылку на него. Что-то знакомое... Да, именно так работает Perplexity, см. https://t.me/javaKotlinDevOps/331. При этом исходный запрос может быть на естественном языке, и есть этап преобразования запроса в вид, оптимальный для поиска. И еще важно - учитывается контекст разговора, т.е. предыдущие запросы. Итого получаем смесь чата и поиска. Главное отличие от чатов - некая гарантия, что ответ не был синтезирован. Как этого удается добиться - очень интересный вопрос, ответа на него не знаю)

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

Чем ответят на это поисковики?
У Google и Bing пока не вижу ничего подобного. Я не про возможность добавить ссылки для ответа чат-бота, а про интеграцию в поиск и некие гарантии точности ответа. Хотя возможности у них есть - Gemini и Copylot соответственно.
А вот Yandex совместил поиск с чатом, и это можно увидеть выбрав тип поиска Нейро. Подробнее как это работает - см. https://vk.com/video-17796776_456241214 Это не бета, не ограниченный доступ.
Круто, что могу сказать!

P.S. Perplexity похоже задал тренд.

P.P.S. Как все-таки они гарантируют отсутствие галюцинаций???

#ai #search
Всем привет!

Есть такая отличная IDE для Java и Kotlin - IntelliJ IDEA.
Лучшая если быть точным)
И у нее есть 2 версии: Community и Ultimate.
Отличия можно посмотреть тут https://www.jetbrains.com/products/compare/?product=idea&product=idea-ce
Плохая новость в том, что IntelliJ, к сожалению, забила на российских разработчиков. Если Community можно скачать без VPN
// а) пока можно б) VPN понадобится для обновления плагинов)
то купить Ultimate сложнее.

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

Так вот, если смотреть на отличия двух версий IDEA - бросаются в глаза следующие полезные штуки:
1) поддержка Spring
2) поддержка JPA
3) Database Tools
4) HTTP Client
5) поддержка Kubernetes
6) Java applications servers
7) Profiling tools

Что тут можно сделать?

-1) сидеть на perpetual лицензии. Плохо, не доступны новые версии Java и фиксы

0) даунгрейд до Community - возможно кому-то подойдет, но есть варианты лучше

1) найти правильную карту или человека с правильной картой и надеяться, что вас не заблокируют - https://t.me/spring_aio/245. Так себе идея, как по мне.

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

3) в качестве замены IDEA Ultimate Сбер разрабатывает GigaIDE Desktop. Важное слово здесь - разрабатывает.
Что это за зверь такой - если кратко: IDEA Community + open source плагины + предустановленный AI ассистент GigaCode. Подробнее можно почитать тут https://habr.com/ru/companies/haulmont/articles/828828/ Статья еще полезна тем, что можно подсмотреть полезные плагины, которые предустановлены в GigaIDE.
Обращает внимание нормальная альтернатива Database Tools и отсутствие альтернатив для остальных пунктов. Самая больная часть - Spring. Разработка плагина от Сбера идет, результат на данный момент неизвестен.

4) собрать свою IDEA на основе Community или GigaIDE. И тут у нас есть хорошая альтернатива Spring и JPA плагину - Amplicode. Это новый плагин от Haulmont, авторов JPA Buddy - плагина для работы с JPA+Liquibase+Flyway. Amplicode насколько я могу судить включает в себя функционал JPA Buddy. Детальнее про Amplicode можно почитать тут https://habr.com/ru/companies/haulmont/articles/814207/ или посмотреть видосы тут https://vk.com/video/playlist/-222549074_1 А вот тут независимые от разработчиков Amplicode ребята провели сравнение поддержки Spring в Ultimate и Amplicode https://habr.com/ru/companies/spring_aio/articles/854062/
Они примерно равны, со своими сильными и слабыми сторонами. Лично мне Amplicode даже больше понравился. Разве что встроенного аналога start.spring.io не хватает, но в конце концов есть собственно https://start.spring.io. В общем настоятельно рекомендую установить Amplicode даже если у вас Ultimate. Предварительно посмотрев обучающие материалы по ссылке выше)

5) хардкор - собрать свою IDEA из исходников, вот инструкция https://habr.com/ru/companies/spring_aio/articles/852526/ Как по мне - особой необходимости нет. Пока Community Edition останется Open Source - я бы не беспокоился. Вряд ли в open source продукт вкорячат блокировку по IP) И вряд ли перестанут работать все VPN, включая настроенные самостоятельно.

P.S. Что касается остальных инструментов из Community - если знаете альтернативы - добро пожаловать в комментарии.
Или возможно я забыл что еще важное?

#ide #idea
Всем привет.

В дополнение к предыдущему посту - ещё один способ получить IDEA Ultimate в России.

6) участие в программе EAP - Early Access Program. https://www.jetbrains.com/idea/nextversion
За подсказку спасибо @poeticpragmatic
Особенности:
а) критичные баги не замечены
б) имеет смысл автоматизировать накат новой версии скриптом с сохранением предыдущей для возможности отката. Если критичные баги все же появятся)

Не заблокируют ли этот вариант - да кто его знает)

#ide #idea
Всем привет!

И ещё пару мыслей по развитию IDEA в России.

1) кажется, что со стороны Сбера было бы разумнее использовать готовый сильный продукт в виде Amplicode, чем в спешном порядке делать свой Spring плагин. Даже с учётом потенциальной монетизации Amplicode.

2) Haulmont активно развивается. Вначале JPA Buddy, теперь Amplicode, включающий его функционал. Что дальше?
IDEA, к слову, начинала с 2 плагинов к Borland JBuilder https://blog.jetbrains.com/ru/team/2013/02/28/nikolaj-chashnikov-intellij-idea-ide-kotoraya-ponimaet-kod/

Да, эти два пути противоречат друг другу. Да и российский рынок не выдержит 2 IDE) Их в мире по большому счёту три.

#ide #idea