Ссылка на видео:
Ответы на вопросы
Вопрос про OpenShift (что такое ingress, egress, sidecar)
1. Что такое OpenShift?
OpenShift — это Kubernetes-платформа от Red Hat с дополнительными функциями для управления жизненным циклом приложений. Она предоставляет разработчикам и DevOps-инженерам удобную среду для развертывания, масштабирования и управления контейнеризированными приложениями.
Ключевые особенности:
- Построен поверх Kubernetes
- Встроенные CI/CD пайплайны (через Jenkins или Tekton)
- Управление правами доступа (RBAC)
- Поддержка шаблонов приложений (OpenShift Templates, Helm Charts)
- Web UI и CLI (
oc
)
Что такое Ingress?
Ответ:
Ingress — это объект Kubernetes (и OpenShift), который управляет входящим HTTP(S)-трафиком в кластер. Он определяет правила маршрутизации запросов к различным сервисам внутри кластера.
Пример использования:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- host: example.com
http:
paths:
- path: /app
pathType: Prefix
backend:
service:
name: my-service
port:
number: 80
Что такое Egress?
Ответ:
Egress — это термин, обозначающий исходящий трафик из подов наружу (в Интернет или другие внешние ресурсы). В OpenShift можно управлять Egress-трафиком, например, с помощью Egress firewall rules, Egress IPs, или NetworkPolicy, чтобы ограничить или разрешить доступ к внешним адресам.
Что такое Sidecar?
Ответ:
Sidecar — это контейнер, запускаемый в одном поде вместе с основным приложением, дополняющий его функциональность. Это шаблон проектирования в Kubernetes, широко используемый для:
- Логирования
- Проксирования (например, Envoy в Istio)
- Мониторинга (например, Prometheus exporters)
- Кеширования
Пример:
В поде запускается ваше Java-приложение и рядом — sidecar-контейнер с Fluentd для логирования или Istio proxy для трассировки.
Как обеспечить безопасность межсервисных обращений через Keycloak?
Общий подход
Чтобы сервисы безопасно вызывали друг друга, необходимо:
- Аутентифицировать вызывающий сервис
- Проверять токен на принимающей стороне
- Гарантировать, что только авторизованные сервисы могут обращаться к нужным эндпоинтам
Подход с Keycloak
Шаги:
Настройка Realm и Clients:
- Создайте отдельный client для каждого сервиса (например, “service-a”, “service-b”) в режиме confidential.
- Установите grant type: client credentials (для machine-to-machine общения).
Выдача токена:
- Сервис A получает токен от Keycloak через “POST /token” с client_id и client_secret.
- Keycloak возвращает access token (чаще всего в формате JWT).
Валидация токена:
- Сервис B (принимающая сторона) проверяет:
- подпись токена (если JWT)
- срок действия (“exp”)
- “aud” / “azp” (кому выдан токен)
- роли/scopes (если есть)
Передача токена:
- В заголовке “Authorization: Bearer ” при каждом вызове между сервисами.
Что такое JWT и Opaque токены?
JWT (JSON Web Token)
- Самодостаточный токен в формате JSON, закодированный и подписанный.
- Содержит полезную нагрузку (claims), такую как “sub”, “exp”, “scope”, “roles”, “azp”.
- Проверяется локально (нет запроса к Keycloak).
- Пример:
{
"sub": "service-a",
"azp": "service-a",
"exp": 1716409999,
"realm_access": {
"roles": ["service-caller"]
}
}
Плюсы:
- Нет обращения к Keycloak при каждом запросе
- Быстрая валидация
Минусы:
- Нельзя отозвать или немедленно отследить отключение (если нет отдельного механизма)
Opaque token
- Непрозрачный токен (обычно просто UUID), не содержит читаемой информации.
- Требует обратного запроса к Keycloak для валидации через “/introspect” endpoint.
Плюсы:
- Лучше контроль — можно отозвать токен
- Меньший риск утечки данных (в токене нет содержимого)
Минусы:
- Требует сетевого запроса к Keycloak при каждом вызове
- Медленнее
Сценарий | Рекомендация |
---|---|
Внутренние микросервисы, быстрые вызовы | JWT (access token) |
Требуется высокая управляемость (отзыв) | Opaque token + introspection |
Нужна трассировка и аудит | JWT с scopes/roles |
Вопросы по Kafka, offset и offset lag
Что такое Kafka?
Kafka — это распределённая платформа потоковой передачи событий (event streaming platform), разработанная в LinkedIn и переданная Apache Foundation. Она используется для:
- асинхронной коммуникации между микросервисами,
- реалтайм-аналитики,
- журнального хранения событий.
Основные понятия
Topic
- Логическая категория/канал, куда публикуются события.
- Подразумевается, что производители (producers) отправляют события в топик, а потребители (consumers) их читают.
Partition
- Топик разбивается на партиции — физические сегменты данных.
- Каждая партиция — упорядоченный, неизменяемый лог событий.
- Сообщения внутри партиции имеют offset — уникальный номер, по которому происходит чтение.
Зачем нужны партиции?
- Масштабируемость (горизонтальный шардинг)
- Параллельное потребление (каждая партиция читается одним consumer’ом внутри consumer group)
Consumer group
- Группа потребителей, обрабатывающих события вместе.
- Каждая партиция назначается ровно одному потребителю в группе.
- Это означает: N consumers на максимум N партиций — не более.
Партиций | Consumer’ов | Что будет? |
---|---|---|
3 | 3 | Идеально: 1 consumer на 1 партицию |
3 | 2 | Один consumer читает 2 партиции |
3 | 5 | 2 consumer’а будут “бездельничать”, т.к. лишние |
Как связаны партиции и количество consumer’ов?
Число активных consumer’ов в группе не может быть больше числа партиций.
Что такое Offset и Offset Lag?
- Offset — позиция, до которой consumer прочитал сообщения.
- Offset lag — количество непрочитанных сообщений (разница между последним offset’ом в партиции и тем, что прочитал consumer).
Как бороться с Offset Lag?
- Увеличить число партиций
Чтобы больше consumer’ов могли читать параллельно. - Добавить consumer’ов
Но не больше числа партиций! - Убедиться, что обработка сообщений быстрая
Узким местом может быть БД, внешние API и т.д. - Масштабировать горизонтально
— Распределить нагрузку по нескольким нодам. - Использовать batch processing
Вместо обработки по одному сообщению — пакетно (“max.poll.records”). - Увеличить “fetch.min.bytes”, “max.poll.interval.ms”, “session.timeout.ms”
Для оптимизации чтения и избежания ребалансинга.
Сколько должно быть consumer’ов?
- Максимум: = числу партиций
- Обычно: = числу партиций или чуть меньше
- Избыточное количество consumer’ов бесполезно — Kafka назначит одному consumer’у ноль партиций
Вопрос | Ответ |
---|---|
Kafka хранит сообщения? | Да, по времени (retention.ms) или по объёму (retention.bytes) |
Kafka — очередь? | Нет, это лог событий (event log), поддерживает pub/sub и replay |
Kafka масштабируется? | Да, за счёт партиций и кластеров брокеров |
Нужно ACK от consumer’а? | Да, Kafka фиксирует offset только после commit (авто или вручную) |
Нагрузочное тестирование
Что такое нагрузочное тестирование (load testing)?
Нагрузочное тестирование — это вид нефункционального тестирования, при котором проверяется, как система ведёт себя при ожидаемой и повышенной нагрузке. Цель — определить пределы производительности, задержки, стабильность и масштабируемость системы.
Зачем нужно?
- Проверить, выдержит ли система пик нагрузки
- Найти узкие места (база данных, API, кэш)
- Предотвратить сбои в проде
- Определить, сколько пользователей или запросов система может обрабатывать
Виды нагрузочного тестирования
Вид теста | Цель |
---|---|
Load Testing | Проверка работы системы под нормальной и повышенной нагрузкой |
Stress Testing | Проверка системы на пределе, чтобы увидеть, как она ломается |
Spike Testing | Проверка резкого скачка нагрузки (внезапный наплыв трафика) |
Soak Testing (Endurance) | Проверка системы под нагрузкой в течение долгого времени |
Scalability Testing | Оценка, насколько хорошо система масштабируется с ростом нагрузки |
Как проводится нагрузочное тестирование?
Определение целей
- Что мы хотим протестировать? (API, БД, UI, Kafka, Redis)
- Какие метрики важны? (RPS, latency, CPU, memory)
Настройка сценариев
- Эмуляция пользовательского поведения (например, логин ? просмотр ? заказ)
- Задание количества виртуальных пользователей, RPS
Выбор инструментов
- JMeter (графический интерфейс, скрипты)
- Gatling (Scala/Java, кодогенерация)
- k6 (JavaScript-подход, CI-friendly)
- Locust (Python-скрипты)
- Artillery, Tsung, Vegeta, wrk — для CLI/микросервисов
Запуск теста
- Локально, в CI или через Kubernetes
- Снятие метрик (Prometheus, Grafana, Zipkin, OpenTelemetry)
Анализ результатов
- Важные метрики:
- Response Time (P50, P95, P99)
- Throughput (RPS)
- Error rate
- CPU, Memory, Disk I/O
- Kafka lag, Redis latency
Оптимизация
- Балансировка нагрузки
- Кэширование
- Оптимизация SQL-запросов
- Увеличение партиций в Kafka
- Горизонтальное масштабирование
Пример из практики
API обрабатывает 300 RPS, при 500 RPS растёт latency до 3 сек, CPU 100% ? узкое место — синхронные DB-запросы ? решение: кэширование + асинхронная очередь (Kafka).
Общие вопросы о JDK 11, 17, 21
Какие релизы JDK являются LTS?
Ответ:
- Java 11 — LTS (вышел в 2018)
- Java 17 — LTS (вышел в 2021)
- Java 21 — LTS (вышел в 2023)
JDK 11 — ключевые нововведения
Что нового в JDK 11?
- “var” разрешён в лямбда-параметрах
- Новый HTTP Client (стабилен, из incubator в JDK 9)
- “String” API: “isBlank()”, “lines()”, “strip()”, “repeat()”
- “Files.readString()” / “Files.writeString()”
- Удаление модулей (JavaFX, CORBA, WebStart)
Что такое ZGC и появился ли он в JDK 11?
Ответ: Да. ZGC — экспериментальный низколатентный сборщик мусора для больших heap (до терабайтов), с паузами <10 мс.
JDK 17 — основные изменения
Какие новые возможности добавлены в Java 17?
- Sealed classes (final для наследования):
public sealed class Shape permits Circle, Square {}
- Pattern matching for switch (preview) — упрощение “switch” по типам
- New “record” enhancements
- Новый GC: G1 улучшен, ZGC стабилизирован
- Удаление RMI Activation, Applet API, Security Manager (deprecate)
- JEP 356: Enhanced Pseudo-Random Number Generators
JDK 21 — нововведения и стабилизации
Что было стабилизировано в JDK 21?
- Virtual Threads (JEP 444) — масштабируемые lightweight-потоки
- Pattern Matching for “switch” (JEP 441) — полная поддержка
- Record Patterns (JEP 440) — распаковка вложенных структур
- Sequenced Collections (JEP 431) — “SequencedSet”, “SequencedMap” — предсказуемый порядок элементов
Что такое virtual threads?
- Это user-mode потоки (на “java.lang.Thread”), исполняемые в ForkJoinPool
- Облегчают реализацию конкурентных REST-сервисов без использования Reactive stack
Чем отличаются платформенные потоки от виртуальных?
Платформенный поток | Виртуальный поток | |
---|---|---|
Управляется | ОС (kernel thread) | JVM (user thread) |
Вес | Тяжёлый | Лёгкий (~few KB stack) |
Кол-во одновременно | Ограничено | Сотни тысяч возможно |
Как использовать виртуальные потоки с “ExecutorService”?
var executor = Executors.newVirtualThreadPerTaskExecutor();
executor.submit(() -> System.out.println("Hello from virtual thread"));
Какие GC появились или стабилизированы?
- ZGC: Java 11 — experimental, Java 15+ — стабильный
- Shenandoah: С JDK 17 — включён по умолчанию в некоторых билдах
- G1: Постоянно оптимизируется, остаётся дефолтным
Виртуальные потоки в Java
Что такое виртуальные потоки?
Virtual threads (JEP 444, Java 21) — это легковесные потоки, управляемые JVM, а не операционной системой. Они позволяют запускать миллионы конкурентных задач без перегрузки системы.
- Создаются быстро
- Имеют низкие накладные расходы
- Идеальны для I/O-bound задач (например, HTTP-запросов, JDBC)
Почему это важно для HTTP?
Обычные (платформенные) потоки ограничивают масштабируемость сервера:
- У Tomcat, Jetty и других серверов есть thread pool — обычно ограниченный (~200 потоков)
- Если каждый HTTP-запрос блокирует поток (ожидая БД, стороннего API), то масштаб ограничен
Виртуальные потоки снимают это ограничение: можно обрабатывать десятки тысяч запросов, даже если каждый из них блокирующий.
Можно ли использовать виртуальные потоки с Tomcat?
По умолчанию — нет.
Apache Tomcat (даже 10.1+) работает на платформенных потоках. Он использует “ExecutorService”, в котором работают обычные “java.lang.Thread”.
Можно — через кастомный “Executor”
Начиная с Java 21, можно внедрить виртуальные потоки вручную:
Executor executor = Executors.newVirtualThreadPerTaskExecutor();
Connector connector = new Connector();
connector.getProtocolHandler().setExecutor(executor);
Но:
- Tomcat неофициально поддерживает virtual threads
- Не всё совместимо (некоторые filters/servlets могут быть не thread-safe)
- Поддержка может появиться официально позднее (обсуждается в Apache Tomcat mailing list)
Где лучше применять Virtual Threads уже сейчас?
- Spring Boot 3 + Undertow/Jetty: легче внедрить виртуальные потоки
- Micronaut / Helidon Nima / Quarkus Loom: экспериментальная или полноценная поддержка
- Самописные HTTP-серверы с “HttpServer” из JDK:
HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);
server.createContext("/", exchange -> {
Thread.startVirtualThread(() -> {
// Обработка запроса
exchange.sendResponseHeaders(200, 0);
exchange.getResponseBody().write("Hello".getBytes());
});
});
Пример: Spring Boot + Virtual Threads (на Undertow)
@Bean
public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> virtualThreadCustomizer() {
return factory -> {
if (factory instanceof UndertowServletWebServerFactory undertow) {
undertow.addBuilderCustomizers(builder ->
builder.setWorkerThreads(100_000) // Нереально много, т.к. это виртуальные потоки
);
}
};
}
И включить в “application.yml”:
server:
undertow:
threads:
worker: 100000
Вывод
Платформенные потоки | Виртуальные потоки | |
---|---|---|
Уровень управления | ОС (kernel threads) | JVM (user-mode threads) |
Задержки на I/O | Блокируют поток | Не блокируют ресурсы |
Масштабируемость | ~1000 потоков | ~1 000 000+ |
Поддержка в Tomcat | Нет (только вручную) | Экспериментально |
Поддержка в Netty | Нет (лучше использовать reactive) | — |
Вопросы по многопоточности и executorservice ам
Базовые вопросы
Что такое поток в Java?
Ответ:
Поток (thread) — это наименьшая единица исполнения в программе. В Java каждый поток реализуется через “java.lang.Thread” и выполняется независимо от других потоков.
Как создать и запустить поток?
Ответ:
Thread thread = new Thread(() -> System.out.println("Hello"));
thread.start();
Что такое race condition?
Ответ:
Ситуация, когда два потока обращаются к одной переменной и порядок их выполнения влияет на результат. Решается через синхронизацию (“synchronized”, “Lock”, атомарные переменные).
Какие проблемы решает “ExecutorService”?
Ответ:
- Повторное использование потоков (thread pooling)
- Управление количеством потоков
- Планирование и контроль задач
- Асинхронное выполнение с получением результата (“Future”, “CompletableFuture”)
Что такое “ExecutorService”?
Ответ:
Интерфейс из “java.util.concurrent”, представляющий пул потоков и методы для отправки задач (“submit”, “execute”, “invokeAll”, “shutdown” и др.).
Чем отличаются “execute()” и “submit()”?
Метод | Возвращает | Обработка ошибок |
---|---|---|
execute(Runnable) | void | Исключения могут потеряться |
submit(Runnable) | Future<?> | Можно обработать результат и исключения |
Что делает “shutdown()” и “shutdownNow()”?
- “shutdown()” — инициирует корректное завершение, не принимает новые задачи, завершает текущие.
- “shutdownNow()” — прерывает текущие потоки, возвращает список задач, которые не начали выполнение.
Как реализовать пул из 10 потоков?
ExecutorService executor = Executors.newFixedThreadPool(10);
Как получить результат выполнения задачи?
Future<Integer> future = executor.submit(() -> 1 + 1);
Integer result = future.get(); // блокирующий вызов
Что такое “Callable”?
Интерфейс, аналогичный “Runnable”, но:
- Возвращает значение
- Может выбрасывать checked-исключения
Чем отличается “Future” от “CompletableFuture”?
“Future” | “CompletableFuture” | |
---|---|---|
Асинхронный API | Нет | Да (“thenApply”, “thenCompose”) |
Блокирующий “get()” | Да | Можно избежать |
Комбинирование задач | Нет | Да |
Как работают виртуальные потоки с “ExecutorService”?
ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
executor.submit(() -> {
// lightweight thread
});
Как избежать “ThreadPoolExecutor” saturation?
- Ограничить очередь (например, “ArrayBlockingQueue”)
- Добавить RejectedExecutionHandler
- Мониторить метрики (“activeCount”, “queueSize”)
Какие есть типы пулов в “Executors”?
Метод | Описание |
---|---|
newFixedThreadPool(n) | Постоянное число потоков |
newCachedThreadPool() | Динамический пул, без ограничений |
newSingleThreadExecutor() | Один поток — все задачи последовательно |
newScheduledThreadPool(n) | Запуск по таймеру |
Executors.newVirtualThreadPerTaskExecutor() | Virtual threads (Java 21+) |
Практические вопросы распределенным системам
Как приложение на Spring Boot валидирует Access Token, выданный Keycloak?
JWT Access Token (по умолчанию в Keycloak)
Spring Boot валидирует JWT локально, без запроса в Keycloak.
Механизм:
- Токен приходит в заголовке “Authorization: Bearer “
- Spring Security (через “OAuth2ResourceServer”) извлекает токен
- Проводится проверка подписи с использованием публичного ключа из Keycloak (“/realms/{realm-name}/protocol/openid-connect/certs”)
- Проверяются:
- “exp” — срок действия
- “aud”, “iss” — валидность источника
- “scope”, “roles”, “permissions”
Конфигурация:
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://keycloak.example.com/realms/myrealm
Альтернатива — opaque token:
- Валидация через introspection endpoint
- Нужно “POST”-запрос к Keycloak: “/protocol/openid-connect/token/introspect”
- Медленнее, но управляемее
Почему чтение из RAM быстрее, чем из SSD?
Причина: уровни иерархии памяти
Уровень | Пример | Скорость доступа |
---|---|---|
Регистры CPU | — | ~1 наносекунда |
Кэш L1/L2/L3 | CPU-кэш | 1–10 наносекунд |
Оперативная память (RAM) | DDR4/DDR5 | ~100 наносекунд |
SSD (NVMe) | Samsung 980 Pro | ~100 микросекунд |
HDD | — | ~5–10 миллисекунд |
Почему так:
- RAM — энергозависимая и адресуется напрямую
- SSD — работает через контроллер, поддерживает I/O очереди, требует больше операций (чтение страниц, wear leveling, garbage collection)
Пример:
Чтение из RAM — прямой доступ по адресу
Чтение с SSD — обращение к файловой системе, драйверу, контроллеру
Что такое партиционирование в БД?
Определение:
Партиционирование — это разбиение таблицы на несколько частей (partition) по заданному критерию (например, по дате, ID, региону).
Цель:
- Ускорить поиск и агрегацию
- Ограничить область данных для запросов
- Улучшить масштабируемость и управляемость
Виды партиционирования:
Тип | Пример | Подходит для |
---|---|---|
Range | WHERE date >= '2023-01-01' | Временные данные |
List | region IN ('RU', 'US') | Разные регионы |
Hash | id % N | Равномерное распределение |
Composite | date + region | Комбинация стратегий |
Пример в PostgreSQL:
CREATE TABLE orders (
id SERIAL,
region TEXT,
created_at DATE
) PARTITION BY RANGE (created_at);
CREATE TABLE orders_2023 PARTITION OF orders
FOR VALUES FROM ('2023-01-01') TO ('2024-01-01');
Преимущества:
- Query pruning — оптимизатор сам выбирает нужную партицию
- Меньше индексов на каждую часть
- Упрощённое удаление старых данных (удаляется партиция)
Документирование API
Документирование API — важная часть разработки, особенно в микросервисной архитектуре. Ниже — краткий и структурированный гайд по способам документирования REST API, подходящий для собеседования Java-разработчика:
Цели документации API
- Упростить использование API другими командами и клиентами
- Обеспечить прозрачность контрактов
- Облегчить тестирование и интеграцию
- Поддерживать единый формат и описание версий
Основные подходы
a. OpenAPI / Swagger (де-факто стандарт)
- YAML/JSON спецификация, описывающая эндпоинты, методы, параметры, модели
- Используется для генерации:
- Документации (Swagger UI)
- Клиентов (OpenAPI Generator)
- Серверных заглушек
Инструменты:
- Springdoc OpenAPI (“springdoc-openapi-ui”)
- Swagger-Core (ручная аннотация)
- Stoplight, Redocly (для ручной редакции и визуализации)
Пример аннотаций с Spring Boot:
@Operation(summary = "Получить заказ по ID")
@GetMapping("/orders/{id}")
public OrderDto getOrder(@PathVariable Long id) { ... }
b. Javadoc для внутренних API
- Подходит для SDK, client-libraries
- Используется “/ … */” над методами и классами
- Генерируется через “javadoc” CLI или IDE
c. Asciidoc / Markdown + REST Docs
- Позволяет писать документацию вручную или полуавтоматически
- Spring REST Docs генерирует snippets из интеграционных тестов
Инструменты и стек
Название | Назначение |
---|---|
Swagger UI | Интерфейс для просмотра и тестирования API |
springdoc-openapi | Генерация OpenAPI из кода Spring Boot |
Postman / Insomnia | Просмотр и экспорт коллекций API |
Spring REST Docs | Генерация документации на основе тестов |
Redoc | Современная визуализация OpenAPI-доков |
Stoplight Studio | Редактор OpenAPI |
Хорошая документация включает:
- Описание каждого эндпоинта (метод, URL, описание)
- Параметры запроса, заголовки, тело
- Формат ответа (с примерами)
- Ошибки и коды статусов
- Безопасность (auth, scopes)
- Примеры cURL / HTTP-запросов
Советы
- Храните “openapi.yaml” в репозитории рядом с кодом
- Включайте документацию в CI
- Для публичных API — публикуйте с Redoc или SwaggerHub
- Поддерживайте версионирование API (“/v1/”, “/v2/”)
Различия между системами сборки Maven и Gradle
Maven vs Gradle: ключевые различия
Критерий | Maven | Gradle |
---|---|---|
Язык конфигурации | XML (pom.xml ) | Groovy или Kotlin DSL (build.gradle , build.gradle.kts ) |
Скорость сборки | Медленнее (особенно при больших проектах) | Быстрее благодаря incremental build и daemon |
Гибкость | Ограниченная, строгое дерево фаз | Очень гибкий, можно писать произвольную логику сборки |
Структура сборки | Стандартная и предсказуемая | Более гибкая, но требует дисциплины |
Инструменты и плагины | Огромное количество плагинов | Богатый набор, легко пишутся кастомные плагины |
Декларативность | Полностью декларативный | Поддерживает декларативный и императивный подход |
Кэширование | Нет | Есть (в том числе remote build cache) |
Зависимости | Определяются через <dependency> | Определяются как implementation 'group:artifact:version' |
Интеграция с IDE | Отличная (особенно с IntelliJ) | Также отличная, но иногда нужна ручная настройка |
Test lifecycle | Жёстко заданная модель фаз (compile, test, package и т.д.) | Можно задавать произвольные таски и зависимости |
Многомодульность | Поддерживается, но может быть громоздкой | Легче реализуется, особенно для больших проектов |
Maven — когда использовать?
Выбираем Maven, если:
- Требуется стабильность и читаемость конфигурации
- Проект простой или стандартный
- Команда уже привыкла к Maven
- Не нужно кастомных шагов сборки
Gradle — когда использовать?
Выбираем Gradle, если:
- Большой монорепозиторий или сложные зависимости
- Нужна высокая производительность сборки
- Много кастомных шагов и скриптов
- Используется Kotlin DSL (например, в Android проектах)
Рекомендованная литература и статьи:
Java и многопоточность
- “Java Concurrency in Practice” — Brian Goetz
Фундаментальная книга по потокам,
ExecutorService
,synchronized
,volatile
, и многопоточному проектированию.
- “Modern Java in Action” — Raoul-Gabriel Urma
Покрывает лямбды, стримы,
CompletableFuture
, virtual threads (в последних изданиях).
- “Effective Java” (3rd edition) — Joshua Bloch
Паттерны и лучшие практики, включая работу с потоками, коллекциями и API-дизайном.
Spring Boot и безопасность
- “Spring Security in Action” — Laurentiu Spilca
Полное руководство по настройке OAuth2, JWT, ресурсных серверов, интеграции с Keycloak.
- “Spring Boot: Up and Running” — Mark Heckler
Введение и практика, включая REST, WebFlux, Actuator, Docker.
Kafka и распределённые системы
- “Kafka: The Definitive Guide” — Neha Narkhede
Практика Kafka, топики, партиции, offset lag, продюсеры и консьюмер-группы.
- “Designing Data-Intensive Applications” — Martin Kleppmann
MUST READ: транзакции, репликация, шардирование, потоковые системы.
Документирование и архитектура API
- “RESTful Web APIs” — Leonard Richardson
Архитектурные подходы, HATEOAS, версионирование, контракты и статус-коды.
- “API Design Patterns” — JJ Geewax (Google)
Подробности по REST, GraphQL, OpenAPI, и практикам построения устойчивых API.
Системные знания и DevOps
- “The Linux Command Line” — William E. Shotts Основы работы с Linux, процессы, память, системные вызовы.
- “Kubernetes in Action” / “OpenShift in Action” Для понимания кластеров, ingress/egress, sidecar, CI/CD, и сервисов.
Статьи и официальные источники
OpenAPI и документация:
Keycloak:
- https://www.keycloak.org/docs/latest/server_admin/
- https://youtu.be/uq2I9z_ZB6Q
- Securing Applications with Spring Boot and Keycloak
Virtual Threads:
Java 11–21:
- https://openjdk.org/projects/jdk/11/
- https://openjdk.org/projects/jdk/17/
- https://openjdk.org/projects/jdk/21/
- https://proselyte.net/java21-usage/
Kafka:
Нагрузочное тестирование: