Одна из самых частых тем на собеседованиях Java/backend-разработчиков ⇒ Проблема N+1 в JPA
→ 1 первичный запрос: получение N родительских сущностей.
→ Затем N дополнительных запросов: для каждой из этих N сущностей выполняется отдельный запрос, чтобы загрузить связанные дочерние данные.
→ В итоге выполняется 1 + N запросов к БД, что приводит к снижению производительности и замедлению отклика.
Пример:
Получаем 100 авторов (1 запрос), а затем в цикле вызываем author.getBooks() для каждого (N=100) — в итоге 101 запрос.
⇒ Как решить проблему N+1 в JPA
⇆ Цель — загрузить связанные данные за меньшее количество запросов, желательно за один проход к базе.
1. JPQL/HQL JOIN FETCH (рекомендуется для конкретных связей)
Позволяет явно указать JPA, что ассоциации нужно подгружать через JOIN в запросе.
Пример:
Плюсы: один эффективный запрос.
Важно: при джойне нескольких коллекций можно получить декартово произведение.
2. Batch Fetching
(
Вместо одного запроса на каждого родителя, связанные коллекции загружаются пакетами — по нескольким ID за один запрос.
Пример:
Плюсы: уменьшает количество запросов с 1 + N до 1 + (N / batch_size), избегая проблемы декартовых произведений.
3. Entity Graphs
(
Позволяет декларативно определить, какие связи нужно подгружать eagerly для конкретного метода репозитория.
Пример:
Плюсы: гибкая и переиспользуемая стратегия загрузки без явных JPQL JOIN’ов.
Всегда используйте явные стратегии загрузки (такие как JOIN FETCH,
👉 Java Portal
→ 1 первичный запрос: получение N родительских сущностей.
→ Затем N дополнительных запросов: для каждой из этих N сущностей выполняется отдельный запрос, чтобы загрузить связанные дочерние данные.
→ В итоге выполняется 1 + N запросов к БД, что приводит к снижению производительности и замедлению отклика.
Пример:
Получаем 100 авторов (1 запрос), а затем в цикле вызываем author.getBooks() для каждого (N=100) — в итоге 101 запрос.
⇒ Как решить проблему N+1 в JPA
⇆ Цель — загрузить связанные данные за меньшее количество запросов, желательно за один проход к базе.
1. JPQL/HQL JOIN FETCH (рекомендуется для конкретных связей)
Позволяет явно указать JPA, что ассоциации нужно подгружать через JOIN в запросе.
Пример:
@Query("SELECT a FROM Author a JOIN FETCH a.books")
List<Author> findAllWithBooks();
Плюсы: один эффективный запрос.
Важно: при джойне нескольких коллекций можно получить декартово произведение.
2. Batch Fetching
(
@BatchSize
или hibernate.default_batch_fetch_size
)Вместо одного запроса на каждого родителя, связанные коллекции загружаются пакетами — по нескольким ID за один запрос.
Пример:
@BatchSize(size = 10)
@OneToMany(...)
private List<Book> books;
Плюсы: уменьшает количество запросов с 1 + N до 1 + (N / batch_size), избегая проблемы декартовых произведений.
3. Entity Graphs
(
@EntityGraph
— Spring Data JPA / JPA 2.1+)Позволяет декларативно определить, какие связи нужно подгружать eagerly для конкретного метода репозитория.
Пример:
@EntityGraph(attributePaths = "books")
List<Author> findAll();
Плюсы: гибкая и переиспользуемая стратегия загрузки без явных JPQL JOIN’ов.
Всегда используйте явные стратегии загрузки (такие как JOIN FETCH,
@BatchSize
или @EntityGraph
), чтобы избежать проблемы N+1 и обеспечить эффективное взаимодействие с базой данных.Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤4😁1
Распространённые Алгоритмы Балансировки Нагрузки
Статические алгоритмы
Динамические алгоритмы
👉 Java Portal
Статические алгоритмы
1. Круговой Алгоритм
Клиентские запросы отправляются в различные экземпляры сервисов в последовательном порядке. Сервисы обычно должны быть без сохранения состояния.
Недостаток:
- Эта простейшая версия алгоритма будет эффективно работать только в сферической среде в вакууме, где все серверы обладают почти одинаковой конфигурацией, а все входящие запросы (задачи, процессы) имеют одинаковые приоритет и продолжительность.
2. Закреплённый Круговой Алгоритм
Усовершенствование кругового алгоритма. Если первый запрос Алисы отправляется в сервис A, следующие запросы также отправляются в сервис A.
3. Взвешенный Круговой Алгоритм
Администратор может указать вес для каждого сервиса. Сервисы с более высоким весом обрабатывают больше запросов, чем другие.
4. Хэш IP/URL
Применяет хеш-функцию к IP или URL входящих запросов. Запросы направляются в соответствующие экземпляры на основе результата хеш-функции.
Преимущества:
- Постоянство сессии – алгоритм гарантирует, что запросы от одного клиента всегда попадают на один и тот же сервер.
- Облегчает кеширование данных на стороне сервера для конкретных клиентов.
Недостатки:
- Если много пользователей приходят из одного диапазона IP, один сервер может быть перегружен.
- Неэффективен в средах, где IP клиентов часто меняются (мобильные сети).
- Может привести к неравномерной нагрузке, если некоторые клиенты генерируют больше трафика.
Динамические алгоритмы
5. Наименьшее Количество Соединений
Новый запрос отправляется в экземпляр сервиса с наименьшим количеством одновременных подключений.
Преимущества:
- Более мощные серверы естественным образом будут обрабатывать больше запросов и, следовательно, иметь больше соединений. И напротив, менее мощные серверы будут получать меньше запросов, что предотвращает их перегрузку.
- Гибкость – если один сервер начинает работать медленнее, он будет получать меньше новых запросов.
Недостатки:
- Алгоритм считает все соединения одинаковыми, не учитывая, что некоторые запросы могут быть более ресурсоёмкими.
- Вновь добавленный сервер может получить слишком много запросов, т.к. изначально у него 0 соединений.
6. Наименьшее Время Ответа
Новый запрос отправляется в экземпляр сервиса с самым быстрым временем ответа. Аналогичный алгоритм - Наименьший объем трафика
Преимущества:
- Учёт текущей производительности серверов и динамическая адаптация обеспечивают оптимальный баланс и наилучший пользовательский опыт.
- Хорошо работает с серверами разной мощности и приложениями с разными характеристиками.
Недостаток:
- Сложность реализации – требует постоянного мониторинга и анализа производительности серверов, отсюда повышенная нагрузка на балансировщик.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Полный Roadmap для Spring Boot разработчика
Много разработчиков ищут структурированный путь от новичка до продвинутого уровня в Spring Boot. Ниже представлен 3-фазный roadmap, который поможет освоить все ключевые концепции и инструменты.
PHASE 1
- Создание Spring Boot проекта через Spring Initializer
- Maven и Gradle
- Основные аннотации
- Профили и конфигурации для разных окружений
-
- Path variables и request parameters
- Настройка баз данных (H2, MySQL, PostgreSQL)
- Использование
- Spring Boot DevTools и hot reloading
- Spring Batch, Scheduling и Cron выражения
PHASE 2
-
- Кастомные ошибки и глобальная обработка исключений
- Базовая аутентификация и настройка безопасности API
- JWT для stateless аутентификации
- HATEOAS и версионирование REST API (URI, параметры, headers)
- Unit-тесты с JUnit и Mockito
- Интеграционные тесты с Spring Boot Test и MockMvc
- Actuator endpoints и кастомные health indicators
PHASE 3
-
- Spring Cloud: Eureka Server, Service Discovery, API Gateway
- Spring Cloud Config Server для централизованного управления конфигурациями
- Настройка Spring Boot приложений для работы с Config Server
Чтобы полностью усвоить материал, постройте свои проекты на каждом этапе. Практика поможет закрепить знания и сделает их долговечными.
👉 Java Portal
Много разработчиков ищут структурированный путь от новичка до продвинутого уровня в Spring Boot. Ниже представлен 3-фазный roadmap, который поможет освоить все ключевые концепции и инструменты.
PHASE 1
- Создание Spring Boot проекта через Spring Initializer
- Maven и Gradle
- Основные аннотации
- Профили и конфигурации для разных окружений
-
@GetMapping
, @PostMapping
, @PutMapping
, @DeleteMapping
- Path variables и request parameters
- Настройка баз данных (H2, MySQL, PostgreSQL)
- Использование
JpaRepository
и CrudRepository
- Spring Boot DevTools и hot reloading
- Spring Batch, Scheduling и Cron выражения
PHASE 2
-
@ControllerAdvice
и @ExceptionHandler
- Кастомные ошибки и глобальная обработка исключений
- Базовая аутентификация и настройка безопасности API
- JWT для stateless аутентификации
- HATEOAS и версионирование REST API (URI, параметры, headers)
- Unit-тесты с JUnit и Mockito
- Интеграционные тесты с Spring Boot Test и MockMvc
- Actuator endpoints и кастомные health indicators
PHASE 3
-
@Profile
и настройка бинов для разных окружений - Spring Cloud: Eureka Server, Service Discovery, API Gateway
- Spring Cloud Config Server для централизованного управления конфигурациями
- Настройка Spring Boot приложений для работы с Config Server
Чтобы полностью усвоить материал, постройте свои проекты на каждом этапе. Практика поможет закрепить знания и сделает их долговечными.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5🔥5🏆2
В статье разбираем, почему graceful shutdown важен и как настроить плавное завершение работы Spring Boot приложения, которое работает с Kafka.
Ты узнаешь, как корректно завершать обработку сообщений, чтобы не потерять данные и избежать ошибок при остановке сервиса. Практичные советы и примеры кода помогут сделать твое приложение более стабильным и надежным.
👉 Java Portal
Ты узнаешь, как корректно завершать обработку сообщений, чтобы не потерять данные и избежать ошибок при остановке сервиса. Практичные советы и примеры кода помогут сделать твое приложение более стабильным и надежным.
Please open Telegram to view this post
VIEW IN TELEGRAM
Хабр
До свидания, Kafka, или graceful shutdown на Spring Boot для Kafka
Привет! В этой статье я немного объясню важность graceful shutdown и расскажу как сделать плавное завершение работы твоего Spring Boot приложения, которое взаимодействует с Kafka. Представь, что ты...
❤1