Java Portal | Программирование
12K subscribers
1.45K photos
111 videos
45 files
1.49K links
Присоединяйтесь к нашему каналу и погрузитесь в мир для Java-разработчика

Связь: @devmangx

РКН: https://clck.ru/3H4WUg
Download Telegram
Системный дизайн: База данных

По мере роста числа пользователей одного сервера, на котором размещены веб-уровень и уровень данных, становится недостаточно. Поэтому нам потребуется несколько серверов:

- один для обработки веб- и мобильного трафика — веб-уровень (web tier);
- другой для базы данных — уровень данных (data tier).

Разделение серверов, обрабатывающих веб- и мобильный трафик, и серверов базы данных позволяет масштабировать эти уровни независимо друг от друга.

Какую базу данных использовать?

Можно выбрать между традиционной реляционной базой данных — RDBMS, или SQL-базой данных — и нереляционной базой данных — NoSQL.

Реляционные базы данных представляют и хранят данные в виде таблиц и строк. С помощью SQL можно выполнять операции JOIN между различными таблицами базы данных.

Нереляционная база данных может быть подходящим выбором, если:

- приложению требуется сверхнизкая задержка;
- данные неструктурированы или не имеют связей;
- требуется только сериализация и десериализация данных — JSON, YAML и т. д.;
- необходимо хранить огромные объёмы данных.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
Java Streams: limit(n) превращает бесконечный поток в конечный.

Полезно при работе со Stream.iterate() / generate() — они могут создавать бесконечные потоки
limit(5) означает: «взять первые 5 элементов и остановиться»
Отлично подходит для выборки данных или получения первых N значений

#Java #Streams

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
7
💡 Java I/O: используйте Files.copy(), чтобы скопировать файл одной строкой.

Отлично подходит для резервных копий: data.csvdata.csv.bak
Используйте REPLACE_EXISTING, если целевой файл уже может существовать
Работает с Path, поэтому код переносим между разными ОС

#Java #Files

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
2
Сис. дизайн: Балансировщик нагрузки

Балансировщик нагрузки равномерно распределяет входящий трафик между веб-серверами, объединёнными в балансируемую группу.

- Пользователь подключается напрямую к публичному IP-адресу балансировщика нагрузки. При такой схеме клиенты больше не могут обращаться к веб-серверам напрямую.
- Это повышает безопасность: для взаимодействия между серверами используются приватные IP-адреса, недоступные из интернета.
- Балансировщик нагрузки взаимодействует с веб-серверами через приватные IP-адреса.

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

- Если сервер 1 выйдет из строя, весь трафик будет перенаправлен на сервер 2. Это не позволит сайту стать недоступным.
- Если трафик сайта резко вырастет и двух серверов окажется недостаточно, балансировщик нагрузки позволит корректно решить эту проблему. В пул можно добавить дополнительные веб-серверы, после чего балансировщик автоматически начнёт направлять запросы и на них.

Вертикальное и горизонтальное масштабирование

Вертикальное масштабирование, также называемое scale up, — это процесс увеличения мощности серверов: добавления CPU, оперативной памяти и других ресурсов.

Горизонтальное масштабирование, также называемое scale out, позволяет масштабировать систему за счёт добавления новых серверов в пул ресурсов.

При низкой нагрузке вертикальное масштабирование может быть хорошим вариантом, а его главное преимущество — простота.

Ограничения вертикального масштабирования

- Невозможно бесконечно добавлять CPU и память одному серверу.
- Отсутствует отказоустойчивость. Если сервер выходит из строя, сайт или приложение полностью перестаёт работать.

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

Если множество пользователей одновременно обращаются к веб-серверу и нагрузка достигает его предела, пользователи сталкиваются с увеличением времени ответа или вообще не получают ответ.

Эта проблема решается с помощью горизонтального масштабирования и балансировщика нагрузки.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
Я только что наткнулся на этот репозиторий — и он отличный.
Хотите самостоятельно хостить OAuth 2.0-аутентификацию и не зависеть от Auth0, Clerk, Firebase или Supabase?
Тогда OpenAuth — именно то, что вам нужно.

Это универсальный провайдер аутентификации на основе стандартов, который можно полностью развернуть в собственной инфраструктуре.

Он работает с любым фреймворком и на любой платформе, а также совместим с любым OAuth 2.0-клиентом.

Главные возможности:

Полная поддержка OAuth 2.0 — его может использовать любой OAuth-клиент.
Гибкое развёртывание: Node.js, Bun, AWS Lambda или Cloudflare Workers.
Нативная поддержка Google, GitHub и других провайдеров, а также локальных сценариев: email и пароль, PIN-код и другие.
Готовый интерфейс, который можно полностью настроить или заменить собственным.
Полный контроль над управлением пользователями: через простой callback success можно реализовать собственную логику создания и поиска пользователей.
Лёгкое хранилище на основе KV, включая Cloudflare KV и DynamoDB.
Типобезопасный API и простая интеграция.


Проект создан командой SST. Сейчас он находится в бета-версии, но уже набрал более 7 000 звёзд на GitHub и активно развивается.

OpenAuth отлично подойдёт тем, кому нужны полный контроль над данными, отсутствие vendor lock-in, предсказуемые расходы при масштабировании и единая аутентификация для нескольких приложений.
Стоит сохранить, особенно если вы разрабатываете SaaS.

https://github.com/anomalyco/openauth

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
1
💡 Используйте Optional.orElseThrow(), когда отсутствие значения — это ошибка.

orElse(null)NPE возникает позже, далеко от места поиска значения
orElseThrow() останавливает выполнение в месте возникновения проблемы и выбрасывает понятное исключение
Передавайте Supplier, чтобы в сообщении было указано, какое именно значение отсутствует

#Java #Optional

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
7
Принципы проектирования программного обеспечения 👇

[1.] KISS (Keep It Simple, Stupid)
Программное обеспечение должно быть максимально простым.
Используйте понятный и лаконичный код, избегайте излишней сложности и сосредотачивайтесь на основных функциях.

[2.] DRY (Don't Repeat Yourself)
Код не должен дублироваться.
Используйте функции и классы для объединения общего кода.
Применяйте переменные и константы для хранения значений, которые используются в нескольких местах.

[3.] YAGNI (You Ain't Gonna Need It)
Не добавляйте в программное обеспечение функции, которые не нужны.
Поддерживайте простоту и удобство сопровождения.

[4.] SOLID
Принцип единственной ответственности – класс должен выполнять только одну задачу.
Принцип открытости/закрытости – классы должны быть открыты для расширения, но закрыты для изменения.
Принцип подстановки Барбары Лисков – объекты дочернего класса должны заменять объекты базового класса без нарушения функциональности.
Принцип разделения интерфейса – клиенты не должны зависеть от методов, которые они не используют.
Принцип инверсии зависимостей – зависимости должны внедряться в класс, а не быть жёстко закодированными.

[5.] Принцип наименьшего удивления**
Разрабатывайте программное обеспечение так, чтобы оно соответствовало ожиданиям пользователя.
Используйте знакомую терминологию и соглашения, предоставляйте понятные инструкции.
Применяйте четкие и лаконичные сообщения об ошибках.

[6.] Принцип модульности**
Проектируйте программное обеспечение как набор независимых модулей.
Это упрощает понимание, сопровождение и тестирование кода.

[7.] Принцип абстракции
Скрывайте детали реализации от пользователя.
Это делает программное обеспечение более понятным и удобным.

[8.] Принцип инкапсуляции
Программное обеспечение должно скрывать внутреннее состояние объекта от внешнего мира.
Это повышает устойчивость и удобство сопровождения.

[9.] Принцип наименьшего знания
Проектируйте программное обеспечение так, чтобы минимизировать объем знаний модуля о других модулях.
Это помогает повысить модульность и гибкость системы.

[10.] Принцип низкой связности и высокой когезии
Связность – это степень зависимости элементов модуля друг от друга.
Модуль с низкой связностью имеет мало зависимостей, и его элементы слабо зависят друг от друга.

Когезия – это степень, с которой элементы модуля относятся к одной цели.
Модуль с высокой когезией имеет одну четко определенную задачу, и все его элементы связаны с её выполнением.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
5
Серия о проектировании систем : Кэш

Кэш — это временное хранилище, в котором в памяти сохраняются результаты ресурсоёмких запросов или часто используемые данные, чтобы последующие обращения обрабатывались быстрее.

При каждой загрузке страницы выполняется один или несколько запросов к базе данных. Многократные обращения к базе могут значительно снижать производительность приложения. Кэш помогает решить эту проблему.

> Уровень кэширования

Отдельный уровень кэширования даёт несколько преимуществ:

- повышает производительность системы;
- снижает нагрузку на базу данных;
- позволяет масштабировать кэш независимо от других компонентов.

Работа происходит следующим образом:

1. Получив запрос, веб-сервер сначала проверяет, есть ли нужный ответ в кэше.
2. Если ответ есть, сервер отправляет его клиенту.
3. Если ответа нет, сервер обращается к базе данных, сохраняет результат в кэше и отправляет его клиенту.

Такая стратегия называется read-through cache — «сквозное чтение через кэш».

Существуют и другие стратегии кэширования. Выбор зависит от типа и объёма данных, а также от характера обращений к ним.

> Когда использовать кэш?

Кэш особенно полезен, когда данные:

- часто читаются;
- редко изменяются.

Важные данные должны храниться в постоянном хранилище, поскольку кэш обычно находится в оперативной памяти и не предназначен для долговременного хранения.

> Политика истечения срока действия

Рекомендуется задавать срок жизни кэшированных данных.

Без такой политики данные могут оставаться в памяти неограниченно долго.

Слишком короткий срок жизни приведёт к частым обращениям к базе данных, а слишком длинный — к тому, что данные в кэше устареют.

> Согласованность данных

Необходимо поддерживать синхронизацию между основным хранилищем и кэшем.

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

> Предотвращение сбоев

Один сервер кэша является единой точкой отказа, или SPOF — Single Point of Failure.

Поэтому для повышения отказоустойчивости рекомендуется использовать несколько серверов кэша.

> Политика вытеснения

Когда кэш заполняется, добавление новых элементов может приводить к удалению уже существующих.

Этот процесс называется вытеснением из кэша.

Самая популярная политика вытеснения — LRU, Least Recently Used, то есть удаление данных, которые не использовались дольше всего.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
1
Как опытный Java-разработчик/бэкенд-инженер, ты должен разбираться в отказоустойчивости и паттерне Circuit Breaker. Вот сценарий ненадёжного платёжного шлюза 💳 , чтобы проверить знания кандидата:

Сценарий:

Твоё приложение интегрируется со сторонним платёжным API. При пиковых нагрузках этот API стабильно даёт сбой примерно в 2% запросов. Это приводит к неудачным оплатам и ухудшает пользовательский опыт.

Вопрос:

Как ты спроектируешь интеграцию так, чтобы она была устойчива к этим сбоям и при этом сохраняла хороший UX? Объясни, какие именно паттерны (например, Circuit Breaker или Retry с экспоненциальной задержкой) ты бы применил и почему. Как бы ты обработал возможные дубликаты транзакций, возникающие из-за повторных запросов?

→ Что я оцениваю:

Понимание паттернов устойчивости и отказоустойчивости. Кандидат должен уметь объяснить такие концепции, как повторные запросы, Circuit Breaker (например, с использованием Resilience4j), fallback-механизмы, а также критическую важность идемпотентности при проектировании интеграций с платёжными системами.

В примере показано как реализовать Resilience4j с fallback-методом в Spring Boot

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
image_2025-06-15_07-56-57.png
450.7 KB
Концепции моделирования данных, которые должен знать каждый разработчик

1. Сущность — Объект реального мира или концепт, о котором вы хотите хранить данные (например, пользователь, заказ).

2. Атрибут — Свойство или поле сущности (например, имя, email, цена).

3. Первичный ключ — Уникальный идентификатор для каждой строки в таблице (например, user_id).

4. Внешний ключ — Ссылка на первичный ключ в другой таблице; используется для связывания сущностей.

5. Связь "один к одному" — Каждая строка в одной таблице связана с одной строкой в другой.

6. Связь "один ко многим" — Одна строка в таблице связана с несколькими строками в другой (например, пользователь → посты).

7. Связь "многие ко многим" — Несколько строк в одной таблице связаны с несколькими строками в другой (требуется таблица-связка).

8. Нормализация — Организация данных с целью уменьшения дублирования и повышения целостности.

9. Денормализация — Добавление избыточных (дублированных) данных для повышения скорости чтения.

10. Первая нормальная форма (1NF) — Устранение повторяющихся групп; каждая ячейка содержит атомарное значение.

11. Вторая нормальная форма (2NF) — Устранение частичных зависимостей от составного ключа.

12. Третья нормальная форма (3NF) — Устранение транзитивных зависимостей (неключевые столбцы не зависят от других неключевых столбцов).

13. Суррогатный ключ — Системно-сгенерированный идентификатор (например, UUID или auto-increment ID).

14. Естественный ключ — Уникальный идентификатор из реального мира (например, email или номер паспорта).

15. Составной ключ — Первичный ключ, состоящий из нескольких столбцов.

16. Уникальное ограничение — Обеспечивает уникальность значений в столбце (или группе столбцов).

17. Допустимость NULL — Возможность хранить в столбце NULL (т.е. отсутствие значения).

18. Ограничение по значению — Проверяет значения в столбце на соответствие условиям (например, age > 0).

19. Индекс — Повышает производительность поиска за счёт ускоренного доступа к данным.

20. Схема — Структура/определение таблиц, полей, типов и связей в базе данных.

21. ERD (диаграмма "сущность-связь") — Визуальное представление сущностей и их связей.

22. Кардинальность — Количество строк, которое может быть связано в рамках связи.

23. Тип данных — Определяет, какие значения может хранить столбец (например, INT, VARCHAR, DATE).

24. Перечисление — Поле, значение которого ограничено предопределённым набором (например, status = [pending, complete]).

25. Мягкое удаление — Пометка записи как удалённой без фактического удаления (например, deleted_at).

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
Spring Boot: HTTP-клиенты через интерфейсы с @HttpExchange.

Аннотируйте интерфейс — Spring Boot создаст клиентскую реализацию
Настройте тайм-ауты/SSL с помощью свойств spring.http.clients.*

#SpringBoot4 #HttpExchange

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍62
Утверждение «Go потребляет в 4 раза меньше памяти, чем Java» в целом верно, но применимо далеко не во всех сценариях.

При нагрузке в 500 запросов в секунду сервис на Go использует около 68 МБ памяти, а JVM — около 412 МБ (BackendBytes).

Но при 1 миллионе конкурентных задач ситуация меняется на противоположную: Java использует около 800 МБ, а Go — примерно 2,5 ГБ (WebDev|today).

«Победитель» по потреблению памяти зависит от конкретной нагрузки.

Именно поэтому нельзя просто разбрасываться случайными цифрами без учёта контекста.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥4
Хотите стать backend-инженером, которого в 2026 году захотят нанять компании уровня Google, Uber, Netflix и Stripe?

Тогда изучите:

## Сети

- DNS
- TCP/IP
- HTTP/2
- HTTP/3
- TLS

## Внутреннее устройство баз данных

- B+-деревья
- MVCC
- WAL
- оптимизаторы запросов
- индексы

## Проектирование API

- REST
- gRPC
- GraphQL
- идемпотентность
- пагинация

## Распределённые системы

- теорема CAP
- консенсус
- репликация
- CQRS
- Saga

## Событийно-ориентированная архитектура

- Kafka
- Outbox Pattern
- CDC
- потоковая обработка событий

## Инженерия производительности

- пулы соединений
- кэширование
- асинхронный ввод-вывод
- профилирование

## Cloud Native

- Docker
- Kubernetes
- Service Mesh
- автомасштабирование

## Наблюдаемость

- OpenTelemetry
- Prometheus
- Grafana
- ELK

## Безопасность

- OAuth 2.0
- JWT
- mTLS
- Zero Trust
- OWASP Top 10

## Production Engineering

- Blue-Green Deployments
- Canary Releases
- Chaos Engineering
- Disaster Recovery

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
7🤯2👀2
Ты на интервью по системному дизайну. Спрашивают: «Как бы ты спроектировал слой кэширования для высоконагруженного веб-приложения?»

Вот подробный подход:

I. Что кэшировать → Кэшируй дорогие запросы к БД, горячие данные с большим количеством чтений и статические ресурсы; избегай очень динамичных, гигантских объектов или чувствительной PII, если только она не зашифрована и не защищена доступом.

II. Хранилище кэша → Используй Redis или Memcached для распределённого in-memory кэша, CDN для статики на краю сети, локальные in-process кэши (например, Caffeine) для сверхнизкой задержки L1.

III. Паттерн и запись → По умолчанию Cache-Aside: читаем из кэша, при промахе читаем из БД и заполняем кэш. Для сильной консистентности чтения — Write-Through (пишем одновременно в кэш и БД). Всегда сначала коммитим БД, потом обновляем/инвалидируем кэш, чтобы не дать устаревшим данным просочиться.

IV. Истечение и вытеснение → TTL для каждого типа данных, чтобы держать кэш свежим, политики вытеснения (LRU/LFU) для управления памятью, negative caching для промахов, чтобы не перегружать БД. Ограничивай размер объектов, чтобы не создавать проблемы с памятью и сборкой мусора.

V. Масштабирование и «горячие ключи» → Масштабируй через consistent hashing и реплики для пропускной способности чтения. Многоуровневый кэш (edge→regional→local). Горячие ключи — локальные L1 кэши, отдельные кэши для горячих ключей, либо rate-limiting запросов.

VI. Надёжность и наблюдаемость → Предотвращай «каскады» промахов через request coalescing, короткие блокировки (SETNX + expiry) или serve-stale-while-revalidate с jittered TTL. Мониторь hit rate, latency, eviction, память и replication lag с алертами.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Иногда я удивляюсь тому, насколько Java и C# похожи.

Оба языка работают в управляемой среде выполнения с JIT-компиляцией и сборкой мусора: JVM для Java и CLR для C#.

Оба имеют строгую статическую типизацию. Я также нашёл статью, в которой говорится, что к 2026 году даже разрыв в возможностях языков практически исчез: records, pattern matching, primary constructors и так далее.

Java Code Geeks, «The Feature Gap Has Closed», 2026.

Какой язык вы предпочитаете и почему?

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM