Библиотека джависта | Java, Spring, Maven, Hibernate
22.3K subscribers
2.45K photos
54 videos
49 files
3.59K links
Все самое полезное для Java-разработчика в одном канале.

Учиться у нас: clc.to/AATM8w

Для обратной связи: @proglibrary_feeedback_bot

По рекламе: @proglib_adv

РКН: https://gosuslugi.ru/snet/67a5bbda1b17b35b6c1a55c4
Download Telegram
✔️ Concurrency-тест: пул потоков копит задачи до OOM

Нагрузка выросла, latency пополз вверх, потом OutOfMemoryError 👇

📦 Задание — code review

Сервис обрабатывает входящие события асинхронно.
@Configuration
public class ExecutorConfig {

@Bean
public ExecutorService eventExecutor() {
return Executors.newFixedThreadPool(10);
}
}

@Service
@RequiredArgsConstructor
public class EventService {

private final ExecutorService eventExecutor;

public void handle(Event event) {
eventExecutor.submit(() -> process(event));
}
}


▪️ Объясни

— Какая очередь стоит за Executors.newFixedThreadPool и почему она опасна под нагрузкой.
— Почему задачи бесконтрольно «копятся» и система падает в OutOfMemoryError, а не начинает отбрасывать нагрузку.
— Как собрать ThreadPoolExecutor руками: ограниченная очередь, RejectedExecutionHandler, backpressure. Чем плох и newCachedThreadPool в этом сценарии.

Ставьте → 🔥, если нравится формат. Если нет → 🌚

💬 Решения под спойлер. Сравним, какое будет лучше.

🐸 Библиотека собеса по Java

#practise
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥131👍1👏1
🐳 Магия Docker CLI

Собрали образ и он весит 2 ГБ, а вы не понимаете, откуда столько? docker history покажет размер каждого слоя — сразу видно, какая инструкция в Dockerfile раздула образ.

🔹 Зачем это нужно

— Каждая инструкция в Dockerfile создаёт слой, и docker history показывает размер каждого.
— Сразу видно, если COPY затянул 800 МБ зависимостей.
— Помогает оптимизировать порядок слоёв для лучшего кэширования.

🔹 Как использовать

— Посмотреть слои: docker history my-image
— Без обрезки команд: docker history --no-trunc my-image
— Только размеры в human-readable: docker history --format "{{.Size}}\t{{.CreatedBy}}" my-image
— Сравнить два образа: запустите history для обоих и сравните слои.

💡 Если видите большой слой от COPY . . — значит, в контекст сборки попали модули, .git или логи. Проверьте dockerignore, это обычно экономит сотни мегабайт.

══════ Навигация ══════
ВакансииЗадачиСобесы

🐸 Библиотека джависта

#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥3👏2
🚀 Уже завтра стартует новый поток курса «ИИ-агенты»!

Мы собрали мощнейший состав преподавателей. Учить вас проектировать архитектуру и собирать продакшн-агентов будут инженеры и исследователи из топовых IT-компаний.

Старт уже завтра!

Сомневаетесь, подойдет ли вам программа и подача? Начните с бесплатного демо-урока!

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

🔗 Пройти демо-урок и занять место на курсе
1👍1
🔍 List vs Set в @OneToMany: почему «просто замени на Set» — плохой совет

List без @OrderColumn в Hibernate — это bag, неупорядоченное мультимножество. Попытка вытащить две bag-коллекции одним JOIN FETCH роняет приложение ещё на старте:
org.hibernate.loader.MultipleBagFetchException:
cannot simultaneously fetch multiple bags


В интернете 280+ апвоутов у ответа «замени List на Set». Исключение он действительно убирает, но лечит симптом, а не причину.

Суть проблемы в том, что JOIN FETCH двух коллекций порождает декартово произведение строк (N×M). С Set Hibernate просто дедуплицирует это в памяти → SQL-результат всё равно раздут, и на больших коллекциях это деградация, а не решение.

Правильно — грузить максимум одну коллекцию за запрос. Persistence Context гарантирует, что в рамках сессии сущность загружается в единственном экземпляре, поэтому две коллекции можно безопасно дотянуть двумя отдельными запросами / @EntityGraph, или через @BatchSize / subselect-fetch.

Бонус про bag: при изменении bag-коллекции (особенно с join-таблицей без собственного PK) Hibernate нередко делает DELETE всех строк коллекции и INSERT заново вместо точечного INSERT. Ещё один аргумент не использовать bag для изменяемых связей.

══════ Навигация ══════
ВакансииЗадачиСобесы

🐸 Библиотека джависта

#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
7🤔5👍3🔥1
🔥 Стартуем СЕГОДНЯ! Новый поток курса «Разработка ИИ-агентов» открыт

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

Внутри глубокий разбор LLM от Алексея Яндутова (Senior ML-инженер, развивал ответы «Алисы» и «Нейро» в Яндексе). Учимся получать точный результат без галлюцинаций.

Что внутри урока:

- Устройство LLM.
- Рабочие шаблоны промптов (Persona, Chain-of-Thought и др.).
- Разбор реального кейса Яндекса. Как автоматизировать разметку, обойти качество людей на 5% и срезать косты на 60%.


После просмотра вы поймете, когда хватает промпт-инжиниринга, а когда нужен RAG или fine-tuning.

👉Смотреть закрытый урок на YouTube

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

🔗 Занять место на курсе
1
ℹ️ Circuit Breaker: контролируемая деградация вместо падения

Любой вызов внешнего сервиса может зависнуть, упасть или начать возвращать ошибки — неважно, ходишь ты через Feign, WebClient, gRPC или в базу. Circuit Breaker страхует от того, чтобы эта беда утянула за собой твоё приложение.

Дальше на примере Feign-клиента и Resilience4j в Spring, но паттерн работает с любым вызовом.

Вешаем брейкер на метод и сразу указываем, куда падать при проблемах:
@CircuitBreaker(name = "authorService", fallbackMethod = "getInstanceFallback")
String getInstance();

name ссылается на конфиг в application.yml, а fallbackMethod на метод, который отдаст запасной ответ.

🔹Важное правило

Сигнатура фолбэка должна совпадать с исходным методом — тот же тип возврата, те же аргументы плюс Throwable последним параметром. Иначе получишь NoSuchMethodException в рантайме:
public String getInstanceFallback(Throwable ex) {
return "Fallback content";
}


Настраиваем порог и время ожидания под тем же name:
resilience4j:
circuitbreaker:
instances:
authorService:
failure-rate-threshold: 50
sliding-window-size: 10
wait-duration-in-open-state: 5s


🔹 Как это живёт

Брейкер считает долю ошибок не с первого запроса, а по скользящему окну (sliding-window-size). 50% — это «половина из последних 10 вызовов упала», а не «одна ошибка из двух».

Когда порог превышен, цепь размыкается (open) и брейкер перестаёт долбиться в упавший сервис и сразу отдаёт fallback, не копя таймауты.

Через wait-duration-in-open-state цепь переходит в half-open: пропускает несколько пробных запросов. Сервис ожил — цепь замыкается обратно (closed), нет — снова размыкается.

🔹 Идея простая

Внешний сервис упал, а твоё приложение деградирует контролируемо, а не валится следом.

══════ Навигация ══════
ВакансииЗадачиСобесы

🐸 Библиотека джависта

#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥93👍3👏2❤‍🔥1
🔥 Курс «Разработка ИИ-агентов» стартовал, но вы еще успеваете присоединиться!

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

💼 Главная фишка: финальный проект в портфолио:

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


🎁 Упомяните менеджеру специальное предложение «3 курса по цене 1»: Берете VIP-тариф — получаете курс «Разработка ИИ-агентов», хардкорный «AgentOps» и ещё один курс на выбор. Выгода 129.000 ₽!

Двери потока вот-вот закроются окончательно. Успейте забрать стек курсов и начать работу над реальным проектом

🔗 Занять место и забрать 3 курса
😮 Топ-вакансий для джавистов за неделю

Разработчик Java — удалёнка/гибрид (Санкт-Петербург) — 585, Холдинг

Java-разработчик Middle — удалёнка — CRT

Java / Flutter разработчик — удалёнка/гибрид (Москва) — GEOMAX

➡️ Еще больше топовых вакансий — в нашем канале Java jobs
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🫡 Один и тот же запрос к AI можно выполнить двумя способами — и получить совершенно разный результат.

1️⃣ способ — просто попросить написать код. Модель может сгенерировать рабочее решение, но именно на этапе проверки часто всплывают пропущенные edge case’ы, ошибки обработки или проблемы с тестами.

2️⃣ способ — дать агенту цикл Think → Act → Observe. Он не останавливается после первой попытки: планирует действия, проверяет результат и, если находит ошибку, исправляет её и пробует снова.

Самое интересное, что разница здесь не столько в модели Claude, GPT или другая LLM могут быть одинаковыми. Разницу создаёт инженерная система вокруг них.

📅 Именно это разберём 23 июля в 19:00 (МСК) на бесплатном вебинаре с Алексеем Жиряковым (Executive Director в Сбере, GenAI Data Platform, ex-CTO Stream и KION).

На живом демо покажем, как один и тот же запрос работает без агентной системы и с ней 🔥

🔗 Регистрация

🏃‍♀️ Proglib Academy
Please open Telegram to view this post
VIEW IN TELEGRAM
🌐 Зачем нужен CDN и как он работает

Когда пользователь из Сиднея открывает ваш сайт, его запрос летит на сервер в Германии и обратно. Это ~300 мс только на «дорогу» — и это для каждого изображения, шрифта, JS-файла.

CDN (Content Delivery Network / Сеть доставки контента) решает эту проблему в лоб: вместо одного сервера — тысячи точек по всему миру. Пользователь получает файлы с ближайшей к нему ноды, а не с вашего origin-сервера.

🔹 Origin и Edge

В архитектуре с CDN появляются два новых понятия:

Origin Server (Главный сервер): это ваш настоящий сервер, где крутится Spring Boot, лежит база данных и хранятся оригиналы всех файлов (например, в Amazon S3).

Edge Servers (Граничные серверы / Точки присутствия - PoP): это тысячи серверов CDN-провайдера (например, Cloudflare или Akamai), раскиданные по всему земному шару: в Сиднее, Токио, Нью-Йорке, Лондоне, Москве.

🔹 Как работает кэш

Первый запрос к конкретному файлу всё равно идёт до origin. CDN его скачивает, кэширует у себя и отдаёт пользователю. Все последующие запросы на тот же файл edge-сервер обрабатывает сам, не трогая ваш бэкенд. Это называется cache hit.

🔹 Что кладем в CDN

CDN идеально подходит для статического контента:

— Картинки, видео, аудио.
— Скомпилированные файлы JavaScript и CSS.
— Шрифты.

CDN не подходит для динамического контента:

— Корзина товаров.
— Приватные данные пользователя.
(Запросы к API /api/v1/users/me должны идти напрямую на ваш сервер, минуя кэш CDN).

🔹 Защита от DDoS

Современные CDN (тот же Cloudflare) - это не просто кэш. Это гигантский щит.

Если хакеры решат «положить» ваш сайт и отправят миллион запросов в секунду, этот удар примут на себя серверы CDN. Их пропускная способность измеряется терабитами. Они отфильтруют «мусорный» трафик, и ваш маленький Origin-сервер даже не заметит атаки.

🔹 Побочные эффекты

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

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

Безопасность: CDN скрывает реальный IP-адрес вашего сервера и защищает от DDoS-атак.

══════ Навигация ══════
ВакансииЗадачиСобесы

🐸 Библиотека джависта

#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍71👏1