Обновить
64K+
59
Spring АйО@spring_aio

Главный по Spring

27,2
Рейтинг
421
Подписчики
Отправить сообщение

Проблема фантомной записи: почему ваша реализация идемпотентности незаметно теряет данные

Уровень сложностиПростой
Время на прочтение7 мин
Охват и читатели8.7K

В проде бывает так, что одна и та же операция часто повторяется: клиент не дождался ответа и ретраит, балансер порвал соединение, очередь переиграла сообщение. Вспоминаем про идемпотентность - это правило «повтор не должен создавать новый платёж/заказ».

Чтобы отличать повтор от новой операции, используют idempotency key (ключ идемпотентности). Это обычная уникальная строка-идентификатор, которую клиент или апстрим отправляет вместе с запросом (часто в заголовке Idempotency-Key). Сервис сохраняет этот ключ у себя и связывает с результатом операции.

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

В новом переводе от команды Spring АйО рассмотрим не самые очевидные ошибки и то, о чём стоит подумать, при реализации идемпотентного API.

Читать далее

Перевополщение Stable Values в JDK 26

Время на прочтение9 мин
Охват и читатели8.6K

В новом переводе от команды Spring АйО рассмотрим ленивую инициализацию в Java , которая почти всегда значит: поле сначала null, потом double-checked locking, volatile, синхронизация. Ошибиться легко, а final не поставить. Итог - код хрупче и JVM хуже делает constant folding.

В JDK 26 (preview, JEP 526) добавили LazyConstant<T>: final поле, рецепт вычисления через Supplier, значение доступно черезget(). Supplier выполнится при первом get и только один раз успешно, даже при гонке потоков. Кроме этого значение помечается как @Stable - JVM может считать его константой и агрессивнее оптимизировать.

Граничные случаи: null нельзя; не сериализуется; исключение из Supplier пробросится и следующая попытка снова пересчитает; equals у LazyConstant - только identity.

Для 1:n есть List.ofLazy и Map.ofLazy: элементы/значения считаются по индексу/ключу по требованию и кэшируются.

Читать далее

Я залез в исходники Claude Code. Фичи, которых нет в документации

Уровень сложностиПростой
Время на прочтение16 мин
Охват и читатели16K

Оказывается, документация Claude Code рассказывает не всё. Стоило только лишь заглянуть в исходники. И вот что можно настроить, но чего нет в доке:

— hooks, которые переписывают команды на лету;
— автоодобрение safe-команд без лишних подтверждений;
— постоянная память агентов между сессиями;
— auto-mode, который понимает описание окружения на обычном английском;
— самообучающиеся циклы памяти и «снов»;
— скрытые поля skills, agents и permissions, которых нет в документации.

И все это работает уже сейчас, а исходники Claude Code лежат у вас в node_modules. Мы собрали все в статью. Там больше конкретики, JSON-конфигов, shell-хуков и примеров, которые можно утащить себе почти без правок.

Читать далее

Java — быстрая. Ваш код может таким не быть

Уровень сложностиПростой
Время на прочтение12 мин
Охват и читатели17K

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

- Конкатенация строк в циклах

- String.format() в горячем коде

- Автобоксинг 

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

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

Читать далее

Соль и перец в безопасности паролей

Уровень сложностиПростой
Время на прочтение6 мин
Охват и читатели12K

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

Однако обычного хеширования недостаточно из-за угрозы быстрых хакерских атак. Для защиты разработчики применяют «соль» (salt) — случайные данные, добавляемые к паролю. Минус соли в том, что она хранится рядом с хешем и не спасает от мощного перебора. Тогда на помощь приходит «перец» (pepper), скрытый в коде сервера. Его главная проблема — высокий риск потерять доступ ко всем аккаунтам при компрометации самого секретного ключа.

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

Читать далее

Эволюция API без боли: ArchUnit, Gradle и правила для библиотек

Уровень сложностиПростой
Время на прочтение10 мин
Охват и читатели10K

В Netflix тысячи Java-репозиториев. Когда в библиотеку вносят изменение, часть пользователей может перестать собираться или начать работать некорректно. Чаще всгео эта проблема возникает потому, что public контракты являются public только для авторов библиотеки, а не для пользователей.

С новом переводе от команды Spring АйО разбираемся, как ребята из Netflix ввели простые метки для API: @Public - можно использовать снаружи, @Experimental - тоже можно, но интерфейс может меняться, @Deprecated - готовится к удалению. Все остальное считается внутренним и использованию извне не подлежит. Но сами аннотации проблему не решают, нужна проверка на масштабе.

Решение - ArchUnit + Nebula ArchRules. 

ArchUnit анализирует скомпилированный байткод, поэтому одинаково работает для Java/Kotlin/Scala и проверяет реальный код на classpath. Команды пишут правила (например: «вне пакета библиотеки нельзя зависеть от ее deprecated/internal API»), публикуют их как отдельный arch-rules JAR, а runner автоматически запускает проверки в репозиториях и делает отчеты с точной строкой нарушения.

Читать далее

Kotlin переходит к деструктурированию по именам

Уровень сложностиПростой
Время на прочтение6 мин
Охват и читатели9.8K

В Kotlin деструктурирование выглядело так: val (name, age) = person. Но компилятор берет значения не по именам, а по позиции component1/component2.

Отсюда проблемы. Если поменяли порядок параметров в data class или сделали age вычисляемым свойством: то та же строка начинает доставать другое поле. Причем иногда код даже скомпилируется, но, конечно, смысл изменится: val (age, name) = person.

И вот теперь Kotlin эксперементально переводит круглые скобки на деструктурирование по имени. Синтаксис будет такой: (val name, val age) = person. И порядок внутри скобок не важен. Переименование явно: (val years = age, val theName = name) = person.

Позиционное же деструктурирование остается, но переезжает в квадратные скобки для Pair/Triple и коллекций: val [x, y] = point.

Разбираемся полностью в новом переводе от команды Spring АйО.

Читать далее

Команда Spring о Spring Framework 7 и Spring Boot 4

Уровень сложностиПростой
Время на прочтение11 мин
Охват и читатели11K

В новом переводе от команды Spring АйО рассмотрим выход Spring Boot 4 и Spring Framework 7. InfoQ взяли интервью у core команды Spring с целью узнать, куда движется самая популярная в Java экосистема.

Spring Boot 4 модуляризировал автоконфигурацию. Теперь при запуске проверяется меньше классов в classpath, а uber-jar будет более компактным: будут подключаться только нужные модули. Параллельно Spring Boot 4 переходит на Jackson 3, но добавлен модуль совместимости с Jackson 2, потому что экосистема ещё догоняет.

Spring Framework 7 тащит core resilience в ядро: RetryTemplate, @Retryable и @ConcurrencyLimit доступны без отдельной зависимости. @Retryable работает и с реактивными типами (через Retry из Project Reactor); для обычных вызовов используется RetryTemplate с политикой retry/backoff. @ConcurrencyLimit помогает ограничивать доступ к ресурсу, что особенно полезно с Virtual Threads.

Читать далее

Поддержка Docker Compose в Spring Boot 3.1

Уровень сложностиПростой
Время на прочтение4 мин
Охват и читатели9.6K

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

– PostgreSQL

– Kafka

– RabbitMQ

– Redis

И так далее. Менеджить целый зоопарк таких сервисов локально бывает не очень удобно. К счастью, у команды Spring Boot для вас есть небольшой помошник - Spring Boot Docker Compose.

Комментарий от Михаила Поливахи:

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

Читать далее

REST умер? Почему Java-разработчики уходят в GraphQL

Уровень сложностиПростой
Время на прочтение10 мин
Охват и читатели14K

Один экран в приложении, а на бэкенде несколько REST-вызовов, куча эндпоинтов и ответы, где 90% полей не используются. Теряем в скорости, усложняется фронтенд и приходится версионировать контракт, когда меняется формат данных.

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

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

Читать далее

Самый простой способ устроить утечку памяти в Java

Уровень сложностиПростой
Время на прочтение12 мин
Охват и читатели9.2K

В новом переводе от команды Spring АйО рассмотрим утечки памяти в Java.

Не секрет, что GC освобождает только недостижимые объекты. Утечка в Java начинается там, где объект уже не нужен, но на него все еще есть цепочка ссылок от живого потока.

Симптомы обычно одинаковые: куча растет, GC срабатывает чаще, паузы увеличиваются, финал - java.lang.OutOfMemoryError: Java heap space.

В целом вывод такой, что нужно смотреть график heap в VisualVM/JVisualVM/JConsole, снимать heap dump (jmap), в Eclipse MAT запускать Leak Suspects и проверять цепочки удерживающих ссылок.

Читать далее

Раздувание памяти JDK 17 в контейнерах: разбор инцидента

Уровень сложностиПростой
Время на прочтение9 мин
Охват и читатели13K

В новом переводе от команды Spring АйО разберем тему раздувания памяти в JDK 17. Апгрейд микросервисов с JDK 8 на JDK 17 прошел dev и QA спокойно, но в проде через 2-3 часа все начало падать. Утилизация памяти выросла в 4 раза, контейнеры стали ловить OOMKill и перезапускаться, Uptime SLA просел, массовый инцидент.

Раньше JVM использовала около 50% памяти контейнера и обслуживала ~400 потоков. После релиза стало 95-100% и 1600+ соответственно. 

При этом heap выглядел нормально, около Xmx, а раздувалась нативная память: ~800 MB -> 3,4-3,6 GB. Виноваты несколько эффектов, которые в контейнерах усиливаются: JVM начала создавать намного больше потоков, OS стала выделять JVM гораздо больше, а дефолтный GC в JDK 17 добавил накладные расходы.

Всё это из-за простого бага в JDK, который при миграции утащил за собой весь production.

Читать далее

OpenTelemetry со Spring Boot

Уровень сложностиПростой
Время на прочтение13 мин
Охват и читатели8.2K

В новом переводе от команды Spring АйО смотрим, как подружить современный Spring Boot и OpenTelemetry так, чтобы данные уходили по OTLP в любой совместимый бэкенд. 

В экосистеме Spring большая часть телеметрии была завязана на Micrometer Project (Был ещё spring-cloud-sleuth если кто помнит). Но полноценного all-in-one решения для того, чтобы Spring Boot приложение просто начало экспортировать телеметрию по OTLP не было. До Spring Boot 4.

На данный момент для интеграции OTel в Spring Boot приложения есть 3 пути: Java Agent (минимум кода, но чувствителен к версиям и может конфликтовать с другими агентами), сторонний OTel starter (стартер от самих OpenTelemetry, но тянет alpha-зависимости) и новый spring-boot-starter-opentelemetry, доступный в Spring Boot 4.0. Про него и будет речь.

Читать далее

DPoP: что это такое, как работает и почему Bearer-токенов недостаточно

Уровень сложностиПростой
Время на прочтение11 мин
Охват и читатели7.7K

Bearer-токен работает слишком просто: кто его получил, тот и авторизован. Именно поэтому утечки токенов регулярно превращаются в реальные инциденты — от CI/CD до облачных хранилищ.

В новом переводе от команды Spring АйО рассмотрим, как DPoP меняет эту модель, привязывая токен к ключу клиента, зачем это нужно backend-разработчику и как поднять рабочую реализацию на Keycloak и Quarkus.

Читать далее

Spring Data. На пути к более строгой типизации

Уровень сложностиПростой
Время на прочтение7 мин
Охват и читатели7.1K

В новом переводе от команды Spring АйО разберем, почему stringly-typed API со временем становятся хрупкими, чем помогают метамодели вроде Querydsl и JPA Criteria, и как новый механизм в Spring Data даёт более лёгкую и естественную альтернативу без лишней инфраструктуры сборки.

Читать далее

Netflix: практическое применение Vector API, которое спасло CPU

Уровень сложностиПростой
Время на прочтение10 мин
Охват и читатели6.7K

Иногда одна незаметная фича может сжигать гигантский объём ресурсов. В Netflix именно так и вышло: скоринг серендипности в Ranker оказался дорогой горячей точкой, а попытка слегка его ускорить в итоге привела к большой инженерной перестройке — от батчинга до SIMD через JDK Vector API.

В новом переводе от команды Spring АйО разберем, как SIMD AVX инструкции на практике позволили снизить потребление CPU.

Читать далее

О размерах пула соединений

Уровень сложностиПростой
Время на прочтение7 мин
Охват и читатели13K

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

Подробнее в новом переводе от команды Spring АйО.

Читать далее

Изменения в G1/Parallel/Serial GC в JDK 26

Уровень сложностиПростой
Время на прочтение8 мин
Охват и читатели7.2K

JDK 26 выходит уже совсем скоро. Тем временем в GC закрыли около 380 задач (почти в 2 раза больше, чем в прошлом релизе), но в этот раз акцент сместился с  больших фич в пользу практичных доработок.

Главное для всех сборщиков: нормальный учет CPU GC. Теперь считают не только stop-the-world паузы, но и конкурентную работу и дедупликацию строк. Можно посмотреть через лог cpu=info при завершении VM, обновили Hsperf-счетчики, есть доступ из кода. Плюс новый JFR-ивент с деталями по string dedup.

JEP 516: Aot Cache стал независим от выбранного GC и опций VM. Включение через опцию -XX:+AOTStreamableObjects.

G1 получил самые заметные улучшения: JEP 522 уменьшает синхронизацию между GC и приложением (цель - увеличить throughput). Еще: целевое использование CPU G1 по умолчанию снижено с 8% до 4%, добавили важнейший флаг UseGCOverheadLimit.

Читать далее

Разница между параллельными и распределёнными вычислениями

Уровень сложностиПростой
Время на прочтение7 мин
Охват и читатели7.6K

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

Читать далее

Введение в модели согласованности

Уровень сложностиПростой
Время на прочтение15 мин
Охват и читатели8.6K

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

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

Читать далее
1
23 ...

Информация

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