Spring Boot tip:
Используй CommandLineRunner, если нужно выполнить код сразу после того, как приложение полностью поднялось и контекст инициализирован.
CommandLineRunner — это интерфейс Spring Boot, который позволяет запускать любую логику при старте приложения.
Удобно для:
заполнения базы начальными данными,
проверки состояния сервисов,
инициализации внешних ресурсов.
Пример:
Такой класс автоматически выполнится один раз при запуске Spring Boot.
👉   Java Portal
Используй CommandLineRunner, если нужно выполнить код сразу после того, как приложение полностью поднялось и контекст инициализирован.
CommandLineRunner — это интерфейс Spring Boot, который позволяет запускать любую логику при старте приложения.
Удобно для:
заполнения базы начальными данными,
проверки состояния сервисов,
инициализации внешних ресурсов.
Пример:
@Component
public class StartupRunner implements CommandLineRunner {
@Override
public void run(String... args) {
System.out.println("App started! Further setup");
}
}
Такой класс автоматически выполнится один раз при запуске Spring Boot.
Please open Telegram to view this post
    VIEW IN TELEGRAM
  👍4❤2
  Тебе не нужно дробить приложение на 20 репозиториев и 15 сервисов, чтобы получить модульность.
Это можно спокойно реализовать внутри грамотно спроектированного модульного монолита.
1. Разделяй модули по функциональным доменам.
Пример: пользователи, платежи, уведомления, отчёты.
Каждый модуль — это свой пакет со своими сущностями, сервисами и бизнес-логикой.
2. Определи чёткие интерфейсы между модулями.
Один модуль не должен знать внутренние классы другого.
Общай их через интерфейсы или внутренние события (например, Spring Events).
Так сохраняется слабое связывание и высокая связность.
3. Избегай циклических зависимостей.
Если модуль A зависит от B, убедись, что B никогда не зависит от A.
Разрывай такие циклы с помощью интерфейсов, dependency injection или событий.
4. Придерживайся принципа внутренних слоёв.
В каждом модуле разделяй внутренние части (entities, repositories, services) и то, что наружу (controllers, DTO, API).
5. Рассмотри использование Spring Modulith (для Java/Kotlin).
Он не заставляет переходить на микросервисы, но даёт инструменты для организации модулей, проверки зависимостей и документирования архитектуры.
6. Опционально: подумай о доменных событиях.
Они помогают масштабировать модульность, не ломая монолит.
И если потом решишь вынести модуль отдельно — половина работы уже сделана.
Модульность зависит не от размера системы, а от чёткости её границ.
Хорошо спроектированный модульный монолит может быть гораздо проще в поддержке, чем хаотичная сеть микросервисов.
👉   Java Portal
Это можно спокойно реализовать внутри грамотно спроектированного модульного монолита.
1. Разделяй модули по функциональным доменам.
Пример: пользователи, платежи, уведомления, отчёты.
Каждый модуль — это свой пакет со своими сущностями, сервисами и бизнес-логикой.
2. Определи чёткие интерфейсы между модулями.
Один модуль не должен знать внутренние классы другого.
Общай их через интерфейсы или внутренние события (например, Spring Events).
Так сохраняется слабое связывание и высокая связность.
3. Избегай циклических зависимостей.
Если модуль A зависит от B, убедись, что B никогда не зависит от A.
Разрывай такие циклы с помощью интерфейсов, dependency injection или событий.
4. Придерживайся принципа внутренних слоёв.
В каждом модуле разделяй внутренние части (entities, repositories, services) и то, что наружу (controllers, DTO, API).
5. Рассмотри использование Spring Modulith (для Java/Kotlin).
Он не заставляет переходить на микросервисы, но даёт инструменты для организации модулей, проверки зависимостей и документирования архитектуры.
6. Опционально: подумай о доменных событиях.
Они помогают масштабировать модульность, не ломая монолит.
И если потом решишь вынести модуль отдельно — половина работы уже сделана.
Модульность зависит не от размера системы, а от чёткости её границ.
Хорошо спроектированный модульный монолит может быть гораздо проще в поддержке, чем хаотичная сеть микросервисов.
Please open Telegram to view this post
    VIEW IN TELEGRAM
  👍5❤3
  Совет по Spring Boot:
используй spring-boot-starter-logging (на Logback) для логирования — он уже подключён по умолчанию.
spring-boot-starter-logging уже включён во большинство стартеров, например spring-boot-starter-web, spring-boot-starter-data-jpa и т.д.
Можно настраивать уровни логирования, отредактировав application.yml:
Чтобы изменить формат логов и политику ротации, создай файл logback-spring.xml в каталоге src/main/resources.
👉   Java Portal
используй spring-boot-starter-logging (на Logback) для логирования — он уже подключён по умолчанию.
spring-boot-starter-logging уже включён во большинство стартеров, например spring-boot-starter-web, spring-boot-starter-data-jpa и т.д.
Можно настраивать уровни логирования, отредактировав application.yml:
logging:
level:
root: INFO
com.myapp: DEBUG
Чтобы изменить формат логов и политику ротации, создай файл logback-spring.xml в каталоге src/main/resources.
Please open Telegram to view this post
    VIEW IN TELEGRAM
  👍7
  This media is not supported in your browser
    VIEW IN TELEGRAM
  ChartDB это опенсорс-инструмент для работы с SQL-базами данных через визуальный интерфейс.
Что умеет:
✓ интерактивная диаграмма со всеми таблицами и связями
✓ можно скачать схему как PNG-картинку
✓ поддерживает MySQL, PostgreSQL, SQLite и другие
→ app.chartdb.io
👉   Java Portal
Что умеет:
✓ интерактивная диаграмма со всеми таблицами и связями
✓ можно скачать схему как PNG-картинку
✓ поддерживает MySQL, PostgreSQL, SQLite и другие
→ app.chartdb.io
Please open Telegram to view this post
    VIEW IN TELEGRAM
  ❤5
  Spring Boot: можно выполнять задачи через фиксированные интервалы без настройки Quartz или внешних планировщиков.
✅  Добавь 
✅  Используй 
👉   Java Portal
@EnableScheduling в любой конфигурационный или основной класс приложения:@SpringBootApplication
@EnableScheduling
public class MainApp { }
@Scheduled для метода:@Component
public class Scheduler {
@Scheduled(fixedRate = 5000)
public void executeTask() {
...
}
}
@EnableScheduling активирует механизм планирования, а @Scheduled задаёт частоту выполнения метода (fixedRate = 5000 — каждые 5 секунд).Please open Telegram to view this post
    VIEW IN TELEGRAM
  ❤1
  У тебя есть 3 сервера. Приходит 100 запросов. Как их распределить? Вот возможные варианты:
Алгоритмы балансировки нагрузки
🔸 Round Robin (циклический)
- Запрос 1 —> на сервер A
- Запрос 2 —> на сервер B
- Запрос 3 —> на сервер C
- Запрос 4 —> снова на сервер A
- И так по кругу бесконечно
Когда использовать: все сервера одинаковые, запросы примерно равны по времени обработки. Самый простой вариант.
🔸 Weighted Round Robin (взвешенный циклический)
- Сервер A: 4 ядра, вес 4
- Сервер B: 8 ядер, вес 8
- Сервер C: 4 ядра, вес 4
- Из каждых 16 запросов: A получает 4, B — 8, C — 4
Когда использовать: мощности серверов разные, нужно распределять нагрузку пропорционально.
🔸 Least Connections (наименьшее количество соединений)
- Сервер A: 50 активных соединений
- Сервер B: 30 активных соединений
- Сервер C: 45 активных соединений
- Следующий запрос уходит на сервер B (у него меньше всего соединений)
Когда использовать: запросы обрабатываются разное время, есть долгоживущие соединения, например WebSocket.
🔸 Weighted Least Connections (взвешенный по соединениям)
- Сервер A: 50 соединений, 4 ядра → соотношение 12.5
- Сервер B: 30 соединений, 8 ядер → соотношение 3.75
- Сервер C: 45 соединений, 4 ядра → соотношение 11.25
- Следующий запрос идёт на сервер B (самое низкое соотношение)
Когда использовать: сервера разной мощности, при этом соединения держатся долго.
🔸 IP Hash (хеш по IP)
- IP пользователя: 192.168.1.100
- Этот IP хешируется и всегда маршрутизируется на сервер B
- Один и тот же пользователь всегда попадает на один и тот же сервер
Когда использовать: нужна привязка сессии к конкретному серверу, нет общего session storage. Sticky sessions.
🔸 Least Response Time (наименьшее время отклика)
- Сервер A: средний отклик 200 мс
- Сервер B: 150 мс
- Сервер C: 300 мс
- Следующий запрос уходит на сервер B (самый быстрый)
Когда использовать: производительность серверов разная, например, для чтения из реплик БД с разным lag.
🔸 Random (случайное распределение)
- Просто выбирается случайный сервер
- Ничего отслеживать не нужно
- На больших масштабах работает удивительно неплохо
Когда использовать: простые распределённые системы, stateless-сервисы, когда учёт состояния не оправдан.
В большинстве продакшн-систем хорошо себя показывает вариант Least Connections с весами.
👉   Java Portal
Алгоритмы балансировки нагрузки
- Запрос 1 —> на сервер A
- Запрос 2 —> на сервер B
- Запрос 3 —> на сервер C
- Запрос 4 —> снова на сервер A
- И так по кругу бесконечно
Когда использовать: все сервера одинаковые, запросы примерно равны по времени обработки. Самый простой вариант.
- Сервер A: 4 ядра, вес 4
- Сервер B: 8 ядер, вес 8
- Сервер C: 4 ядра, вес 4
- Из каждых 16 запросов: A получает 4, B — 8, C — 4
Когда использовать: мощности серверов разные, нужно распределять нагрузку пропорционально.
- Сервер A: 50 активных соединений
- Сервер B: 30 активных соединений
- Сервер C: 45 активных соединений
- Следующий запрос уходит на сервер B (у него меньше всего соединений)
Когда использовать: запросы обрабатываются разное время, есть долгоживущие соединения, например WebSocket.
- Сервер A: 50 соединений, 4 ядра → соотношение 12.5
- Сервер B: 30 соединений, 8 ядер → соотношение 3.75
- Сервер C: 45 соединений, 4 ядра → соотношение 11.25
- Следующий запрос идёт на сервер B (самое низкое соотношение)
Когда использовать: сервера разной мощности, при этом соединения держатся долго.
- IP пользователя: 192.168.1.100
- Этот IP хешируется и всегда маршрутизируется на сервер B
- Один и тот же пользователь всегда попадает на один и тот же сервер
Когда использовать: нужна привязка сессии к конкретному серверу, нет общего session storage. Sticky sessions.
- Сервер A: средний отклик 200 мс
- Сервер B: 150 мс
- Сервер C: 300 мс
- Следующий запрос уходит на сервер B (самый быстрый)
Когда использовать: производительность серверов разная, например, для чтения из реплик БД с разным lag.
- Просто выбирается случайный сервер
- Ничего отслеживать не нужно
- На больших масштабах работает удивительно неплохо
Когда использовать: простые распределённые системы, stateless-сервисы, когда учёт состояния не оправдан.
В большинстве продакшн-систем хорошо себя показывает вариант Least Connections с весами.
Please open Telegram to view this post
    VIEW IN TELEGRAM
  👍5
  В Spring Boot аннотация 
Тесты выполняются с использованием встроенной базы данных, например H2, а после каждого теста все транзакции автоматически откатываются.
👉   Java Portal
@DataJpaTest используется для изолированного тестирования JPA-репозиториев.@DataJpaTest поднимает только JPA-слой, не загружая весь контекст приложения.Тесты выполняются с использованием встроенной базы данных, например H2, а после каждого теста все транзакции автоматически откатываются.
Please open Telegram to view this post
    VIEW IN TELEGRAM
  👍3
  29 октября(уже сегодня!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью по System Design.
Как это будет:
📂  Дмитрий Дорофеев, TeamLead в американском FitTech Truv Inc, ex-VK, будет задавать реальные вопросы и задачи разработчику-добровольцу
📂  Дмитрий будет комментировать каждый ответ респондента, чтобы дать понять, чего от вас ожидает собеседующий на интервью
📂  В конце можно будет задать любой вопрос Дмитрию
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot
Реклама.
О рекламодателе.
Как это будет:
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot
Реклама.
О рекламодателе.
Please open Telegram to view this post
    VIEW IN TELEGRAM
  Maven Plugin Tip — DepClean 
DepClean автоматически чистит дерево зависимостей в Java-проектах. Он удаляет все зависимости, которые прописаны в дереве, но при сборке на самом деле не нужны.🔥 
https://github.com/ASSERT-KTH/depclean
👉   Java Portal
DepClean автоматически чистит дерево зависимостей в Java-проектах. Он удаляет все зависимости, которые прописаны в дереве, но при сборке на самом деле не нужны.
https://github.com/ASSERT-KTH/depclean
Please open Telegram to view this post
    VIEW IN TELEGRAM
  ❤5👍2🔥2
  Санкт-Петербург, 13 ноября в 19:00
Разберём архитектуру облачной записи встреч, наведём порядок в API и покажем, как простые решения спасают сервисы.
В программе:
📌 Как не упустить важное: архитектура облачной записи и конспектирования видеовстреч в Телемосте — Илья Григорьев, разработчик бэкенда Телемоста.
📌 Укрощение API: процессы и инструменты, которые действительно работают — Никита Ломакин, разработчик в команде Техплатформы.
📌 Как мы закапывали звездолёт: почему важно отстаивать простоту на архревью — Артемий Коцюбенко, разработчик протокольных сервисов Почты.
Команда Яндекс 360 работает с нагрузками >1.000.000+ RPS и создает продукты которыми пользуются 95+ млн человек каждый месяц — Диск, Почта, Телемост, Мессенджер и другие.
🍻А после докладов вас будут ждать афтепати и нетворкинг!
Регистрируйтесь по ссылке
Please open Telegram to view this post
    VIEW IN TELEGRAM
  ❤2
  Векторные базы данных простыми словами
Представь, у тебя есть 10 000 описаний товаров. Пользователь ищет "удобная уличная мебель".
Обычная база данных:
Ищет точные совпадения слов
Находит товары с "удобная" ИЛИ "уличная" ИЛИ "мебель"
Пропускает "уютные кресла для террасы", хотя это то же самое
Ключевые слова — тупой способ поиска
Векторная база данных:
Превращает запрос в набор чисел, отражающих смысл: [0.2, 0.8, 0.1, 0.9, ...]
Каждое описание товара тоже превращается в такие числа
Сравнивает эти "векторы" и ищет похожие по смыслу
Находит "уютные кресла для террасы", потому что векторы похожи
Смысловой поиск — умный поиск
Как это работает
Шаг 1. Превращаем текст в векторы (массивы чисел)
"comfortable chair" → [0.2, 0.7, 0.1, 0.4, ...]
"cozy seat" → [0.3, 0.8, 0.2, 0.5, ...]
Похожие фразы → похожие числа
Это делает AI-модель, например OpenAI embeddings
Шаг 2. Храним векторы
В обычной БД хранят текст
В векторной — массив чисел для каждого объекта
Индексируют их, чтобы быстро искать по схожести
Оптимизировано под "найди похожие", а не "найди точное"
Шаг 3. Ищем по схожести
Запрос: "outdoor furniture"
Превращается в [0.3, 0.6, 0.2, 0.8, ...]
Система ищет ближайшие векторы (через cosine similarity)
Результаты сортируются по степени похожести
Где это используется:
- Поиск товаров, который понимает смысл, а не только слова
- Поиск по документации, который находит релевантные ответы
- Рекомендательные системы
- Чатботы, ищущие похожие вопросы
- Обнаружение аномалий
Популярные векторные базы
Pinecone = управляемая, простая, но дорогая
Weaviate = опенсорс, с кучей функций
Milvus = быстрая и масштабируемая, но сложная
pgvector = расширение для Postgres, простое и удобное
Qdrant = быстрая, написана на Rust
Спорная, но практичная мысль
В большинстве проектов тебе не нужна отдельная векторная база.
Начни с Postgres + pgvector = этого хватает, пока у тебя меньше 1 миллиона векторов.
Когда масштаб вырастет, тогда уже смотри в сторону специализированных решений.
👉   Java Portal
Представь, у тебя есть 10 000 описаний товаров. Пользователь ищет "удобная уличная мебель".
Обычная база данных:
Ищет точные совпадения слов
Находит товары с "удобная" ИЛИ "уличная" ИЛИ "мебель"
Пропускает "уютные кресла для террасы", хотя это то же самое
Ключевые слова — тупой способ поиска
Векторная база данных:
Превращает запрос в набор чисел, отражающих смысл: [0.2, 0.8, 0.1, 0.9, ...]
Каждое описание товара тоже превращается в такие числа
Сравнивает эти "векторы" и ищет похожие по смыслу
Находит "уютные кресла для террасы", потому что векторы похожи
Смысловой поиск — умный поиск
Как это работает
Шаг 1. Превращаем текст в векторы (массивы чисел)
"comfortable chair" → [0.2, 0.7, 0.1, 0.4, ...]
"cozy seat" → [0.3, 0.8, 0.2, 0.5, ...]
Похожие фразы → похожие числа
Это делает AI-модель, например OpenAI embeddings
Шаг 2. Храним векторы
В обычной БД хранят текст
В векторной — массив чисел для каждого объекта
Индексируют их, чтобы быстро искать по схожести
Оптимизировано под "найди похожие", а не "найди точное"
Шаг 3. Ищем по схожести
Запрос: "outdoor furniture"
Превращается в [0.3, 0.6, 0.2, 0.8, ...]
Система ищет ближайшие векторы (через cosine similarity)
Результаты сортируются по степени похожести
Где это используется:
- Поиск товаров, который понимает смысл, а не только слова
- Поиск по документации, который находит релевантные ответы
- Рекомендательные системы
- Чатботы, ищущие похожие вопросы
- Обнаружение аномалий
Популярные векторные базы
Pinecone = управляемая, простая, но дорогая
Weaviate = опенсорс, с кучей функций
Milvus = быстрая и масштабируемая, но сложная
pgvector = расширение для Postgres, простое и удобное
Qdrant = быстрая, написана на Rust
Спорная, но практичная мысль
В большинстве проектов тебе не нужна отдельная векторная база.
Начни с Postgres + pgvector = этого хватает, пока у тебя меньше 1 миллиона векторов.
Когда масштаб вырастет, тогда уже смотри в сторону специализированных решений.
Please open Telegram to view this post
    VIEW IN TELEGRAM
  ❤11
  Самый прямолинейный способ вынести секреты во внешнее хранилище в Spring Boot приложении это использовать Spring Cloud Config Server.
Spring Cloud Config Server позволяет хранить конфигурацию приложения в централизованном репозитории (обычно Git).
В случае с Git репозиторием при старте приложение подтягивает конфигурационные файлы с Config Server, а не локально, а сам Config Server берет их из Git репозитория. Ниже пример конфигурации, чтобы сервер подключался к Git репо:
Конфигурация клиента может выглядеть примерно так:
Можно шифровать чувствительные данные в конфигурационных файлах в Git репо. Ниже пример с паролем для key-store, который используется для защищенного SSL соединения (обрати внимание на префикс
Альтернатива это использовать HashiCorp Vault
👉   Java Portal
Spring Cloud Config Server позволяет хранить конфигурацию приложения в централизованном репозитории (обычно Git).
В случае с Git репозиторием при старте приложение подтягивает конфигурационные файлы с Config Server, а не локально, а сам Config Server берет их из Git репозитория. Ниже пример конфигурации, чтобы сервер подключался к Git репо:
cloud:
config:
server:
git:
uri: https://github.com/username/spring-cloud-config-git-server-repo.git
username: ${github.username}
password: ${github.password}
Конфигурация клиента может выглядеть примерно так:
config:
import: "optional:configserver:"
Можно шифровать чувствительные данные в конфигурационных файлах в Git репо. Ниже пример с паролем для key-store, который используется для защищенного SSL соединения (обрати внимание на префикс
 {cipher}, он обязателен)server:
port: ${PORT:8092}
ssl:
enabled: true
key-store: classpath:books.p12
key-store-password: '{cipher}AAQAB0P8AKMImyLncL3WUbLsn2J0DlHBeMbmylb0e5RMqr7QWrPhDwJ8xVMw...'
key-store-type: PKCS12:
Альтернатива это использовать HashiCorp Vault
Please open Telegram to view this post
    VIEW IN TELEGRAM
  