Java Portal | Программирование
12.4K subscribers
1.1K photos
90 videos
36 files
964 links
Присоединяйтесь к нашему каналу и погрузитесь в мир для Java-разработчика

Связь: @devmangx

РКН: https://clck.ru/3H4WUg
Download Telegram
Если ты когда-нибудь писал что-то вроде этого в Java:

List<String> stringList = map.get(key);
if (stringList == null) {
stringList = new ArrayList<String>();
map.put(key, stringList);
}
stringList.add(newElement);


То то же самое можно записать в одну строку:

map.computeIfAbsent(key, k -> new ArrayList<String>()).add(newElement);


А ещё короче так:

map.computeIfAbsent(key, k -> new ArrayList<>()).add(newElement);


Компилятор Java сам поймёт, какой тип ArrayList нужно создать, исходя из типа Map
(в данном случае Map<String, List<String>>).

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍203
Docker это не мини-виртуальные машины

Многие пользуются Docker каждый день, но не особо понимают, что происходит под капотом. Это становится очевидно, когда начинаются проблемы с производительностью, правами доступа или сетью.

1. Docker — это не виртуалка

Когда ты запускаешь docker run ubuntu, ты не создаешь «мини-компьютер».

Никакого нового ядра нет.
Контейнер использует то же ядро, что и хост — просто в изоляции.

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

2. Изоляция достигается через namespaces

Namespace говорит системе:
«Этот процесс видит только вот этот кусочек мира».

Примеры:

PID namespace — контейнер думает, что его процесс 1 — единственный.

NET namespace — у контейнера своя сеть и интерфейсы.

MNT namespace — своя файловая система с примонтированными ресурсами.

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

3. Cgroups ограничивают ресурсы

Контейнер может считать, что владеет всей машиной…
но control groups (cgroups) ставят реальные лимиты:

- максимум CPU (--cpus=2)
- максимум памяти (--memory=1g)
- лимиты на I/O или количество процессов

Если контейнер пытается выйти за рамки, ядро его просто отрубает 😅

4. Файловая система и слои (UnionFS)

Образ это не один файл, а набор слоев.
Каждая инструкция RUN, COPY или ADD в Dockerfile создает новый слой.

Когда контейнер запускается, поверх монтируется временный слой для записи.

Вот почему все изменения исчезают после удаления контейнера —
временный слой просто выкидывается.

5. Как контейнеры общаются между собой

Docker создает виртуальные сети внутри хоста.
Каждый контейнер получает свой внутренний IP.

Когда ты используешь --link или docker-compose,
ты просто задаешь внутренние DNS-имена.

Во внешний мир трафик не выходит,
пока ты сам не пробросишь порт через -p 8080:80.

6. Безопасность -изоляция не идеальна

Поскольку ядро общее, защита не такая жесткая, как у виртуалки.

Для этого и придуманы штуки вроде:

gVisor — песочница для системных вызовов
SELinux или AppArmor
rootless Docker

Если запускаешь сторонние контейнеры — лучше использовать их.

Так что же такое Docker на самом деле?

Это оркестратор изоляции:

- прячет ресурсы через namespaces
- ограничивает их через cgroups
- управляет файловой системой через UnionFS
- эмулирует сеть через network namespaces

Он ничего не эмулирует по-настоящему,
он просто создает очень правдоподобную иллюзию 👏

Понимание этого полностью меняет подход к дебагу и оптимизации.

Контейнер жрет всю оперативку? → смотри cgroups.
Не может подключиться к сети? → проверь network namespace.
Билды весят по 5 ГБ? → разбери слои образа.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍152
Представим, что тебе нужно посчитать максимальную зарплату сотрудников по отделам на Java. Код мог бы выглядеть так:

List<Employee> employees = new ArrayList<>();
Map<String, Long> maxMap = new HashMap<>();

for (Employee employee : employees) {
Long maxSalaryForDepartment = maxMap.get(employee.department);
if (maxSalaryForDepartment == null || maxSalaryForDepartment < employee.salary) {
maxMap.put(employee.department, employee.salary);
}
}


Но этот цикл можно записать гораздо короче:

for (Employee employee : employees) {
maxMap.merge(employee.department, employee.salary, Math::max);
}


Метод Map.merge() работает так:

Первый параметр — это ключ, по которому ты хочешь добавить или обновить значение в Map.

Второй параметр — новое значение, которым нужно обновить сохранённое.
Если для этого ключа значение отсутствует (или там null), Map просто сохраняет новое значение.

Третий параметр — это функция. Если в Map уже есть значение для этого ключа, функция вызывается с двумя аргументами: старым и новым значением. То, что вернёт эта функция, и будет записано как новое значение для ключа.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥113
Экосистема разработки API с открытым исходным кодом

https://github.com/hoppscotch/hoppscotch/

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
Паттерны микросервисов для Java / Backend-разработчиков

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

🔸Application Architecture Patterns
Высокоуровневые схемы структуры систем:
- Monolithic architecture
- Microservice architecture

🔸 External API Patterns
Подходы к проектированию API для сторонних разработчиков:
- API Gateway
- Backends for Frontend (BFF)

🔸Decomposition Patterns
Как разделить большую систему на независимые сервисы:
- Decompose by business capability
- Decompose by subdomain

🔸Testing Patterns
Подходы к проверке корректности микросервисов:
- Consumer-driven contract test
- Consumer-side contract test
- Service component test

🔸Messaging Style Patterns
Схемы асинхронного взаимодействия сервисов:
- Messaging
- Remote Procedure Invocation (RPI)

🔸Security Patterns
Решения для аутентификации и авторизации:
- Access Token

🔸Reliable Communication Patterns
Техники обработки сбоев при взаимодействии сервисов:
- Circuit Breaker

🔸Cross-cutting Concerns Patterns
Обработка общих функций вроде логирования и метрик:
- Externalized Configuration
- Microservice Chassis

🔸 Service Discovery Patterns
Как сервисы находят друг друга в сети:
- 3rd Party Registration
- Client-side Discovery
- Self-registration
- Server-side Discovery

🔸Observability Patterns
Как понять, что происходит внутри системы:
- Application Metrics
- Audit Logging
- Distributed Tracing
- Exception Tracking
- Health Check API
- Log Aggregation

🔸Transactional Messaging Patterns
Обеспечение согласованности данных между сервисами:
- Polling Publisher
- Transaction Log Tailing
- Transactional Outbox

🔸Deployment Patterns
Подходы к безопасному релизу новых версий сервисов:
- Deploy as Container
- Deploy as VM
- Language-specific Packaging
- Service Mesh
- Serverless Deployment
- Sidecar

🔸Data Consistency Patterns
Как управлять целостностью данных в распределённых БД:
- Saga

🔸Business Logic Design Patterns
Как организовать доменную модель и бизнес-логику:
- Aggregate
- Domain Event
- Domain Model
- Event Sourcing
- Transaction Script

🔸Refactoring to Microservices Patterns
Как поэтапно мигрировать монолит в микросервисы:
- Transaction Script
- Strangler Application

🔸Querying Patterns
Как извлекать данные из нескольких сервисов:
- API Composition
- CQRS (Command Query Responsibility Segregation)


Освой эти паттерны и ты поймёшь, как проектировать надёжные, масштабируемые и поддерживаемые системы.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
4👍2
Как отладить медленный API

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

1. Начни с сети.
Высокая задержка? Поставь CDN перед статикой. Слишком большой payload? Сжимай ответы. Это простые решения, не требующие правки кода.

2. Проверь бэкенд.
Чаще всего проблема там. Тяжелые по CPU операции нужно выносить в фон. Сложная бизнес-логика — упрощать. Синхронные блокирующие вызовы — делать асинхронными. Прогони профилирование, найди узкие места и оптимизируй.

3. Загляни в базу данных.
Отсутствующие индексы — классическая причина тормозов. Ещё одна ловушка — N+1 запросы, когда вместо одного батч-запроса база получает сотни одинаковых обращений.

4. Не забудь про внешние API.
Вызовы вроде Stripe или Google Maps не под твоим контролем. Где возможно — запускай их параллельно. Настрой агрессивные таймауты и ретраи, чтобы один медленный сторонний сервис не тормозил весь ответ.

5. Проверь инфраструктуру.
Если серверы забиты под завязку — настрой авто-масштабирование. Подкорректируй лимиты connection pool. Иногда дело не в коде, а в том, что ты пытаешься обслужить 10 000 запросов на ресурсах, рассчитанных на 100.


Главное действовать системно. Не бросайся фиксить вслепую. Сначала измерь, найди конкретное узкое место — потом исправляй.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
4👍4🔥3
На реальном собеседовании по Java задать вот такой простой вопрос — не лучший способ проверить, насколько кандидат реально разбирается в теме. Поэтому часто добавляют сценарий, чтобы оценить глубину понимания.

Как заставить три потока — T1, T2 и T3 — выполняться строго по очереди, один за другим?

Сценарий:

Ты разрабатываешь пайплайн обработки данных, который состоит из трёх этапов:

Скачивание данных с удалённого источника,

Обработка скачанных данных,

Сохранение результатов в базу данных.

Каждый этап должен выполняться в отдельном потоке, но строго последовательно: второй этап начинается только после завершения первого, а третий — только после второго. Как реализовать это, чтобы гарантировать порядок выполнения?

Подсказка:

Метод Thread.join() позволяет одному потоку дождаться завершения другого. Когда поток вызывает t.join(), он приостанавливает своё выполнение и ждёт, пока поток t не завершится.

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