Более подробное описание канала:
Здесь я буду публиковать теорию с рабочими примерами на github по различным технологиям и вопросам с собеседований, где каждый может сделать fork и предложить изменение через pull request.
Это пространство для обмена знаниями, где можно общаться на тему разработки, делиться опытом и полезными материалами, обозревать книги и доклады.
Есть идеи, которые в будущем можно реализовать:
— Проводить Mock-интервью
— Делать совместное code review
— Устраивать соревнования с вознаграждениями на самый лучший ответ на вопрос с собеседования, а также на самое лучшее решение алгоритмической задачи либо задачи на системный дизайн
По вопросам и предложениям можно писать мне — @alpa1479 либо просто оставлять комментарии под одним из постов
➿ Меню
➿ Подпишись: @developer_sandbox
Здесь я буду публиковать теорию с рабочими примерами на github по различным технологиям и вопросам с собеседований, где каждый может сделать fork и предложить изменение через pull request.
Это пространство для обмена знаниями, где можно общаться на тему разработки, делиться опытом и полезными материалами, обозревать книги и доклады.
Есть идеи, которые в будущем можно реализовать:
— Проводить Mock-интервью
— Делать совместное code review
— Устраивать соревнования с вознаграждениями на самый лучший ответ на вопрос с собеседования, а также на самое лучшее решение алгоритмической задачи либо задачи на системный дизайн
По вопросам и предложениям можно писать мне — @alpa1479 либо просто оставлять комментарии под одним из постов
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Developer's Sandbox pinned «Более подробное описание канала: Здесь я буду публиковать теорию с рабочими примерами на github по различным технологиям и вопросам с собеседований, где каждый может сделать fork и предложить изменение через pull request. Это пространство для обмена знаниями…»
Анонимный класс:
— Генерируется компилятором
— Может реализовать тип с множеством методов
— Может иметь состояние и сохранять его между вызовами методов
— Не может иметь больше одного объекта, а также иметь конструктор или быть абстрактным или реализовывать несколько интерфейсов
— Для работы с внешними локальными переменными они должны быть effectively final
— Создает новый scope, если объявить переменную с таким же именем что и внешняя, то она скроет внешнюю переменную
— ‘this’ внутри анонимного класса будет обращаться к объекту анонимного класса
Лямбда выражение:
— Создается в runtime через LambdaMetafactory
— Может быть использовано только с функциональными интерфейсами
— Не имеет состояния, если внутри явно каким-то образом не завязываться на состояние внешнего объекта через ссылку
— Является анонимной функцией, соответственно не имеет полей, конструкторов и т.д.
— Для работы с внешними локальными переменными они должны быть effectively final
— Не создает новый scope, если объявить переменную с таким же именем что и внешняя, то будет ошибка компиляции
— ‘this’ внутри лямбда выражения обращается объекту внешнего класса, если выражение не объявлено в статическом контексте
Теорию можно посмотреть на рабочих примерах —
#sandbox_java #anonymous_classes_vs_lambda_expressions
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Non-Capturing:
— Может использовать внешние статические переменные и методы, не зависит от нестатического контекста
— Не использует внешние локальные переменные в методе в котором объявлена или нестатические поля класса или методы
— Благодаря оптимизации JVM объект такого лямбда выражения может быть создан 1 раз и переиспользован
Capturing:
— Использует внешние локальные переменные или нестатические поля класса или методы
— Отсутствует оптимизация JVM, каждый раз будет создан новый объект сгенерированного класса, выполняющий лямбда выражение
Теорию можно посмотреть на рабочих примерах —
#sandbox_java #lambda_expressions
Please open Telegram to view this post
VIEW IN TELEGRAM
Во время выполнения приложения, когда поток доходит до метода, в котором находится capturing лямбда выражение, создается объект класса, сгенерированного LambdaMetafactory, для выполнения логики внутри лямбда выражения.
Таким образом, если мы часто выполняем метод в котором находится capturing лямбда выражение, будут часто создаваться новые объекты, что повлияет на работу GC.
Этого можно избежать благодаря оптимизациям JVM таким как escape analysis и method inlining. Однако такие оптимизации срабатывают не всегда. Например если метод достаточно большой, с конфигурацией по-умолчанию JVM может не заинлайнить метод.
Как обычным вызовом метода вывода пустой строки на консоль увеличить нагрузку на GC в несколько раз?
Ответ и теория на практике в примере —
#sandbox_java #lambda_expressions
Please open Telegram to view this post
VIEW IN TELEGRAM
В случае если можно сократить лямбда выражение, можно использовать метод референс, который будет выглядеть более читабельно и при этом поведение будет таким же.
Но есть некоторые неочевидные моменты:
— Если производить какие-либо вычисления, а после этого брать у результата метод референс, то такие вычисления не будут ленивыми
— Метод референс может завязаться на ссылку, которая в будущем будет изменена
— Неявно можно создать capturing лямбда выражение, вместо non-capturing
Эти примеры доступны по ссылке —
#sandbox_java #lambda_expressions
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Наиболее часто встречающейся формой конфигурации IoC-контейнера на данный момент в проектах использующих Spring является Annotation based конфигурация.
Рассмотрим такую конфигурацию без Spring Boot, с минимальной зависимостью — spring-context.
Для создания контекста используется AnnotationConfigApplicationContext. Передавая туда базовый компонент с аннотацией ComponentScan (которая будет обработана классом ComponentScanAnnotationParser), запускается механизм сканирования пакетов, который найдет все классы, помеченные аннотациями из пакета org.springframework.stereotype и создаст для каждого из них BeanDefinition, на основе которого создаст Bean.
Также имеется возможность зарегистрировать Bean уже в runtime, получив BeanFactory из ApplicationContext (вернется ConfigurableListableBeanFactory) и использовав методы для регистрации, например registerSingleton.
Тестирование такого примера проводится с помощью JUnit и spring-test зависимости. Аннотация SpringJUnitConfig позволяет задать классы, которые будут находится в контексте во время теста.
Теорию можно посмотреть и продебажить на рабочем примере —
Для более подробного ознакомления —
#sandbox_spring_context #annotation_based_configuration
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Когда бин A ссылается на бин B, а бин B ссылается на бин A, возникает циклическая зависимость, в таком случае Spring не сможет создать контекст если не предпринимать никаких дополнительных действий и будет выброшено исключение BeanCurrentlyInCreationException.
В документации говорится о том что в таком случае можно использовать setter injection. Однако помимо этого можно использовать аннотацию Lazy, в таком случае вместо реальной зависимости изначально будет инжектиться прокси, а когда зависимость понадобится, вместо прокси будет создана реальная зависимость.
Тем не менее лучшим решением здесь будет пересмотреть код и избавиться от циклических зависимостей, например создать бин C, который будет вызывать в правильном порядке бин A и B, либо будет использован в бине A и B как некоторая шаренная функциональность, которая необходима обоим бинам.
Теорию можно посмотреть и продебажить на рабочем примере —
#sandbox_spring_context #annotation_based_configuration
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Dependency injection можно выполнить следующими способами, которые отличаются местонахождением аннотации Autowired:
— поле (введено в annotation-based configuration)
— сеттер
— конструктор
Недостаток использования инъекции через поле заключается в том, что такие компоненты сложно тестировать. Нету конструктора или сеттера чтобы предоставить mock зависимость. Однако, все же используется для инъекции в самих тестах, чтобы получить бины, которые мы собираемся тестировать, либо объявить MockBean, а также в классах с аннотацией Configuration.
Инъекция через сеттер не распространена и не имеет преимуществ перед конструктором, за исключением того что есть возможность сделать опциональную зависимость, однако через конструктор так же есть способы, менее явные, например объявить параметр через Optional.
Предпочтительнее использовать инъекцию через конструктор (заметка в документации — “Constructor-based or setter-based DI?”), в таком случае мы имеем immutable компоненты, которые возвращаются клиенту в полностью проинициализированном виде. Объект изначально создается с необходимыми зависимостями, а не создается пустым, а после чего получает зависимости.
Наиболее компактный вариант, использовать RequiredArgsContructor из библиотеки Lombok, и объявлять зависимости как final поля. В таком случае, учитывая что если у класса 1 конструктор, то аннотация Autowired не нужна (заметка об этом в документации), и этот конструктор будет использован для Dependency injection.
Теорию можно посмотреть и продебажить на рабочем примере —
#sandbox_spring_context #annotation_based_configuration
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
Happens-before позволяет гарантировать порядок видимости операций между потоками.
Это означает что если есть поток T1 и T2, действия a1 и a2, выполняемые в потоках Т1 и Т2 соответственно, и действие a1 происходит до (happens-before) действия a2, то во время выполнения Т2, ему будут видны все изменения, произошедшие в a1 потоком T1.
В Java happens-before происходит в следующих случаях:
Теорию можно посмотреть и продебажить на рабочих примерах —
#sandbox_java #java_memory_model
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Когда приложение работает с несколькими потоками, которые используют общие переменные. Может так оказаться, что значение переменной в одном потоке, отличается от значения переменной в другом потоке, не из-за того что так подразумевалось, а из-за того что значение могло взяться не из общей памяти, а как один из вариантов, из кеша процессора.
В таком случае у нас возникает проблема Visibility, когда изменения общей переменной могут быть не видны в других потоках.
Для того чтобы решить эту проблему можно пометить переменную как volatile, в таком случае все записи и чтения будут осуществляться с общей памятью, а не с кешом процессора.
Однако volatile не решит проблему Mutual Exclusion, когда в критической секции в одно время должен быть только один поток. В таком случае если не атомарные операции чтения/записи в volatile переменную выполняются из разных потоков, то результат будет также неопределенным.
Один из вариантов решения проблемы Mutual Exclusion это использовать ключевое слово synchronized, в таком случае даже если операции не атомарные, выполнять критическую секцию будет только один поток, а переменные с которыми взаимодействует поток внутри synchronized блока будут также записаны или прочтены из общей памяти.
Таким образом volatile решает проблему Visibility без Mutual Exclusion и может быть использован когда нам неважно что множество потоков работают с переменной параллельно, а важно чтобы они видели изменения.
В свою очередь synchronized решает обе проблемы Visibility и Mutual Exclusion и может быть использован когда нам необходимо чтобы работа с переменной производилась последовательно и также была видна другим потокам.
Теорию можно посмотреть и продебажить на рабочих примерах —
#sandbox_java #java_memory_model
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
При запуске приложения, происходит инициализация Spring контекста. В зависимости от способа конфигурации бинов выбирается соответствующий BeanDefinitionReader. Например, для конфигурации через аннотации используется AnnotatedBeanDefinitionReader.
BeanDefinitionReader создает объекты BeanDefinition, каждый из которых содержит метаинформацию о бине, такую как метод инициализации, зависимости, имя класса и другую информацию, необходимую для создания экземпляра бина. Создание объектов бинов осуществляется с помощью BeanFactory.
BeanFactory создает бины со скоупом singleton сразу после старта приложения. Процесс создания бина состоит из последовательности шагов, на каждом из которых можно производить настройку и кастомизацию.
С учетом создания BeanDefinition, можно выделить следующие шаги в жизненном цикле бина:
Также, например, в случае gracefully shut down буду вызваны методы перед завершением работы приложения:
Spring рекомендует реализовывать методы *Aware только для инфраструктурных бинов, а не для сервисов или других компонентов, чтобы избежать привязки к специфическим контрактам Spring.
Теорию можно посмотреть и продебажить на рабочих примерах —
#sandbox_spring_context #bean_lifecycle
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Делюсь открытыми материалами для подготовки к собеседованию в Яндекс и Тинькофф:
Тинькофф:
📌 об этапах собеседования и материалы для подготовки
📌 о секции системного дизайна
Яндекс:
📌 гайд по интервью в Яндекс.Облако со всеми материалами в одном месте
📌 об этапах собеседования
📌 тренировочные задачи
📌 отдельная площадка для тренировки задач
📌 числа которые нужно знать и о системном дизайне
📌 об опыте прохождения архитектурных секций
📌 fast track программа для прохождения в Яндекс
Для того чтобы занимать позицию Senior, необходимо помимо знания самого языка и фреймворков, а также алгоритмов, еще знание о системном дизайне, для чего выделяется отдельная секция интервью.
#note #sources
➿ Меню
➿ Подпишись: @developer_sandbox
Тинькофф:
📌 об этапах собеседования и материалы для подготовки
📌 о секции системного дизайна
Яндекс:
📌 гайд по интервью в Яндекс.Облако со всеми материалами в одном месте
📌 об этапах собеседования
📌 тренировочные задачи
📌 отдельная площадка для тренировки задач
📌 числа которые нужно знать и о системном дизайне
📌 об опыте прохождения архитектурных секций
📌 fast track программа для прохождения в Яндекс
Для того чтобы занимать позицию Senior, необходимо помимо знания самого языка и фреймворков, а также алгоритмов, еще знание о системном дизайне, для чего выделяется отдельная секция интервью.
#note #sources
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7
Apache Kafka — распределенная стриминговая платформа с открытым исходным кодом.
Можно встретить также другие формулировки:
— распределенный лог коммитов (distributed commit log)
— с точки зрения разработчика работающего с Kafka это персистентная очередь (такая формулировка относиться не ко всем сценариям использования)
Изначально Kafka была разработана небольшой командой инженеров в 2011 году компанией LinkedIn.
Задача стояла в реализации системы для отслеживания активности пользователей (Activity tracking). Т.е. каждый клик, на какую страницу пользователь зашел, где поставил лайк, сколько потратил время на странице и т.д.
Объем данных проходящий через такую систему чрезвычайно большой. Однако благодаря реализации Kafka, она способна выдерживать такие нагрузки.
Других сценариев для применения кафки большое количество. Например:
— Messaging — другие приложения могут общаться между собой через кафку.
— Metrics and logging collection - другие приложения могут посылать метрики и логи в кафку, которые затем будут переданы в системы для мониторинга.
— Commit log — изменения в базе данных могут паблишиться в кафку и другие приложения могут отслеживать эти изменения.
— Stream processing — обработка событий в реальном времени, например получение данных из нескольких источников, их преобразование (ETL процессы), агрегирование и сохранение в базу данных.
Количество информации, которое полезно знать о кафке сложно описать в одной статье. Поэтому основные сущности и принципы работы будут описаны в следующих статьях по кафке.
Однако с примером можно ознакомиться уже сейчас, в последующем я буду ссылаться на этот же пример. Кафка кластер из двух брокеров, Zookeeper и Kafka-UI в docker-compose. Spring Boot интеграция с Kafka кластером и удобные команды для исследования поведения приложения через Spring Shell.
Все это можно найти по ссылке —
#sandbox_kafka #spring_boot_kafka
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
В нашем примере есть Kafka Cluster, состоящий из двух Kafka Broker’ов и Zookeeper. В качестве клиентов используются Spring Boot приложения - Consumer и Producer, где Producer передает сообщения, а Consumer их получает. Используется топик с именем “demo-topic" состоящий из четырех партиций и с фактором репликации равным 2.
На базе вышесказанного коротко рассмотрим первую часть основных сущностей Apache Kafka:
— Kafka Broker (Kafka Server, Kafka Node) — посредник между Consumer’ами и Producer’ами. Он отвечает за прием, выдачу и хранение сообщений.
— Kafka Cluster — группа связанных Kafka Broker’ов.
— Kafka Controller — один из брокеров в кластере, автоматически выбранный для выполнения инфраструктурных задач. В кластере может быть только один активный контроллер, а в случае его отказа происходит автоматический выбор контроллера среди доступных брокеров. В его задачи входит отслеживание состояния брокеров, выбор лидер реплик, автоматическая балансировка кластера.
— Zookeeper — координатор, хранящий конфигурацию и состояние всего кластера. Хранит информацию о всех доступных брокерах в кластере, о всех топиках и каждой партиции, и на каком брокере эти партиции располагаются. Также участвует в выборе контроллера, хранит конфигурацию об уровне доступа для каждого топика и об ограничениях по размеру данных на чтение и запись.
— Message (Record) — единица данных в системе, имеет по-умолчанию максимальный размер 1МБ. Состоит из необязательного параметра Key (массив байт), который может быть использован, например, для выбора конкретной партиции. Value (массив байт), содержащий тело сообщения. Headers (последовательность пар ключ-значение) для передачи дополнительных параметров. Метаданные о сообщении, например - timestamp, offset, partition id.
— Topic — логическая единица организации сообщений. По аналогии с папкой в файловой системе, в которой хранятся файлы, в топике хранится набор сообщений. Топик является multi-producer и multi-subscriber, это означает что он может иметь множество Producer’ов и Consumer’ов, либо не иметь их вообще. Сообщения из топика могут быть прочитаны множество раз, после чтения Consumer’ом они не удаляются. Вместо этого можно указать время жизни сообщений.
— Partition — физическая единица организации сообщений, является частью топика. Каждый топик имеет минимум одну партицию, они нумеруются с нуля. Их добавление позволяет реализовать параллельную обработку сообщений, а также позволяет распределить данные между брокерами и обеспечить отказоустойчивость благодаря репликации. Чтение из партиции происходит в том же порядке в котором была произведена запись в эту партицию.
— Replication — механизм обеспечения отказоустойчивости и высокой доступности с помощью создания копий (реплик) партиций между брокерами. Конфигурация параметра replication.factor позволяет указать количество реплик, которое будет создано для каждой партиции. Реплики одной партиции не могут находиться на одном брокере.
Отрефакторил docker-compose.yaml, исправил batch обработку в Сonsumer’e, теперь он обрабатывает по 3 сообщения и это конфигурабельно.
Можно ознакомиться с примером по ссылке —🐙 Github.
#sandbox_kafka #spring_boot_kafka
➿ Меню
➿ Подпишись: @developer_sandbox
На базе вышесказанного коротко рассмотрим первую часть основных сущностей Apache Kafka:
— Kafka Broker (Kafka Server, Kafka Node) — посредник между Consumer’ами и Producer’ами. Он отвечает за прием, выдачу и хранение сообщений.
— Kafka Cluster — группа связанных Kafka Broker’ов.
— Kafka Controller — один из брокеров в кластере, автоматически выбранный для выполнения инфраструктурных задач. В кластере может быть только один активный контроллер, а в случае его отказа происходит автоматический выбор контроллера среди доступных брокеров. В его задачи входит отслеживание состояния брокеров, выбор лидер реплик, автоматическая балансировка кластера.
— Zookeeper — координатор, хранящий конфигурацию и состояние всего кластера. Хранит информацию о всех доступных брокерах в кластере, о всех топиках и каждой партиции, и на каком брокере эти партиции располагаются. Также участвует в выборе контроллера, хранит конфигурацию об уровне доступа для каждого топика и об ограничениях по размеру данных на чтение и запись.
— Message (Record) — единица данных в системе, имеет по-умолчанию максимальный размер 1МБ. Состоит из необязательного параметра Key (массив байт), который может быть использован, например, для выбора конкретной партиции. Value (массив байт), содержащий тело сообщения. Headers (последовательность пар ключ-значение) для передачи дополнительных параметров. Метаданные о сообщении, например - timestamp, offset, partition id.
— Topic — логическая единица организации сообщений. По аналогии с папкой в файловой системе, в которой хранятся файлы, в топике хранится набор сообщений. Топик является multi-producer и multi-subscriber, это означает что он может иметь множество Producer’ов и Consumer’ов, либо не иметь их вообще. Сообщения из топика могут быть прочитаны множество раз, после чтения Consumer’ом они не удаляются. Вместо этого можно указать время жизни сообщений.
— Partition — физическая единица организации сообщений, является частью топика. Каждый топик имеет минимум одну партицию, они нумеруются с нуля. Их добавление позволяет реализовать параллельную обработку сообщений, а также позволяет распределить данные между брокерами и обеспечить отказоустойчивость благодаря репликации. Чтение из партиции происходит в том же порядке в котором была произведена запись в эту партицию.
— Replication — механизм обеспечения отказоустойчивости и высокой доступности с помощью создания копий (реплик) партиций между брокерами. Конфигурация параметра replication.factor позволяет указать количество реплик, которое будет создано для каждой партиции. Реплики одной партиции не могут находиться на одном брокере.
Отрефакторил docker-compose.yaml, исправил batch обработку в Сonsumer’e, теперь он обрабатывает по 3 сообщения и это конфигурабельно.
Можно ознакомиться с примером по ссылке —
#sandbox_kafka #spring_boot_kafka
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12
В продолжение предыдущего поста, вторая часть основных сущностей Apache Kafka:
— Leader — главная реплика, назначенная Kafka Controller’ом, особенность которой заключается в том, что операции чтения и записи происходят только с ней (с версии 2.4 Kafka поддерживает чтение с реплик). Может случится ситуация, когда лидер реплики расположены неравномерно между брокерами, и один брокер имеет большую часть нагрузки, а другие хранят follower реплики. Не всегда автоматическая балансировка позволяет это предотвратить и необходимо балансировать кластер вручную, учитывая знание нагрузки на определенные топики.
— Follower — копия лидер реплики. Для синхронизации данных с лидером используются два подхода, в первом случае follower реплика сама периодически опрашивает лидера о новых сообщениях, а во втором случае лидер при получении сообщения также записывает его в follower, в таком случае follower называется ISR - in-sync replica.
— Producer — любой клиент, отправляющий сообщения брокерам. Отправляя сообщения, можно как ожидать подтверждения со стороны Kafka так и не ожидать, в зависимости от целей это можно сконфигурировать с помощью параметра acks, который имеет следующие значения:
* 0 — сообщение будет отправлено без ожидания какого-либо подтверждения со стороны Kafka. В таком случае сообщения могут теряться.
* 1 — сообщение будет отправлено с ожиданием подтверждения что запись была произведена в Leader реплику без ожидания подтверждений от ISR Follower’ов. Сообщения могут дублироваться в случае если брокер с Leader репликой сломался до того как произошла репликация Follower’ам.
* all — сообщение будет отправлено с ожиданием подтверждения что запись была произведена в Leader реплику и реплицирована ISR Follower’ам.
— Consumer — любой клиент, принимающий сообщения от брокеров. Kafka использует pull-based подход. Это означает, что приложение, работающее с Kafka само опрашивает брокеров на предмет наличия сообщений. Для организации параллельной обработки можно объединить несколько Consumer’ов в Consumer Group указав им одинаковый group id. В группе равномерно распределяются партиции для каждого Consumer’a, однако чтобы исключить ситуацию, когда сообщение будет прочитано дважды Consumer’aми из одной группы, Consumer не может получать сообщения из партиции из которого их уже получает другой Consumer из этой же группы. Т.е. если Consumer’ов в группе будет больше чем партиций в топике, какие-то из них будут просто ожидать и не читать сообщения.
По практике:
Добавил мониторинг Kafka кластера с помощью Prometheus и Grafana как с помощью метрик из официального jmx-exporter’a, так и с помощью стороннего kafka-lag-exporter’a для просмотра consumer lag’a.
Подробнее о мониторинге и о consumer lag’e поговорим в будущем, а сейчас можно посмотреть пример по ссылке —🐙 Github
#sandbox_kafka #spring_boot_kafka
➿ Меню
➿ Подпишись: @developer_sandbox
— Leader — главная реплика, назначенная Kafka Controller’ом, особенность которой заключается в том, что операции чтения и записи происходят только с ней (с версии 2.4 Kafka поддерживает чтение с реплик). Может случится ситуация, когда лидер реплики расположены неравномерно между брокерами, и один брокер имеет большую часть нагрузки, а другие хранят follower реплики. Не всегда автоматическая балансировка позволяет это предотвратить и необходимо балансировать кластер вручную, учитывая знание нагрузки на определенные топики.
— Follower — копия лидер реплики. Для синхронизации данных с лидером используются два подхода, в первом случае follower реплика сама периодически опрашивает лидера о новых сообщениях, а во втором случае лидер при получении сообщения также записывает его в follower, в таком случае follower называется ISR - in-sync replica.
— Producer — любой клиент, отправляющий сообщения брокерам. Отправляя сообщения, можно как ожидать подтверждения со стороны Kafka так и не ожидать, в зависимости от целей это можно сконфигурировать с помощью параметра acks, который имеет следующие значения:
* 0 — сообщение будет отправлено без ожидания какого-либо подтверждения со стороны Kafka. В таком случае сообщения могут теряться.
* 1 — сообщение будет отправлено с ожиданием подтверждения что запись была произведена в Leader реплику без ожидания подтверждений от ISR Follower’ов. Сообщения могут дублироваться в случае если брокер с Leader репликой сломался до того как произошла репликация Follower’ам.
* all — сообщение будет отправлено с ожиданием подтверждения что запись была произведена в Leader реплику и реплицирована ISR Follower’ам.
— Consumer — любой клиент, принимающий сообщения от брокеров. Kafka использует pull-based подход. Это означает, что приложение, работающее с Kafka само опрашивает брокеров на предмет наличия сообщений. Для организации параллельной обработки можно объединить несколько Consumer’ов в Consumer Group указав им одинаковый group id. В группе равномерно распределяются партиции для каждого Consumer’a, однако чтобы исключить ситуацию, когда сообщение будет прочитано дважды Consumer’aми из одной группы, Consumer не может получать сообщения из партиции из которого их уже получает другой Consumer из этой же группы. Т.е. если Consumer’ов в группе будет больше чем партиций в топике, какие-то из них будут просто ожидать и не читать сообщения.
По практике:
Добавил мониторинг Kafka кластера с помощью Prometheus и Grafana как с помощью метрик из официального jmx-exporter’a, так и с помощью стороннего kafka-lag-exporter’a для просмотра consumer lag’a.
Подробнее о мониторинге и о consumer lag’e поговорим в будущем, а сейчас можно посмотреть пример по ссылке —
#sandbox_kafka #spring_boot_kafka
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9