Эволюция коммуникации между сервисами
Архитектура ПО кардинально изменилась за последние 30 лет.
Не потому, что старые подходы были неправильными..
а потому что приложения постоянно росли.
Вот как развивалась коммуникация сервисов:
🔹 1990-е → Point-to-Point (прямая связь)
Просто. Быстро. Но жёсткая связанность.
🔹 2000-е → Запрос/Ответ (RPC)
Удалённые вызовы упростили построение распределённых систем.
🔹 2010-е → Очереди сообщений (Message Queues)
Асинхронная коммуникация повысила надёжность и масштабируемость.
🔹 Середина 2010-х → Издатель/Подписчик (Pub/Sub)
Сервисам больше не нужно было знать друг о друге напрямую.
🔹 Конец 2010-х → Потоковая обработка событий (Event Streaming)
Непрерывная обработка данных в реальном времени с помощью платформ вроде Kafka.
🔹 2020-е → API Gateway + Service Mesh
Управление трафиком, безопасность, наблюдаемость и отказоустойчивость стали первоклассными гражданами.
🔹 Сегодня → AI-нативная коммуникация
Агенты не просто вызывают API — они обнаруживают инструменты, рассуждают о задачах и координируют рабочие процессы.
Главный урок?
Каждая эволюция уменьшала связанность и увеличивала масштабируемость.
Мы движемся от:
➡️ Вызова сервисов
➡️ Публикации событий
➡️ Координации интеллектуальных систем
Какой паттерн коммуникации вы используете чаще всего сегодня?
- REST
- gRPC
- Kafka
- RabbitMQ
- Event Bus
- Service Mesh
👉 Java Portal
Архитектура ПО кардинально изменилась за последние 30 лет.
Не потому, что старые подходы были неправильными..
а потому что приложения постоянно росли.
Вот как развивалась коммуникация сервисов:
🔹 1990-е → Point-to-Point (прямая связь)
Просто. Быстро. Но жёсткая связанность.
🔹 2000-е → Запрос/Ответ (RPC)
Удалённые вызовы упростили построение распределённых систем.
🔹 2010-е → Очереди сообщений (Message Queues)
Асинхронная коммуникация повысила надёжность и масштабируемость.
🔹 Середина 2010-х → Издатель/Подписчик (Pub/Sub)
Сервисам больше не нужно было знать друг о друге напрямую.
🔹 Конец 2010-х → Потоковая обработка событий (Event Streaming)
Непрерывная обработка данных в реальном времени с помощью платформ вроде Kafka.
🔹 2020-е → API Gateway + Service Mesh
Управление трафиком, безопасность, наблюдаемость и отказоустойчивость стали первоклассными гражданами.
🔹 Сегодня → AI-нативная коммуникация
Агенты не просто вызывают API — они обнаруживают инструменты, рассуждают о задачах и координируют рабочие процессы.
Главный урок?
Каждая эволюция уменьшала связанность и увеличивала масштабируемость.
Мы движемся от:
➡️ Вызова сервисов
➡️ Публикации событий
➡️ Координации интеллектуальных систем
Какой паттерн коммуникации вы используете чаще всего сегодня?
- REST
- gRPC
- Kafka
- RabbitMQ
- Event Bus
- Service Mesh
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
Почему используется Event-Driven Architecture?
Представьте систему с двумя микросервисами:
1) payments
2) emails
Когда платеж подтверждён, payments вызывает emails, чтобы отправить чек.
Но приложение растёт. Теперь нужно ещё сгенерировать счёт, обновить метрики и отправить уведомление.
Чтобы это сделать, payments начинает вызывать каждый из них.
Каждая новая функциональность добавляет ещё один вызов. Со временем такой поток становится всё сложнее поддерживать.
Event-Driven Architecture предлагает другой способ коммуникации.
Когда платеж подтверждён:
1) payments публикует событие "payment confirmed".
2) emails отправляет чек.
3) billing генерирует счёт.
4) metrics обновляет дашборды.
Если завтра вы добавите ещё один микросервис, ему просто нужно реагировать на это событие. Payments не меняется.
Вот почему это так хорошо сочетается с микросервисами: каждый сохраняет единственную ответственность и может развиваться без прямой зависимости от остальных.
Очевидно, не всё только преимущества. Система также становится сложнее. Возникают такие проблемы, как повторные попытки, дублирующиеся события, порядок обработки и наблюдаемость.
На практике обычно используется брокер (например, Kafka или RabbitMQ), который получает событие и распределяет его по подписанным микросервисам.
👉 Java Portal
Представьте систему с двумя микросервисами:
1) payments
2) emails
Когда платеж подтверждён, payments вызывает emails, чтобы отправить чек.
Но приложение растёт. Теперь нужно ещё сгенерировать счёт, обновить метрики и отправить уведомление.
Чтобы это сделать, payments начинает вызывать каждый из них.
Каждая новая функциональность добавляет ещё один вызов. Со временем такой поток становится всё сложнее поддерживать.
Event-Driven Architecture предлагает другой способ коммуникации.
Когда платеж подтверждён:
1) payments публикует событие "payment confirmed".
2) emails отправляет чек.
3) billing генерирует счёт.
4) metrics обновляет дашборды.
Если завтра вы добавите ещё один микросервис, ему просто нужно реагировать на это событие. Payments не меняется.
Вот почему это так хорошо сочетается с микросервисами: каждый сохраняет единственную ответственность и может развиваться без прямой зависимости от остальных.
Очевидно, не всё только преимущества. Система также становится сложнее. Возникают такие проблемы, как повторные попытки, дублирующиеся события, порядок обработки и наблюдаемость.
На практике обычно используется брокер (например, Kafka или RabbitMQ), который получает событие и распределяет его по подписанным микросервисам.
Please open Telegram to view this post
VIEW IN TELEGRAM
Самая большая слабость JWT — его гибкость. PASETO устраняет её.
Спецификация JWT позволяет токену самому указывать, какой алгоритм использовать. Это единственное дизайнерское решение стоит за большинством проблем с JWT в продакшене.
Вот что PASETO делает иначе.
1. Атака живёт в заголовке
JWT содержит поле
Или взять публичный RSA-ключ, использовать его как HMAC-секрет, подписать через HS256 — и сервер, доверяющий заголовку, примет поддельный токен.
Это атака RS256→HS256 confusion, и она до сих пор ломает реальные системы.
2. PASETO привязывает криптографию к версии
Токен PASETO имеет формат
3. Вы выбираете назначение, а не алгоритм
Локальный токен (
Стандартный JWT только подписан — payload читается как обычный base64, и секреты утекают, когда люди забывают об этом.
4. Для сессий не нужно ни то, ни другое
JWT безопасны только как короткоживущие токены — минуты, а не недели, на которые тянется сессия. Google делает именно так: JWT используется только для передачи логина между хостами, а сессия в браузере остаётся кукой.
PASETO — лучший выбор для короткоживущего подписанного токена: SSO-переходы, межсервисные вызовы, одноразовое использование.
Для сессий проще кука, подкреплённая Postgres или Redis, а отзыв одной сессии — это удаление одной строки.
Большинство логинов хватаются за токен там, где подошла бы сессия.
https://gist.github.com/samsch/0d1f3d3b4745d778f78b230cf6061452
👉 Java Portal
Спецификация JWT позволяет токену самому указывать, какой алгоритм использовать. Это единственное дизайнерское решение стоит за большинством проблем с JWT в продакшене.
Вот что PASETO делает иначе.
1. Атака живёт в заголовке
JWT содержит поле
alg, которое указывает свой же алгоритм подписи. Вы можете установить его в "none", и некоторые библиотеки пропустят проверку.Или взять публичный RSA-ключ, использовать его как HMAC-секрет, подписать через HS256 — и сервер, доверяющий заголовку, примет поддельный токен.
Это атака RS256→HS256 confusion, и она до сих пор ломает реальные системы.
2. PASETO привязывает криптографию к версии
Токен PASETO имеет формат
version.purpose.payload. Версия фиксирует набор шифров — нечего согласовывать.v4.public — всегда Ed25519. v4.local — всегда XChaCha20 с BLAKE2b. Нет заголовка alg — нет атаки alg:none и confusion-атак.3. Вы выбираете назначение, а не алгоритм
Локальный токен (
local) зашифрован симметричным ключом. Публичный токен (public) подписан так, что любой с публичным ключом может его проверить.Стандартный JWT только подписан — payload читается как обычный base64, и секреты утекают, когда люди забывают об этом.
4. Для сессий не нужно ни то, ни другое
JWT безопасны только как короткоживущие токены — минуты, а не недели, на которые тянется сессия. Google делает именно так: JWT используется только для передачи логина между хостами, а сессия в браузере остаётся кукой.
PASETO — лучший выбор для короткоживущего подписанного токена: SSO-переходы, межсервисные вызовы, одноразовое использование.
Для сессий проще кука, подкреплённая Postgres или Redis, а отзыв одной сессии — это удаление одной строки.
Большинство логинов хватаются за токен там, где подошла бы сессия.
https://gist.github.com/samsch/0d1f3d3b4745d778f78b230cf6061452
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4
PostgreSQL 19 добавит в SQL поддержку графовых запросов.
Можно описывать пути связей вроде:
user → likes → topic ← likes ← peer → follows → creator
Это полезно для рекомендаций, прав доступа, социальных графов, цепочек мошенничества и памяти ИИ.
👉 Java Portal
Можно описывать пути связей вроде:
user → likes → topic ← likes ← peer → follows → creator
Это полезно для рекомендаций, прав доступа, социальных графов, цепочек мошенничества и памяти ИИ.
Please open Telegram to view this post
VIEW IN TELEGRAM
This media is not supported in your browser
VIEW IN TELEGRAM
Кто-то собрал Kubernetes, который полностью работает в браузере.
Это может быть самый простой способ изучить Kubernetes.
- Не нужен Docker.
- Не нужен Minikube.
- Не нужен Kind.
- Не нужен EKS.
- Не требуется установка.
Просто откройте веб-страницу и начинайте изучать Pods, Deployments, ReplicaSets, Nodes, планирование, сеть и многое другое.
Инженерная работа за этим проектом невероятна.
Kubernetes написан на Go, но вместо компиляции в браузер разработчик переписал ключевые компоненты Kubernetes на TypeScript, чтобы они работали нативно внутри браузера.
Это один из лучших примеров использования ИИ, который я видел.
ИИ помог портировать тысячи строк кода Kubernetes, пока разработчик вручную проверял всё и подтверждал обширными тестами, чтобы убедиться, что поведение соответствует реальному кластеру.
Это не для продакшн-нагрузок.
Он создан для обучения, преподавания, экспериментов и подготовки к DevOps-собеседованиям.
Представьте онбординг новых инженеров или обучение Kubernetes без необходимости тратить час на установку Docker, настройку Minikube или создание EKS-кластера.
Я искренне считаю, что такие проекты изменят то, как мы изучаем инфраструктуру.
Интерактивные лабораторные работы > Статическая документация.
Пост в блоге: https://ngrok.com/blog/i-ported-kubernetes-to-the-browser
👉 Java Portal
Это может быть самый простой способ изучить Kubernetes.
- Не нужен Docker.
- Не нужен Minikube.
- Не нужен Kind.
- Не нужен EKS.
- Не требуется установка.
Просто откройте веб-страницу и начинайте изучать Pods, Deployments, ReplicaSets, Nodes, планирование, сеть и многое другое.
Инженерная работа за этим проектом невероятна.
Kubernetes написан на Go, но вместо компиляции в браузер разработчик переписал ключевые компоненты Kubernetes на TypeScript, чтобы они работали нативно внутри браузера.
Это один из лучших примеров использования ИИ, который я видел.
ИИ помог портировать тысячи строк кода Kubernetes, пока разработчик вручную проверял всё и подтверждал обширными тестами, чтобы убедиться, что поведение соответствует реальному кластеру.
Это не для продакшн-нагрузок.
Он создан для обучения, преподавания, экспериментов и подготовки к DevOps-собеседованиям.
Представьте онбординг новых инженеров или обучение Kubernetes без необходимости тратить час на установку Docker, настройку Minikube или создание EKS-кластера.
Я искренне считаю, что такие проекты изменят то, как мы изучаем инфраструктуру.
Интерактивные лабораторные работы > Статическая документация.
Пост в блоге: https://ngrok.com/blog/i-ported-kubernetes-to-the-browser
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8
Java CompletableFuture: цепочка асинхронных шагов без блокировки потока при каждом I/O вызове.
Цепочка: supplyAsync, thenApply, thenCompose, thenAccept (получить пользователя, затем заказы)
Обрабатывайте сбои через exceptionality, не давайте асинхронным ошибкам бесшумно исчезать
Запускайте независимые вызовы параллельно, объединяйте через thenCombine когда оба завершатся
#JavaDev
👉 Java Portal
Цепочка: supplyAsync, thenApply, thenCompose, thenAccept (получить пользователя, затем заказы)
Обрабатывайте сбои через exceptionality, не давайте асинхронным ошибкам бесшумно исчезать
Запускайте независимые вызовы параллельно, объединяйте через thenCombine когда оба завершатся
#JavaDev
Please open Telegram to view this post
VIEW IN TELEGRAM
Основы системного дизайна
Теорема CAP: почему распределённые системы не могут иметь всё сразу
Представьте, что ваше приложение работает на нескольких серверах в разных городах.
Внезапно...
Сетевое соединение между серверами прерывается.
Теперь у системы есть выбор:
Продолжать принимать запросы?
Или отклонять запросы, пока всё не синхронизируется?
Именно эту проблему решает теорема CAP.
Что такое теорема CAP?
CAP означает:
C — Consistency (Согласованность)
Каждый пользователь видит одни и те же данные, независимо от того, к какому серверу подключился.
Пример: Перевод ₹1000. Каждый сервер сразу показывает обновлённый баланс.
A — Availability (Доступность)
Каждый запрос получает ответ.
Даже если один или несколько серверов недоступны.
Ответ может не содержать самых свежих данных.
P — Partition Tolerance (Устойчивость к разделению)
Система продолжает работать, даже если связь между серверами прервана.
В распределённых системах сетевые сбои неизбежны.
Главное правило. Когда происходит сетевое разделение (partition)...
Можно выбрать только одно из двух:
✔️ Согласованность (Consistency)
ИЛИ
✔️ Доступность (Availability)
Гарантировать оба одновременно нельзя.
Partition Tolerance в распределённых системах не опционален — вы обязаны считать, что это случится.
- CP-системы
Выбирают:
✔️ Согласованность
✔️ Устойчивость к разделению
Пример:
Если серверы не могут общаться, часть запросов отклоняется, чтобы сохранить согласованность данных.
Применение:
- Банковские системы
- Платёжные системы
- Управление запасами
Правильность важнее, чем постоянный ответ.
- AP-системы
Выбирают:
✔️ Доступность
✔️ Устойчивость к разделению
Даже если серверы теряют связь, они продолжают отвечать.
Некоторые пользователи могут временно видеть устаревшие данные.
Применение:
- Социальные сети
- Ленты новостей
- Каталоги товаров
Доступность важнее немедленной согласованности.
= Реальные примеры =
Банкинг
Неверные балансы недопустимы. Выбирают CP.
Лайки в Instagram
Видеть 1024 лайка вместо 1026 пару секунд — не проблема. Выбирают AP.
Корзина покупок
Многие системы ищут баланс.
Корзина должна оставаться доступной, а важные операции (оплата) — строго согласованными.
Главный вывод. Теорема CAP не говорит: «Выбери любые два».
Она говорит:
Когда происходит сетевое разделение, вы обязаны выбрать между Согласованностью и Доступностью.
Каждая распределённая система делает этот компромисс.
👉 Java Portal
Теорема CAP: почему распределённые системы не могут иметь всё сразу
Представьте, что ваше приложение работает на нескольких серверах в разных городах.
Внезапно...
Сетевое соединение между серверами прерывается.
Теперь у системы есть выбор:
Продолжать принимать запросы?
Или отклонять запросы, пока всё не синхронизируется?
Именно эту проблему решает теорема CAP.
Что такое теорема CAP?
CAP означает:
C — Consistency (Согласованность)
Каждый пользователь видит одни и те же данные, независимо от того, к какому серверу подключился.
Пример: Перевод ₹1000. Каждый сервер сразу показывает обновлённый баланс.
A — Availability (Доступность)
Каждый запрос получает ответ.
Даже если один или несколько серверов недоступны.
Ответ может не содержать самых свежих данных.
P — Partition Tolerance (Устойчивость к разделению)
Система продолжает работать, даже если связь между серверами прервана.
В распределённых системах сетевые сбои неизбежны.
Главное правило. Когда происходит сетевое разделение (partition)...
Можно выбрать только одно из двух:
✔️ Согласованность (Consistency)
ИЛИ
✔️ Доступность (Availability)
Гарантировать оба одновременно нельзя.
Partition Tolerance в распределённых системах не опционален — вы обязаны считать, что это случится.
- CP-системы
Выбирают:
✔️ Согласованность
✔️ Устойчивость к разделению
Пример:
Сервер A ✖️ Сеть ✖️ Сервер B
Если серверы не могут общаться, часть запросов отклоняется, чтобы сохранить согласованность данных.
Применение:
- Банковские системы
- Платёжные системы
- Управление запасами
Правильность важнее, чем постоянный ответ.
- AP-системы
Выбирают:
✔️ Доступность
✔️ Устойчивость к разделению
Даже если серверы теряют связь, они продолжают отвечать.
Некоторые пользователи могут временно видеть устаревшие данные.
Применение:
- Социальные сети
- Ленты новостей
- Каталоги товаров
Доступность важнее немедленной согласованности.
= Реальные примеры =
Банкинг
Неверные балансы недопустимы. Выбирают CP.
Лайки в Instagram
Видеть 1024 лайка вместо 1026 пару секунд — не проблема. Выбирают AP.
Корзина покупок
Многие системы ищут баланс.
Корзина должна оставаться доступной, а важные операции (оплата) — строго согласованными.
Главный вывод. Теорема CAP не говорит: «Выбери любые два».
Она говорит:
Когда происходит сетевое разделение, вы обязаны выбрать между Согласованностью и Доступностью.
Каждая распределённая система делает этот компромисс.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6👍2
Зачем нужен обратный прокси (Reverse Proxy)?
У вас есть API на Node.js.
Поначалу пользователи отправляют запросы напрямую в приложение, и всё работает отлично.
Но по мере роста проекта появляются новые задачи:
- использовать HTTPS;
- раздавать статические файлы;
- применять ограничение частоты запросов (Rate Limiting);
- масштабировать приложение.
Часть этих задач можно решить прямо в API. Но проблема в том, что тогда ему приходится выполнять две разные роли:
реализовывать бизнес-логику (пользователи, платежи, заказы и т. д.);
решать инфраструктурные задачи (HTTPS, раздача статики, Rate Limiting и т. д.).
По мере появления новых инфраструктурных задач становится логично отделить их от бизнес-логики.
Для этого между интернетом и вашим API добавляют дополнительный слой.
Этот слой называется обратным прокси (Reverse Proxy).
Он принимает входящие запросы и решает, что с ними делать: обработать их самостоятельно или перенаправить в API.
Интернет → Reverse Proxy → Ваш API
Одним из самых популярных решений для реализации обратного прокси является NGINX.
Главное преимущество такого подхода в том, что API может полностью сосредоточиться на бизнес-логике, а обратный прокси берёт на себя управление входящим трафиком до того, как он попадёт в приложение.
Недостаток заключается в том, что в архитектуре появляется ещё один компонент, который необходимо настраивать и поддерживать.
Однако по мере роста приложения такое разделение ответственности обычно значительно упрощает масштабирование и сопровождение системы.
👉 Java Portal
У вас есть API на Node.js.
Поначалу пользователи отправляют запросы напрямую в приложение, и всё работает отлично.
Но по мере роста проекта появляются новые задачи:
- использовать HTTPS;
- раздавать статические файлы;
- применять ограничение частоты запросов (Rate Limiting);
- масштабировать приложение.
Часть этих задач можно решить прямо в API. Но проблема в том, что тогда ему приходится выполнять две разные роли:
реализовывать бизнес-логику (пользователи, платежи, заказы и т. д.);
решать инфраструктурные задачи (HTTPS, раздача статики, Rate Limiting и т. д.).
По мере появления новых инфраструктурных задач становится логично отделить их от бизнес-логики.
Для этого между интернетом и вашим API добавляют дополнительный слой.
Этот слой называется обратным прокси (Reverse Proxy).
Он принимает входящие запросы и решает, что с ними делать: обработать их самостоятельно или перенаправить в API.
Интернет → Reverse Proxy → Ваш API
Одним из самых популярных решений для реализации обратного прокси является NGINX.
Главное преимущество такого подхода в том, что API может полностью сосредоточиться на бизнес-логике, а обратный прокси берёт на себя управление входящим трафиком до того, как он попадёт в приложение.
Недостаток заключается в том, что в архитектуре появляется ещё один компонент, который необходимо настраивать и поддерживать.
Однако по мере роста приложения такое разделение ответственности обычно значительно упрощает масштабирование и сопровождение системы.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤1
This media is not supported in your browser
VIEW IN TELEGRAM
НОВИНКА: Устойчивые функции (Durable Functions) в PostgreSQL 🤯
pg_durable — это расширение PostgreSQL. Состояние рабочего процесса, очередь, повторные попытки и восстановление хранятся в Postgres, и оно использует устойчивость Postgres / высокую доступность / резервное копирование / восстановление.
https://techcommunity.microsoft.com/blog/adforpostgresql/introducing-durable-functions-in-postgresql/4526821
👉 Java Portal
pg_durable — это расширение PostgreSQL. Состояние рабочего процесса, очередь, повторные попытки и восстановление хранятся в Postgres, и оно использует устойчивость Postgres / высокую доступность / резервное копирование / восстановление.
https://techcommunity.microsoft.com/blog/adforpostgresql/introducing-durable-functions-in-postgresql/4526821
Please open Telegram to view this post
VIEW IN TELEGRAM
Привет, на связи Таня Коровкина из ШОРТКАТ. Ментор по алгоритмам и backend-разработчик
Каждый месяц тысячи разработчиков совершают одни и те же ошибки на алгоритмических интервью 🚩
И продолжают готовиться... не к тому.
Уже сегодня в 19:00 (МСК) проведу вебинар и покажу, что на самом деле оценивает интервьюер и какие ошибки чаще всего приводят к отказу
• дам практические советы, которые можно использовать уже на следующем собеседовании
• расскажу про специфику российского BigTech
🤘 Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot
Реклама.
О рекламодателе.
Please open Telegram to view this post
VIEW IN TELEGRAM
Spring Boot: Вы можете реализовать оптимистическую блокировку с помощью аннотации
✅ Идеально подходит, когда:
операции чтения выполняются часто;
операции записи происходят сравнительно редко;
конфликты возникают редко.
❌ Не подходит, когда:
конфликты происходят часто;
требуется строгая последовательная обработка (strict serialization).
#SpringBoot #JavaDev
👉 Java Portal
@Version.✅ Идеально подходит, когда:
операции чтения выполняются часто;
операции записи происходят сравнительно редко;
конфликты возникают редко.
❌ Не подходит, когда:
конфликты происходят часто;
требуется строгая последовательная обработка (strict serialization).
#SpringBoot #JavaDev
Please open Telegram to view this post
VIEW IN TELEGRAM
💡 Java: sealed types позволяют закрыть граф наследования с помощью
Это даёт полный контроль над тем, какие классы или интерфейсы могут наследоваться от базового типа.
✅ Наследоваться от
✅ Каждый разрешённый подтип должен быть объявлен как
При этом
#JavaDev
👉 Java Portal
permits.Это даёт полный контроль над тем, какие классы или интерфейсы могут наследоваться от базового типа.
✅ Наследоваться от
sealed-класса или интерфейса могут только типы, перечисленные в permits.✅ Каждый разрешённый подтип должен быть объявлен как
final, sealed или non-sealed.При этом
non-sealed — это своего рода «точка выхода»: начиная с такого класса, ограничения снимаются, и наследование снова становится открытым для любых потомков.#JavaDev
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
💡 Switch-выражения в Java: больше не нужно писать
✅ По одной строке на каждый
✅ Добавили новую константу в
👉 Java Portal
break, а компилятор сам следит за тем, чтобы вы не забыли обработать ни один случай.✅ По одной строке на каждый
case, выражение возвращает значение, break больше не нужен.✅ Добавили новую константу в
enum, но не добавили соответствующий case? Получите ошибку компиляции, а не тихий баг, который проявится только во время выполнения.Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
В PostgreSQL
Когда использовать
Если есть бизнес-требование ограничить максимальную длину значения или столбец индексируется с помощью B-tree, стоит рассмотреть
Более того, в документации PostgreSQL говорится:
Почему изменить
Потому что это всего лишь изменение метаданных. Физическое хранение данных у этих типов одинаковое.
Метаданные хранятся в таблице
А вот с
При миграции с
Это уже значительно более затратная операция, чем простое изменение метаданных, поэтому PostgreSQL приходится переписывать таблицу.
Как PostgreSQL хранит строки. PostgreSQL использует формат хранения переменной длины для всех строковых типов данных.
Данные могут храниться либо непосредственно в строке таблицы (inline), либо с использованием механизма TOAST (The Oversized-Attribute Storage Technique), который отвечает за сжатие и вынесение больших значений за пределы основной таблицы. Обычно TOAST начинает использоваться, когда размер строки превышает примерно 2 КБ.
И
Когда действительно стоит использовать
Используйте
Стоит ли использовать
Для
Что касается
В таких случаях
Проще говоря,
Индексируемые столбцы? Рассмотрите
Само по себе индексирование столбцов типа
Почему?
Потому что PostgreSQL не сможет создать запись в B-tree-индексе, если её размер превышает примерно 2704 байта.
На самом деле ограничение распространяется не на исходный размер строки, а на её сжатый размер, поэтому назвать точный предел в символах невозможно: разные строки сжимаются по-разному.
Ограничение длины через
👉 Java Portal
varchar(255) ведёт себя так же, как столбец типа text; единственное отличие — у varchar есть ограничение на длину. Тип varchar(n) всегда работал именно так. Если вы видите в PostgreSQL столбец varchar(255), то зачастую это потому, что разработчик сначала работал с другой СУБД и перенёс свои прежние представления о том, как должен работать varchar(n).Когда использовать
text, а когда varchar?Если есть бизнес-требование ограничить максимальную длину значения или столбец индексируется с помощью B-tree, стоит рассмотреть
varchar(n). Если такого требования нет — используйте text и не думайте, что делаете что-то неправильно. Более того, в документации PostgreSQL говорится:
Хотя в некоторых других СУБД тип character(n) может иметь преимущества по производительности, в PostgreSQL таких преимуществ нет. Более того, character(n)
обычно является самым медленным из трёх вариантов из-за дополнительных затрат на хранение. В большинстве случаев вместо него следует использовать text или character varying
Почему изменить
varchar(n) на text ничего не стоит?Потому что это всего лишь изменение метаданных. Физическое хранение данных у этих типов одинаковое.
Метаданные хранятся в таблице
pg_attribute, поэтому изменение типа сводится к обновлению записи в этой таблице. Сами данные остаются без изменений, поэтому не требуется ни переписывать таблицу, ни менять формат хранения.А вот с
char всё иначеПри миграции с
char на text для каждого значения выполняется rtrim, поскольку неявное приведение char к text автоматически удаляет завершающие пробелы.Это уже значительно более затратная операция, чем простое изменение метаданных, поэтому PostgreSQL приходится переписывать таблицу.
Как PostgreSQL хранит строки. PostgreSQL использует формат хранения переменной длины для всех строковых типов данных.
Данные могут храниться либо непосредственно в строке таблицы (inline), либо с использованием механизма TOAST (The Oversized-Attribute Storage Technique), который отвечает за сжатие и вынесение больших значений за пределы основной таблицы. Обычно TOAST начинает использоваться, когда размер строки превышает примерно 2 КБ.
И
varchar(n), и text используют один и тот же механизм хранения, включая TOAST.Когда действительно стоит использовать
varchar(n)?Используйте
varchar(n), когда ограничение длины — это бизнес-правило, которое должна контролировать сама база данных. Например:country_code varchar(2), -- ISO 3166-1
currency_code varchar(3), -- ISO 4217
us_zip_code varchar(5), -- 5 цифр
sku varchar(20), -- ограничения внешних систем
Стоит ли использовать
varchar для country_code и currency_code? Конечно. Международные стандарты жёстко определяют длину этих кодов.Для
SKU ограничение длины также может диктоваться внешними требованиями.Что касается
us_zip_code, то на практике нередко возникает необходимость поддерживать расширенный формат ZIP+4. Со временем такие столбцы вообще могут быть переименованы в postal_code, чтобы поддерживать международные почтовые индексы.В таких случаях
varchar одновременно обеспечивает и необходимое ограничение, и достаточную гибкость.Проще говоря,
varchar помогает обеспечить соблюдение бизнес-правил.Индексируемые столбцы? Рассмотрите
varchar(n)Само по себе индексирование столбцов типа
text не является проблемой, однако есть нюанс.varchar(n) может служить дополнительной защитой для индексируемых столбцов (например, если username используется не просто как отображаемое имя, а для поиска, аутентификации или загрузки профиля).Почему?
Потому что PostgreSQL не сможет создать запись в B-tree-индексе, если её размер превышает примерно 2704 байта.
На самом деле ограничение распространяется не на исходный размер строки, а на её сжатый размер, поэтому назвать точный предел в символах невозможно: разные строки сжимаются по-разному.
Ограничение длины через
varchar(n) позволяет предотвратить ситуацию, когда приложение пытается сохранить значение, которое невозможно проиндексировать.Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍3
Массивы в Java
Представьте, что вам нужно хранить оценки 100 студентов.
Неужели вы будете создавать 100 отдельных переменных?
Конечно, нет.
Именно для этого и существуют массивы. Массив позволяет хранить несколько значений одного типа данных в одной переменной.
Что такое массив?
Массив — это коллекция элементов фиксированного размера одного типа, расположенных в непрерывной области памяти.
Каждый элемент определяется своим индексом, который начинается с 0.
Создание массива
- Объявление
- Создание
- Объявление и создание
Или можно сразу инициализировать массив:
Основные операции
- Доступ к элементу
- Изменение элемента
- Получение длины массива
- Перебор массива
Важные моменты
- Размер массива фиксирован.
- Индексация всегда начинается с 0.
- Все элементы массива должны быть одного типа данных.
- Массивы примитивных типов автоматически заполняются значениями по умолчанию.
Например:
Значения элементов будут такими:
- Совет для собеседований
Что произойдет в этом случае?
❌ Будет выброшено исключение ArrayIndexOutOfBoundsException.
Почему?
Потому что допустимые индексы:
Попытка обратиться к индексу, выходящему за пределы массива, приводит к возникновению исключения во время выполнения программы.
Массивы — одна из самых фундаментальных структур данных в Java.
Хорошее понимание принципов их работы значительно упрощает изучение ArrayList, Collections, Stack, Queue, а также большинства алгоритмов, которые встречаются на технических собеседованиях.
👉 Java Portal
Представьте, что вам нужно хранить оценки 100 студентов.
Неужели вы будете создавать 100 отдельных переменных?
int mark1;
int mark2;
int mark3;
...
Конечно, нет.
Именно для этого и существуют массивы. Массив позволяет хранить несколько значений одного типа данных в одной переменной.
Что такое массив?
Массив — это коллекция элементов фиксированного размера одного типа, расположенных в непрерывной области памяти.
int[] scores = {10, 20, 30, 40, 50};Каждый элемент определяется своим индексом, который начинается с 0.
Индекс : 0 1 2 3 4
Значение:10 20 30 40 50
Создание массива
- Объявление
int[] numbers;
- Создание
numbers = new int[5];
- Объявление и создание
int[] numbers = new int[5];
Или можно сразу инициализировать массив:
int[] numbers = {10, 20, 30, 40, 50};Основные операции
- Доступ к элементу
System.out.println(numbers[2]); // 30
- Изменение элемента
numbers[1] = 25;
- Получение длины массива
numbers.length
- Перебор массива
for (int i = 0; i < numbers.length; i++) {
System.out.println(numbers[i]);
}Важные моменты
- Размер массива фиксирован.
- Индексация всегда начинается с 0.
- Все элементы массива должны быть одного типа данных.
- Массивы примитивных типов автоматически заполняются значениями по умолчанию.
Например:
int[] arr = new int[3];
Значения элементов будут такими:
0 0 0
- Совет для собеседований
Что произойдет в этом случае?
int[] arr = {10, 20, 30};
System.out.println(arr[3]);❌ Будет выброшено исключение ArrayIndexOutOfBoundsException.
Почему?
Потому что допустимые индексы:
0, 1, 2
Попытка обратиться к индексу, выходящему за пределы массива, приводит к возникновению исключения во время выполнения программы.
Массивы — одна из самых фундаментальных структур данных в Java.
Хорошее понимание принципов их работы значительно упрощает изучение ArrayList, Collections, Stack, Queue, а также большинства алгоритмов, которые встречаются на технических собеседованиях.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Масштабирование базы данных и стратегии шардинга — простое объяснение с иллюстрациями
По мере роста приложения или системы база данных тоже должна масштабироваться, чтобы справляться с увеличивающейся нагрузкой. Ниже — обзор основных стратегий.
1. Горизонтальное масштабирование (Horizontal Scaling)
Добавление новых серверов для распределения нагрузки и увеличения общей производительности без перегрузки одного сервера.
2. Вертикальное масштабирование (Vertical Scaling)
Увеличение ресурсов существующего сервера — процессора, оперативной памяти или дискового пространства — чтобы он мог обрабатывать больше запросов.
3. Стратегии партиционирования (Partition Strategies)
Логическое разделение большой базы данных на части (например, по времени, региону или типу данных), что упрощает управление и ускоряет доступ к данным.
4. Шардинг по диапазонам (Range-Based Sharding)
Данные распределяются между шардами по диапазонам значений (например, по цене, дате или идентификатору), что ускоряет поиск по таким полям.
5. Равномерное распределение данных (Even Distribution)
Нагрузка равномерно распределяется между всеми серверами, что позволяет максимально эффективно использовать ресурсы и избегать узких мест.
6. Неравномерное распределение данных (Uneven Distribution)
Нагрузка распределена неравномерно: одни серверы перегружены, а другие практически простаивают, что снижает эффективность всей системы.
7. Шардинг по ключу (Key-Based Sharding)
Для распределения данных между шардами используется хеш-функция, которая обеспечивает стабильное и равномерное распределение записей.
8. Масштабирование операций чтения (Scaling Reads)
Создание нескольких реплик базы данных только для чтения (Read Replicas), чтобы обрабатывать большое количество запросов и снизить нагрузку на основную базу данных.
9. Монолитная база данных vs шардинг (Monolith vs Sharding)
Вместо одной большой монолитной базы данных данные разделяются на логические шарды. Такой подход облегчает масштабирование системы, упрощает организацию данных и повышает производительность.
Эти подходы являются основой проектирования масштабируемых систем и часто используются при разработке высоконагруженных приложений и при подготовке к техническим собеседованиям по System Design.
👉 Java Portal
По мере роста приложения или системы база данных тоже должна масштабироваться, чтобы справляться с увеличивающейся нагрузкой. Ниже — обзор основных стратегий.
1. Горизонтальное масштабирование (Horizontal Scaling)
Добавление новых серверов для распределения нагрузки и увеличения общей производительности без перегрузки одного сервера.
2. Вертикальное масштабирование (Vertical Scaling)
Увеличение ресурсов существующего сервера — процессора, оперативной памяти или дискового пространства — чтобы он мог обрабатывать больше запросов.
3. Стратегии партиционирования (Partition Strategies)
Логическое разделение большой базы данных на части (например, по времени, региону или типу данных), что упрощает управление и ускоряет доступ к данным.
4. Шардинг по диапазонам (Range-Based Sharding)
Данные распределяются между шардами по диапазонам значений (например, по цене, дате или идентификатору), что ускоряет поиск по таким полям.
5. Равномерное распределение данных (Even Distribution)
Нагрузка равномерно распределяется между всеми серверами, что позволяет максимально эффективно использовать ресурсы и избегать узких мест.
6. Неравномерное распределение данных (Uneven Distribution)
Нагрузка распределена неравномерно: одни серверы перегружены, а другие практически простаивают, что снижает эффективность всей системы.
7. Шардинг по ключу (Key-Based Sharding)
Для распределения данных между шардами используется хеш-функция, которая обеспечивает стабильное и равномерное распределение записей.
8. Масштабирование операций чтения (Scaling Reads)
Создание нескольких реплик базы данных только для чтения (Read Replicas), чтобы обрабатывать большое количество запросов и снизить нагрузку на основную базу данных.
9. Монолитная база данных vs шардинг (Monolith vs Sharding)
Вместо одной большой монолитной базы данных данные разделяются на логические шарды. Такой подход облегчает масштабирование системы, упрощает организацию данных и повышает производительность.
Эти подходы являются основой проектирования масштабируемых систем и часто используются при разработке высоконагруженных приложений и при подготовке к техническим собеседованиям по System Design.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1👍1
Java: Используйте Deque вместо Stack для реализации стека (LIFO — last in, first out, «последним пришёл — первым вышел»).
✅ Stack — это устаревший класс. Он наследуется от Vector и синхронизирует каждую операцию.
✅ Deque поддерживает те же методы: push, pop и peek.
✅ ArrayDeque работает быстрее, чем Stack.
#JavaDev
👉 Java Portal
✅ Stack — это устаревший класс. Он наследуется от Vector и синхронизирует каждую операцию.
✅ Deque поддерживает те же методы: push, pop и peek.
✅ ArrayDeque работает быстрее, чем Stack.
#JavaDev
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4
This media is not supported in your browser
VIEW IN TELEGRAM
Создавайте первоклассную документацию для своего API или проекта.
Starlight предлагает всё необходимое: высокую скорость благодаря Astro, встроенную оптимизацию для SEO, доступность и поиск, а также поддержку Markdown, MDX и нескольких языков.
→ http://starlight.astro.build/es
👉 Java Portal
Starlight предлагает всё необходимое: высокую скорость благодаря Astro, встроенную оптимизацию для SEO, доступность и поиск, а также поддержку Markdown, MDX и нескольких языков.
→ http://starlight.astro.build/es
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3
FastAPI с трёхуровневой архитектурой в стиле Java: слои controller, service, crud, schema и model, организованные по аналогии с паттернами Spring Boot. Включает поддержку SQLAlchemy 2.0, авторизации на базе Casbin и Docker.
https://github.com/fastapi-practices/fastapi-best-architecture
👉 Java Portal
https://github.com/fastapi-practices/fastapi-best-architecture
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
GitHub - fastapi-practices/fastapi-best-architecture at opensourceprojects.dev
Enterprise-level backend architecture solution with fastapi、sqlalchemy,、celery、pydantic、grafana、docker... - fastapi-practices/fastapi-best-architecture
👍3