uz
Feedback
Максим Добрынин | Как стать востребованным Java разработчиком | ex. Jetbulb

Максим Добрынин | Как стать востребованным Java разработчиком | ex. Jetbulb

Kanalga Telegram’da o‘tish

IT community с полезными материалами о программировании, технических собеседованих и рабочих буднях в IT. Авторский контент от @maksymdobrynin

Ko'proq ko'rsatish
4 919
Obunachilar
Ma'lumot yo'q24 soatlar
-77 kunlar
-2130 kunlar
Obunachilarni jalb qilish
Iyun '26
Iyun '26
+33
0 kanalda
May '26
+63
0 kanalda
Get PRO
Aprel '26
+62
0 kanalda
Get PRO
Mart '26
+56
0 kanalda
Get PRO
Fevral '26
+69
0 kanalda
Get PRO
Yanvar '26
+220
0 kanalda
Get PRO
Dekabr '25
+55
0 kanalda
Get PRO
Noyabr '25
+70
0 kanalda
Get PRO
Oktabr '25
+80
0 kanalda
Get PRO
Sentabr '25
+97
0 kanalda
Get PRO
Avgust '25
+152
0 kanalda
Get PRO
Iyul '25
+106
0 kanalda
Get PRO
Iyun '25
+86
0 kanalda
Get PRO
May '25
+113
0 kanalda
Get PRO
Aprel '25
+131
0 kanalda
Get PRO
Mart '25
+145
0 kanalda
Get PRO
Fevral '25
+113
0 kanalda
Get PRO
Yanvar '25
+108
0 kanalda
Get PRO
Dekabr '24
+110
0 kanalda
Get PRO
Noyabr '24
+121
0 kanalda
Get PRO
Oktabr '24
+108
0 kanalda
Get PRO
Sentabr '24
+109
0 kanalda
Get PRO
Avgust '24
+170
0 kanalda
Get PRO
Iyul '24
+183
0 kanalda
Get PRO
Iyun '24
+100
0 kanalda
Get PRO
May '24
+107
0 kanalda
Get PRO
Aprel '24
+152
0 kanalda
Get PRO
Mart '24
+209
0 kanalda
Get PRO
Fevral '24
+163
0 kanalda
Get PRO
Yanvar '24
+173
0 kanalda
Get PRO
Dekabr '23
+121
0 kanalda
Get PRO
Noyabr '23
+119
0 kanalda
Get PRO
Oktabr '23
+164
0 kanalda
Get PRO
Sentabr '23
+144
0 kanalda
Get PRO
Avgust '23
+181
0 kanalda
Get PRO
Iyul '23
+170
0 kanalda
Get PRO
Iyun '23
+148
0 kanalda
Get PRO
May '23
+131
0 kanalda
Get PRO
Aprel '23
+148
0 kanalda
Get PRO
Mart '23
+223
0 kanalda
Get PRO
Fevral '23
+196
0 kanalda
Get PRO
Yanvar '23
+260
0 kanalda
Get PRO
Dekabr '22
+145
0 kanalda
Get PRO
Noyabr '22
+186
0 kanalda
Get PRO
Oktabr '22
+282
0 kanalda
Get PRO
Sentabr '22
+195
0 kanalda
Get PRO
Avgust '22
+435
0 kanalda
Get PRO
Iyul '22
+225
0 kanalda
Get PRO
Iyun '22
+92
0 kanalda
Get PRO
May '22
+126
0 kanalda
Get PRO
Aprel '22
+657
0 kanalda
Sana
Obunachilarni jalb qilish
Esdaliklar
Kanallar
30 Iyun+1
29 Iyun0
28 Iyun+2
27 Iyun+2
26 Iyun0
25 Iyun+1
24 Iyun+1
23 Iyun+1
22 Iyun+1
21 Iyun0
20 Iyun0
19 Iyun+1
18 Iyun+2
17 Iyun+2
16 Iyun+2
15 Iyun+1
14 Iyun0
13 Iyun0
12 Iyun+1
11 Iyun+1
10 Iyun+4
09 Iyun+3
08 Iyun0
07 Iyun0
06 Iyun+1
05 Iyun+1
04 Iyun+1
03 Iyun+2
02 Iyun+2
01 Iyun0
Kanal postlari
📌 Takeaway Rate limiting отлично интегрируется в API Gateway (например, на уровне ingress), Reverse Proxy, Redis для горизонтального масштабирования либо внутри приложения, если логика связана с данными, которые удерживает сам сервис. Стоит помнить, что распределенных системах предпочтение необходимо отдавать глобальными лимитам, а не локальным. Не стоит забывать и о компромиссах (trade-off) между: уровень защиты и удобство пользователей, устойчивость и производительность системы, проста и распределенность. Макс Добрынин Software Engineer ⬇️ Поделишься своим списком задач по проектированию и разработке? Пиши о своем опыте в комментариях. 👍 Понравился этот пост? Подписывайся, ставь лайк и поделись постом с другом или коллегой. Курс по Kubernetes | Курс по разработке и проектированию микросервисной архитектуры | Групповая практика по разработке микросервисной архитектуры | Java Roadmap | Задать вопрос менеджеру | Отзывы

2
📚Шаблон проектирования Rate limiting для защита API от перегрузки Привет, всем! Макс вещает 😼 Мне часто приходится говорить о шаблонах проектирования применяемых в микросервисной архитектуре. И я обратил внимание, что все знают Saga, Outbox, Idempotency, но все игнорируют Rate limiting, хотя он применяется очень часто. Сегодня говорим о том, что такое Rate limiting и когда его надо применять. Rate limiting – это базовый, но критически важный механизм защиты API. Его задача заключается в ограничении количество запросов от клиента за определенный период времени. Без него даже хорошо спроектированная система может прийти в негодонсти под влиянием высокой нагрузки – как от реальных пользователей, так и от ботов, которые регулярно спамят публично доступные URL. 🔹Зачем нужен Rate limiting? Во-первых, это защита от перегрузки. Если один клиент начинает слать тысячи запросов в секунду, то это может привести к потреблению всех ресурсов системы (ЦПУ, память, соединения с БД и др.). Во-вторых, это контроль справедливости между параллельными пользователями. Rate limiting гарантирует, что чрезмерная активность одного пользователя не ухудшает опыт других. В-третьих, это защита от злоумышленников. Например, Brute Force Attack, DDoS, Scraping, и др. виды. 🔹Как это работает на практике? Идея простая: во время обработки каждого запроса, система проверяет не превысил ли клиент отведенный ему лимит. Такая проверка основана на определенных алгоритмах (об этом позже). Так например, клиент может определяться на основе API Key, UserID, IP Address, и др. характеристики. В итоге, если лимит превышен, то API отвечает на запрос с ошибкой, как правило – 429 Too Many Requests. 🔹А какие есть алгоритмы реализации Rate limiting? Первым будет Fixed Window, где клиенту отводится строго зафиксированный лимит активности. Например, 100 запросов в минуту. Но, есть проблема, на границе окна возможна вспышка активности – 100 запросов в конце минуты и еще 100 в начале следующей. Это будет слабой точкой такой системы, где может привести к ее падению. Следующий – Sliding Window. Такая реализация Rate limiting использует знаменитый алгоритм Sliding Window (почему? см. тут), который позволяет смещать окно динамически, одновременно удерживая баланс между лимитом и временем в рамках котором он существует. Это позволяет сгладить проблему Fixed Window, учитывая предыдущие запросы, но реализация намного сложнее. Тройку завершает Token Bucket. Такой алгоритм предоставляет клиенту количество токенов, где один расходует на один запрос. Эти токены восполняются с течением времени. Тут все еще остается окно для резких вспышек количества запросов, но при этом они будут кратковременны, а средняя нагрузка станет контролируемой. 🔹Простой пример на основе Spring Boot и Resilience4j Здесь мы ограничиваем вызов метода и при превышении лимита возвращаем понятный ответ клиенту: @RestController @RequestMapping("/api/orders") public class OrderController { @GetMapping("/{id}") @RateLimiter(name = "ordersApi", fallbackMethod = "rateLimitFallback") public ResponseEntity<String> getOrder(@PathVariable String id) { return ResponseEntity.ok("Order: " + id); } public ResponseEntity<String> rateLimitFallback(String id, RequestNotPermitted ex) { return ResponseEntity.status(429).body("Too many requests. Please try again later."); } } Сейчас установлено ограничение – каждую секунду не более 5 запросов. Если приходит шестой, Resilience4j не пропускает его дальше и выбрасывает RequestNotPermitted, после чего срабатывает метод fallback. В результате чего клиент получает ожидаемый HTTP Status 429. Но здесь есть важный нюанс, такой Rate limiting работает внутри конкретного экземпляра приложения. Если у вас сервис масштабирован горизонтально, то фактический лимит уже будет не 5 запросов в секунду, а примерно 25. Поэтому для распределенной системы локальный Rate limiting не всегда решает задачу полностью. В таких случаях обычно используют Redis, API Gateway или ingress с общим состоянием лимитов.
0
3
💡 Главный навык, который отличает дорогих разработчиков Можно посмотреть очень просто. На то, как человек работает с проблемой⬇️ Один разработчик: 🔹 получил задачу 🔹 написал код 🔹 закрыл тикет Вроде всё ок. Другой: 🔹 задал вопросы 🔹 понял, где эта задача в системе 🔹 предложил решение 🔹 подумал о последствиях 🔹 только потом начал писать И вот это уже другой уровень. По сути оба могут: — знать Spring — работать с БД — писать норм код Разница в том, что один: 👉 выполняет А второй: 👉 разбирается Давайте на реальном примере⬇️ Ситуация: нужно добавить новую фичу. Разработчик уровня “обычный”: 🔹 “ок, сделаю endpoint” 🔹 “добавлю таблицу” 🔹 “готово” Разработчик уровнем выше: 🔹 “а это точно отдельный сервис?” 🔹 “а что будет при росте нагрузки?” 🔹 “как это повлияет на другие части системы?” 🔹 “где тут потенциальные проблемы?” Он думает не про код, а про реальные последствия. Сейчас ценятся те, кто: — заранее видит проблемы — снижает риски — не создаёт технический долг ⚡️ Большинство разработчиков привыкают работать так: — дали задачу → сделал — дали задачу → сделал И это становится автоматизмом. Но на самом деле это тупик. 📌 Простая проверка Если тебе дать задачу, ты: сразу идёшь писать код или сначала пытаешься понять систему? Вот здесь и проходит граница Курс по Kubernetes | Курс по разработке и проектированию микросервисной архитектуры | Групповая практика по разработке микросервисной архитектуры | Java Roadmap | Задать вопрос менеджеру | Отзывы
0
4
🤚 Преподаватель курса по Kubernetes - Максим Добрынин И это главное, что нужно понимать😉 Если вы уже смотрели его разборы: — по архитектуре — по системному дизайну — по техническим интервью то уже прекрасно знаете, какой там уровень. Это не формат: “прочитал документацию → пересказал” Это человек, который: — работает с реальными системами — сталкивается с продакшеном — понимает, как всё ломается в жизни, а не в теории — и умеет объяснить это нормально Одна из самых частых обратных связей: “Наконец-то стало понятно, как это работает” Потому что объяснение идёт не через термины, определения и сухую теорию. А через логику, систему и реальные кейсы 🎉 И мы рады объявить, что ближайший поток будет вести сам Максим. Курс по Kubernetes не про: “вот pod, вот deployment” А про: 🔹как работает система внутри 🔹как сервисы живут в Kubernetes 🔹что происходит при деплое 🔹где искать проблемы 🔹как мыслить, когда что-то падает Это ровно тот уровень, который отличает: “я запускал Kubernetes” от “я понимаю, что происходит” 🗓 Старт — 27 апреля По опыту такие группы закрываются быстрее всего. 👉 Подробности и запись: https://iprody.com/microservices-java 💬 Задать вопрос / забронировать место: https://t.me/iprody_online Если давно хотел разобраться в Kubernetes — лучше заходить именно в такие форматы.
0
5
📚Юнит тесты vs. Интеграционные тесты — где на самом деле проходит граница? На самом деле это один из самых «скользких» вопро
📚Юнит тесты vs. Интеграционные тесты — где на самом деле проходит граница? На самом деле это один из самых «скользких» вопросов. Почти все могут дать определение юнит тестами или интеграционным тестами. Проблемы начинаются, когда просят объяснить разницу между ними на практике И это именно то место, где начинается путаница. Суть в том, что граница между юнит и интеграционными тестами не является столько технической, сколько контекстуальной в рамках покрываемого кода. ➖ Для того, чтобы разобраться начнем с простого – классическое определение. Юнит тесты призваны тестировать одну изолированную единицу кода (метод, класс). В данном случае, все зависимости заменены на моки и/или стабы. Интеграционные тесты напротив, проверяют взаимодействие компонентов между собой. Например, как Payment Service взаимодействует с Payment Repository, где вероятно может быть реальное соединение с тестовой базой данных. Другими словами, главное — изолирован ли код от внешнего мира. Звучит просто. Но давайте попробуем найти больше различий⬇️ ➖ Основные различия Юнит тесты обладают следующими характеристиками, которые позволяют их отделить от интеграционных тестов и как следствие, выделить их скорость выполнения, легко реализации и как результат дешевизну их поддержки. 🔹Изоляция кода от других компонент 🔹Скорость выполнения (обычно миллисекунды) 🔹Стабильность и надежность 🔹Просто реализации и эксплуатации 🔹Проверяют бизнес-логику отдельно взятой компоненты Интеграционные тесты в свою очередь призваны проверять взаимодействие отдельно взятых компонент между собой, что позволяет выявить отклонения, которые невозможно обнаружить в изолированной среде. 🔹Проверка взаимодействия 🔹Средняя и высокая скорость выполнения 🔹Хрупки и нестабильные (сетевые проблемы, несогласованность версий между зависимостями) 🔹Отлавливают реальные проблемы конфигурации ➖ Что выбрать юнит тесты или интеграционное тесты? Тут не может быть однозначного выбора в пользу юнит тестов или интеграционных. Каждый из этих двух уровней тестирования отвечает за качество кода в строго отведенном контексте – они дополняют один другого. Так например, юнит тесты не гарантируют, что система реально работает, поскольку они не могут проверить: синтаксис SQL-запроса, верность конфигурации приложения написанного на Spring Boot, совместимости двух сервисов использующих один API, и многие другие проблемы. Все это покрывается на уровне интеграционных тестов. И наоборот — только интеграционные тоже плохо. Поскольку они часто медленно работают, имеют сложные зависимости, минимизируют шанс на локализацию (изоляцию) проблемы, более сложны в реализации и поддержке. 📌 Вывод Граница между юнит тестами и интеграционными тестами проходит по уровню изоляции. Первые полностью изолируют код через моки (или стабы), тогда как вторые проверяют взаимодействие с реальными зависимостями. Очень важно помнить, что тесты различных уровней должны дополнять друг друга, а не дублировать. И это может быть хорошим индикатором для ревизии уровня изоляции. Потому, важно не противопоставлять их друг другу, а правильно комбинировать для достижения максимально эффективного покрытия кода и высокого качества в продакшене. ⬇️Как ты измеряешь уровень покрытия тестами реализованного тобой решения? Пиши о своем опыте в комментариях. 👍 Понравился этот пост? Подписывайся, ставь лайк и поделись постом с другом или коллегой. Курс по Kubernetes | Курс по разработке и проектированию микросервисной архитектуры | Групповая практика по разработке микросервисной архитектуры | Java Roadmap | Задать вопрос менеджеру | Отзывы
0
6
🔥 Как готовится к прохождению собеседования по системному дизайну? Вы знаете технологии. Понимаете архитектуру. Работаете с
🔥 Как готовится к прохождению собеседования по системному дизайну? Вы знаете технологии. Понимаете архитектуру. Работаете с продакшеном. Но на System Design — отказ. И причина почти никогда не в знаниях. System Design — это не про Kafka, Redis и микросервисы. Это про: — умение задавать вопросы — понимание бизнеса — работу с требованиями — аргументацию решений — компромиссы В новом видео разобрал: • главные ошибки разработчиков • как правильно проходить System Design интервью • как мыслить, чтобы получить оффер • почему даже сильные кандидаты проваливаются Если вы готовитесь к собеседованиям — обязательно посмотрите: https://youtu.be/FwznJBVRypc
0
7
❓Почему Two-phase commit (2PC) редко используют в реальных системах? На интервью по системному дизайну Two-phase commit (дале
❓Почему Two-phase commit (2PC) редко используют в реальных системах? На интервью по системному дизайну Two-phase commit (далее 2PC) часто звучит как очевидное решение для случаев, когда существует несколько сервисов или баз данных и необходимо сделать распределенную транзакцию с обеспечением согласованности данных. Но на практике 2PC почти не используют. Давайте разберемся почему⬇️ ➖ Как работает 2PC? Всегда есть координатор и участники распределенной транзакции. Сам процесс разделен на несколько этапов: 🔹Стадия подготовки – координатор спрашивает: «все готовы закоммитить?» 🔹Стадия согласования – участники блокируют ресурсы и отвечают «да» или «нет» 🔹Стадия выполнения – если все согласны, координатор отправляет сигнал на выполнение Такой алгоритм звучит надежно. Но, он начинает рассыпаться, когда начинаются проблемы связанные с распределенными системами. Давайте разберемся с чем именно приходится иметь дело. ➖ Блокировки и деградация производительности Во время подготовительной стадии участники блокируют данные и ждут решения координатора. Если координатор испытывает нагрузку или происходит сетевая задержка, то это приводит к следующим негативным факторам: 🔹увеличивает скорость выполнения транзакция на местах (latency) 🔹ресурсы блокируются на длительное время 🔹падает уровень пропускной способности (throughput) Такой негативный фактор может быть критическим моментом для высоконагруженных систем с малым временем отклика. ➖ Single Point of Failure (SPOF) Координатор – центральный элемент. Если он выходит из строя после подготовительной стадии, то участники не знают об этом и не могут принять решение: отклонить транзакцию или закоммитить. Хуже, участники могут остаться в состоянии ожидания на длительное время. Эту проблему принято называть “blocking problem” и она является ключевым недостатком 2PC. ➖ Плохая масштабируемость 2PC требует синхронной координации между всеми участниками. Большое количество сервисов-участников будет неизбежно увеличивать время ожидания (latency). В итоге, каждый участник влияет на общую транзакцию, что делает всю систему уязвимой к сбоям. Такой подход сам по себе противоречит принципам распределенных систем, где в основу ложится независимость отдельно взятых компонент между собой. ➖ CAP-теорема на практике Целью 2PC является обеспечение полной согласованности данных (strong consistency). Это приводит к необходимости принятия компромисса, что в итоге выражается в понижении уровня доступности (availability) и слабой устойчивости к сетевым сбоям. В случае возникновения проблемы система предпочитает ожидать, а не работать. Этот фактор может быть критическим моментом для определенных систем, где доступность и устойчивость является более предпочтительными характеристиками. 📌 Что же тогда использовать вместо 2PC? В реальных системах выбор чаще всего падает на: Saga pattern (оркестрация или хореография), событийно-ориентированную архитектуру, механизм повторов и идемпотентности, а также Outbox pattern. Иначе говоря, согласованность данных со временем (eventual consistency) вместо глобальной согласованности (strong consistency). ⬇️А ты понимаешь когда необходим eventual consistency, а когда strong consistency? Пиши о своем опыте в комментариях. 👍 Понравился этот пост? Подписывайся, ставь лайк и поделись постом с другом или коллегой. Курс по Kubernetes | Курс по разработке и проектированию микросервисной архитектуры | Групповая практика по разработке микросервисной архитектуры | Java Roadmap | Задать вопрос менеджеру | Отзывы
0
8
🍃Пропагация транзакции между вызовами в Spring Framework На собеседованиях по Java и Spring очень любят спрашивать про @Transactional. Почти все знают про уровни изоляции, но когда разговор заходит о передачи контекста транзакции между вызовами методов (речи идет о параметре Propagation), то ответы резко становятся поверхностными. Хотя именно propagation определяет, что произойдет с транзакцией при вложенных вызовах. Для того, чтобы понять проблему, представим простой сценарий: ctional. Почти все знают про уровни изоляции, но когда разговор заходит о передачи контекста транзакции между Ответ: зависит от параметрау вызовами в Sp примененного к аннотацииежду вызовами в Sp ➖Так что же необходимо знать о параметреpring Framework 🔹REQUIRED (по умолчанию) Самый распространённый режим. Если транзакция уже есть — метод просто присоединяется к ней. В противном случае, создается новая транзакция. Это удобно, но здесь есть важный нюанс: если внутри вложенного метода происходит исключение и транзакция помечается как rollback-only, внешний код может этого не ожидать. В итоге можно получить неожиданный rollback в конце выполнения. 🔹REQUIRES_NEW Всегда создает новую транзакцию, даже если уже есть активная. Текущая транзакция при этом приостанавливается. Это полезно, например, для логирования или аудита: даже если основная операция завершается ошибкой, то запись в лог сохранится. 🔹NESTED Создает вложенную транзакцию черезбходимо знать(если поддерживается СУБД). Если выполнение вложенного метода завершается ошибкой, то откатывается только он, а не вся транзакция. Важно, это не полноценная независимая транзакция, как в REQUIRES_NEW. 🔹SUPPORTS / NOT_SUPPORTED / NEVER Менее популярные, но иногда встречаются: SUPPORTS — работает в транзакции, если она есть, NOT_SUPPORTED — выполняется без транзакции, даже если она была, NEVER — выбрасывает исключение, если транзакция есть. ➖Самое важное, что часто упускают Аннотация @Transactional работает через прокси. Все вызовы внутри одного класса не учитывают propagation, аПропагация тпо умолчанию происходит только для исключений типаamework На собеседо Также стоит учитывать, чтоду вызовами в Sвлияет не только на БД, но и на границы согласованности всей операции целиком. ⬇️А тебе уже приходилось разбирать на собеседовании аннотацию @Transactional? Пиши о своем опыте в комментариях. 👍 Понравился этот пост? Подписывайся, ставь лайк и поделись постом с другом или коллегой.
0
9
🔥 Последние 2 места на Курс по проектированию и разработке микросервисной архитектуры 2.0 Старт — 6 апреля. Подробнее про курс в посте или на сайте ⬇️Новый курс про то, как: — проектировать систему вокруг бизнес-домена (DDD) — строить Event-Driven архитектуру — управлять распределёнными транзакциями (Saga / Outbox) — обеспечивать гарантии доставки сообщений — проектировать отказоустойчивость (Circuit Breaker, Retry, Bulkhead) — строить масштабируемую архитектуру, готовую к росту нагрузки 🎯 Кому особенно актуально Если вы: 🔹 действующий разработчик 🔹 работаете с монолитом или простыми сервисами 🔹 чувствуете пробелы в архитектуре 🔹 хотите перейти на уровень Middle+ / Senior 🔹 готовитесь к сильным компаниям — этот курс даст системность. ⬇️ Что будет на выходе — понимание распределённой архитектуры — практическая реализация паттернов — опыт проектирования, а не просто кодинга ⌛️ Осталось 2 места Группа изначально формируется небольшой, чтобы сохранить качество архитектурных разборов и обратной связи. Старт — уже 6 апреля. 👉 Подробности и запись: https://iprody.com/microservices-java 💬 Задать вопрос / забронировать место: https://t.me/iprody_online Если давно хотели закрыть пробел в микросервисной архитектуре — сейчас правильный момент.
0
10
🔥 ТОП 5 вещей, которые реально усилят твоё резюме Не “ещё один фреймворк” и даже не “курс по аннотациям”. А то, что реально влияет на офферы. Давайте смотреть👇 1️⃣ Опыт разработки системы, а не разные фичи На самом деле разница огромная. ❌ “делал сервис” ✔️ “участвовал в проектировании системы из N микросервисов” Если ты не можешь описать систему — для рынка ты просто исполнитель. 2️⃣ Архитектурные решения Не: “использовал Kafka”, а: 🔹 зачем выбрали Kafka 🔹 какие были альтернативы 🔹 какие trade-offs Это сразу поднимает уровень. 3️⃣ Командная разработка Рынку важно: 🔹 работал ли ты в команде 🔹 проходил ли Code Review 🔹 участвовал ли в обсуждениях Одиночные проекты почти не ценятся. 4️⃣ Работа с продакшеном Любой опыт, где ты: 🔹 деплоил 🔹 разбирал падения 🔹 работал с логами 🔹 чинил проблемы сильно выделяет тебя среди кандидатов. 5️⃣ Понимание системы Самый недооценённый навык среди разработчиков. Можешь ли ты объяснить: 🔹 как работает система 🔹 где узкие места 🔹 что сломается при нагрузке Если да — ты уже выше 80% кандидатов. 📌 В чём суть? Резюме усиливают не технологии. Резюме усиливает опыт, который показывает: — ты думаешь — ты понимаешь — ты принимаешь решения Курс по Kubernetes | Курс по разработке и проектированию микросервисной архитектуры | Групповая практика по разработке микросервисной архитектуры | Java Roadmap | Задать вопрос менеджеру | Отзывы
0
11
❓Почему сообщения дублируются при доставке At-least-once Гарантия at-least-once delivery (доставка «как минимум один раз») ча
❓Почему сообщения дублируются при доставке At-least-once Гарантия at-least-once delivery (доставка «как минимум один раз») часто встречается в в качестве решения. На первый взгляд звучит надежно и создается впечатление, что это сообщение точно не потеряется. Но у этой гарантии есть важное следствие — дубликаты неизбежны. Разберёмся, почему это происходит. В основе лежит простая идея: брокер сообщений считает сообщение доставленным только после получения подтверждения (ack) от потребителя. Пока ack не получен, сообщение считается «необработанным» и может быть отправлено повторно. Типичный сценарий дублирования выглядит так: 🔹Потребитель получает сообщение 🔹Успешно обрабатывает его (например, записывает в базу) 🔹Но не успевает отправить ack (или ack теряется) 🔹Брокер сообщений считает, что сообщение не обработано 🔹И совершает повторную попытку отправки В результате одно и то же сообщение обрабатывается дважды. Важно понимать: с точки зрения брокера всё корректно. Он действует по контракту — «лучше отправить ещё раз, чем потерять». ➖ Какие существуют причины неполучения ack? 🔹сбой сети между консьюмером и брокером сообщений 🔹ошибка в консьюмере после обработки, но до отправки ack 🔹таймаут обработки (visibility timeout в SQS, session timeout в Kafka) 🔹ребалансировка Вот отсюда и происходит природа дупликаторов при различного рода коммуникациях, включая асинхронную. ➖ Что с этим делать? Главный подход — идемпотентность. Обработчик должен уметь безопасно обрабатывать одно и то же сообщение несколько раз. На практике это реализуется так: 🔹использование уникального ключа для контроля уникальности 🔹хранение обработанных запросов в БД 🔹обновление вместо вставки в БД Например, если сообщение создает заказ, перед его созданием будет выполнена проверка на возможность его существования в системе. В случае детекции дубликата, такого сообщение будет игнорироваться и пользователю вернется ответ связанный уже с ранее обработанным сообщением. 📌 Вывод При доставке At-least-once сообщения могут дублироваться, потому что брокер сообщений повторно отправляет их, если не получил подтверждение обработки. Это может происходить из-за сбоев сети или недоступности консьюмера. Поэтому обработчики входящих сообщений должны быть идемпотентными. Это фундаментальный компромисс между надежностью и уникальностью доставки. ⬇️ А тебе уже приходилось реализовывать системы и предусматривать гарантии доставки? Пиши о своем опыте в комментариях. 👍 Понравился этот пост? Подписывайся, ставь лайк и поделись постом с другом или коллегой. Курс по Kubernetes | Курс по разработке и проектированию микросервисной архитектуры | Групповая практика по разработке микросервисной архитектуры | Java Roadmap | Задать вопрос менеджеру | Отзывы
0