В нашем примере есть 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
Посмотрел видео https://www.youtube.com/watch?v=QUOynbWKwZo&t=300s на скорости x2 (ссылка специально с таймингом где начинается рассказ)
На мой взгляд для middle/senior уровня здесь мало что можно нового узнать, разве что для повторения.
Вопросы, которые здесь рассматриваются:
— Что такое хорошая архитектура кода?
— Метрика архитектуры кода — Time To Market, имеется ввиду от времени на разработку до конца тестирования
— Указывается что основа для архитектуры кода, это:
* Архитектура системы (Microservices vs Monolith, Sync vs Async)
* Framework (в примерах рассматривается Spring)
* Знания разработчика
— Рассматриваются принципы хорошей архитектуры:
* DRY
* KISS
* SOLID (просто упоминается, но не разбирается. Говорится лишь о том, что Spring использует эти принципы)
— Разбираются слои в архитектуре, с примером какие классы какому слою принадлежат
— Publisher-subscriber паттерн для реализации прогрева кеша
— Приводятся виды паттернов проектирования
Еще один интересный момент, приводится пример, где следуя принципу DRY, избавляются от дубликата кода. Пример заключается в следующем:
Есть 2 метода, помеченные аннотацией GetMapping, в них есть одинаковые параметры limit и offset, помеченные аннотацией RequestParam, а также нужно валидировать их значения.
Для того чтобы избежать дубликата кода, используем знание Spring фреймворка. Создается класс Paging с полями limit и offset, для валидации используется spring-boot-starter-validation и аннотация Valid перед параметром в методе контроллера, и аннотации Positive и PositiveOrZero над полями класса Paging.
Чтобы объект был создан из двух RequestParam, реализуется PagingParamMethodArgumentResolver, который наследуется от класса из Spring - RequestParamMethodArgumentResolver. Создается аннотация PagingParam для того чтобы помечать такие параметры, по аналогии с RequestParam.
Не совсем понял почему именно в примере наследуются от класса RequestParamMethodArgumentResolver вместо реализации интерфейса HandlerMethodArgumentResolver, что на мой взгляд правильнее, т.к. RequestParamMethodArgumentResolver создан для обработки аннотации RequestParam.А также если мы создаем объект Paging как делается в примере, у нас не будет работать валидация несмотря на аннотацию Valid. (ред. Если все-таки добавить еще аннотацию Validated над классом, то валидация будет работать)
В итоге, можно сделать тоже самое, но значительно проще. Можно просто создать класс Paging и указать его в качестве параметра метода. Spring расценит его поля как query параметры и сам создаст объект, не нужно реализовывать HandlerMethodArgumentResolver, и в таком случает работает и валидация.
RequestParam аннотация применяется по-умолчанию если нет никаких других аннотаций над параметрами метода контроллера (об этом в документации - https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-methods/requestparam.html)
А если нам все-таки нужно реализовать свой HandlerMethodArgumentResolver и использовать валидацию через Valid, то тут уже не так просто, об этом можно почитать тут (https://stackoverflow.com/questions/18091936/spring-mvc-valid-validation-with-custom-handlermethodargumentresolver) (см. выше)
Написал пример online-library, где используется Spring Data, Spring MVC, Postgres в Docker’e вместе с pgAdmin, миграция через Flyway, однако в контексте данной статьи интересует пример с Paging классом, описанный мною выше, только в моем случае я назвал его Pagination. Посмотреть можно по ссылке —🐙 Github
#note #sources #video_review #sandbox_spring_web #online_library
➿ Меню
➿ Подпишись: @developer_sandbox
На мой взгляд для middle/senior уровня здесь мало что можно нового узнать, разве что для повторения.
Вопросы, которые здесь рассматриваются:
— Что такое хорошая архитектура кода?
— Метрика архитектуры кода — Time To Market, имеется ввиду от времени на разработку до конца тестирования
— Указывается что основа для архитектуры кода, это:
* Архитектура системы (Microservices vs Monolith, Sync vs Async)
* Framework (в примерах рассматривается Spring)
* Знания разработчика
— Рассматриваются принципы хорошей архитектуры:
* DRY
* KISS
* SOLID (просто упоминается, но не разбирается. Говорится лишь о том, что Spring использует эти принципы)
— Разбираются слои в архитектуре, с примером какие классы какому слою принадлежат
— Publisher-subscriber паттерн для реализации прогрева кеша
— Приводятся виды паттернов проектирования
Еще один интересный момент, приводится пример, где следуя принципу DRY, избавляются от дубликата кода. Пример заключается в следующем:
Есть 2 метода, помеченные аннотацией GetMapping, в них есть одинаковые параметры limit и offset, помеченные аннотацией RequestParam, а также нужно валидировать их значения.
Для того чтобы избежать дубликата кода, используем знание Spring фреймворка. Создается класс Paging с полями limit и offset, для валидации используется spring-boot-starter-validation и аннотация Valid перед параметром в методе контроллера, и аннотации Positive и PositiveOrZero над полями класса Paging.
Чтобы объект был создан из двух RequestParam, реализуется PagingParamMethodArgumentResolver, который наследуется от класса из Spring - RequestParamMethodArgumentResolver. Создается аннотация PagingParam для того чтобы помечать такие параметры, по аналогии с RequestParam.
Не совсем понял почему именно в примере наследуются от класса RequestParamMethodArgumentResolver вместо реализации интерфейса HandlerMethodArgumentResolver, что на мой взгляд правильнее, т.к. RequestParamMethodArgumentResolver создан для обработки аннотации RequestParam.
В итоге, можно сделать тоже самое, но значительно проще. Можно просто создать класс Paging и указать его в качестве параметра метода. Spring расценит его поля как query параметры и сам создаст объект, не нужно реализовывать HandlerMethodArgumentResolver, и в таком случает работает и валидация.
RequestParam аннотация применяется по-умолчанию если нет никаких других аннотаций над параметрами метода контроллера (об этом в документации - https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-methods/requestparam.html)
Написал пример online-library, где используется Spring Data, Spring MVC, Postgres в Docker’e вместе с pgAdmin, миграция через Flyway, однако в контексте данной статьи интересует пример с Paging классом, описанный мною выше, только в моем случае я назвал его Pagination. Посмотреть можно по ссылке —
#note #sources #video_review #sandbox_spring_web #online_library
Please open Telegram to view this post
VIEW IN TELEGRAM
YouTube
ШБР 2023 — Архитектура кода (Java)
В этой лекции поговорим об архитектуре кода, рассмотрим какие проблемы и трудности возникают при написании приложения, какие есть методики и подходы их решения, рассмотрим паттерны проектирования, взглянем на базовые аспекты Spring Framework и покажем некоторые…
🔥13❤1
Прочитал книгу "От Джуна до Сеньора. Как стать востребованным разработчиком", автор - Владимир Швец.
Увидел ее в книжном, она небольшая (211 страниц), заинтересовало то, как человек будет описывать свой 15-летний опыт, сравнить его со своим почти уже 5-летним опытом.
Книга мне понравилась, читается быстро и легко, как обзор и повторение ключевых моментов в разработке как с технической стороны, так и со стороны взаимодействия с людьми и отношению к работе, не смотря на то, что некоторые вещи очевидные.
Книга разделена на 3 основные секции (1. Код 2. Люди 3. Я). Читать можно в любом порядке, то что будет интересно.
В конце каждой главы есть тезисы где описаны основные моменты главы, можно бегло их просмотреть и решить стоит ли читать главу. Еще интересным моментом тут являются истории из жизни самого автора по теме самой главы.
Для меня здесь было интересно повторить в очередной раз о теме перфекционизма, например не рефакторить код 3 недели вместо того чтобы добавлять приоритетный функционал, уметь останавливать себя не смотря на тягу к красивому коду.
Различать программирование для себя и для работы не смотря на тягу попробовать новые технологии или обновиться до новой версии фреймворка или языка.
Помимо этого можно еще упомянуть следующие моменты:
— О здравом подходе к абстракциям в коде (KISS).
— Об отделении себя как личности от результатов твоей работы, например, при ревью кода не нужно воспринимать комментарии как личное оскорбление тебя как человека, можно рассматривать код как инструмент к достижению общей цели и у каждого участника команды общий интерес чтобы все работало как нужно. Конечно тут зависит еще от людей и их характеров, но мысль правильная.
Найти книгу достаточно просто, может кому-то будет интересно как и мне для повторения и сравнения опыта, а может кто-то узнает что-то новое.
#note #sources #book_review
➿ Меню
➿ Подпишись: @developer_sandbox
Увидел ее в книжном, она небольшая (211 страниц), заинтересовало то, как человек будет описывать свой 15-летний опыт, сравнить его со своим почти уже 5-летним опытом.
Книга мне понравилась, читается быстро и легко, как обзор и повторение ключевых моментов в разработке как с технической стороны, так и со стороны взаимодействия с людьми и отношению к работе, не смотря на то, что некоторые вещи очевидные.
Книга разделена на 3 основные секции (1. Код 2. Люди 3. Я). Читать можно в любом порядке, то что будет интересно.
В конце каждой главы есть тезисы где описаны основные моменты главы, можно бегло их просмотреть и решить стоит ли читать главу. Еще интересным моментом тут являются истории из жизни самого автора по теме самой главы.
Для меня здесь было интересно повторить в очередной раз о теме перфекционизма, например не рефакторить код 3 недели вместо того чтобы добавлять приоритетный функционал, уметь останавливать себя не смотря на тягу к красивому коду.
Различать программирование для себя и для работы не смотря на тягу попробовать новые технологии или обновиться до новой версии фреймворка или языка.
Помимо этого можно еще упомянуть следующие моменты:
— О здравом подходе к абстракциям в коде (KISS).
— Об отделении себя как личности от результатов твоей работы, например, при ревью кода не нужно воспринимать комментарии как личное оскорбление тебя как человека, можно рассматривать код как инструмент к достижению общей цели и у каждого участника команды общий интерес чтобы все работало как нужно. Конечно тут зависит еще от людей и их характеров, но мысль правильная.
Найти книгу достаточно просто, может кому-то будет интересно как и мне для повторения и сравнения опыта, а может кто-то узнает что-то новое.
#note #sources #book_review
Please open Telegram to view this post
VIEW IN TELEGRAM
👍21❤2
После обсуждения предыдущего поста, решил составить список книг.
В нем я упоминаю не только прочитанные мною книги, а также те, с которыми хочу в будущем ознакомиться, либо книги, которые часто упоминались как must read в различных источниках.
То что подойдет начинающим помечено 🐣.
Перейдем к списку:
📚 Java:
- 🐣
- 🐣
- 📖
- 📖
- 🐣
- 🐣
- 📖
#note #sources
➿ Меню
➿ Подпишись: @developer_sandbox
В нем я упоминаю не только прочитанные мною книги, а также те, с которыми хочу в будущем ознакомиться, либо книги, которые часто упоминались как must read в различных источниках.
То что подойдет начинающим помечено 🐣.
Перейдем к списку:
📚 Java:
- 🐣
Core Java Volume I--Fundamentals (Core Series) 11th Edition - Cay Horstmann
- 🐣 Thinking in Java - Bruce Eckel
- 🐣 Java: The Complete Reference - Herbert Schildt
- 🐣 Head First Java: A Brain-Friendly Guide - Kathy Sierra, Bert Bates, Trisha Gee
- 📖 Effective Java, 3rd Edition - Joshua Bloch
- 📖 Java Puzzlers: Traps, Pitfalls, and Corner Cases - Joshua Bloch, Neal Gafter
- 📖 Java Concurrency in Practice - Brian Goetz
📚 Алгоритмы и структуры данных:- 🐣
Grokking Algorithms: An Illustrated Guide for Programmers and Other Curious People - Aditya Bhargava
- 📖 Algorithms - Robert Sedgewick
- 📖 Introduction to Algorithms - Thomas H. Cormen
📚 Архитектура и системный дизайн:- 📖
Clean Architecture: A Craftsman's Guide to Software Structure and Design - Robert C. Martin
- 📖 System Design Interview – An insider's guide - Alex Xu
- 📖 Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems - Martin Kleppmann
- 📖 Building Microservices: Designing Fine-Grained Systems - Sam Newman
📚 Паттерны проектирования:- 📖
Design Patterns: Elements of Reusable Object-Oriented Software - Gamma Erich, Helm Richard, Johnson Ralph, Vlissides John
- 📖 Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software - Eric Freeman, Elisabeth Robson
- 📖 Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions - Gregor Hohpe, Bobby Woolf
📚 SQL:- 🐣
Learn SQL The Hard Way - Zed Shaw
📚 Computer science:- 🐣
Code: The Hidden Language of Computer Hardware and Software - Charles Petzold
- 🐣 Computer Science Distilled: Learn the Art of Solving Computational Problems - Wladston Ferreira Filho
📚 Разработка:- 📖
Clean Code: A Handbook of Agile Software Craftsmanship - Robert C. Martin
- 📖 Refactoring: Improving the Design of Existing Code - Martin Fowler
- 📖 Code Complete: A Practical Handbook of Software Construction - Steve McConnell
- 📖 Working Effectively with Legacy Code - Michael Feathers
- 📖 The Pragmatic Programmer: Your Journey To Mastery - David Thomas, Andrew Hunt
- 📖 Domain-Driven Design: Tackling Complexity in the Heart of Software - Eric Evans
- 📖 Cracking the Coding Interview: 189 Programming Questions and Solutions - Gayle Laakmann McDowell
- 📖 Test Driven Development: By Example - Kent Beck
Буду рад, если в комментариях вы напишете, с какими еще книгами следует ознакомиться 📚#note #sources
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19🔥4❤2
DLT (Dead Letter Topic) или DLC (Dead Letter Channel) или DLQ (Dead Letter Queue) — это подход для обработки недоставленных сообщений, которые не удалось обработать в нормальном режиме.
Представим, что идет поток сообщений через Apache Kafka. Producer их посылает, Consumer их принимает.
При обработке Consumer'ом сообщений, может возникнуть исключение, по самым разным причинам, например, неправильный формат данных, NPE, неправильное значение определенного поля в сообщении и т.д. И нам необходимо определить поведение для таких ситуаций. И одним из способов является DLT.
Выбираем топик, для которого мы хотим обрабатывать ошибки, например, demo-topic. Создаем дополнительный топик для сообщений с ошибками, например, demo-topic.failures.
Когда Consumer будет получать исключение в ходе обработки сообщения, он будет отправлять это сообщение в demo-topic.failures с дополнительной информацией в Headers о том, какое исключение было выброшено.
Помимо этого, можно реализовать несколько попыток повторной отправки сообщения, прежде чем оно все-таки попадет в DLT. В Spring это уже все реализовано, остается только правильно сконфигурировать.
— Отделение основного потока сообщений, от потока ошибок
— Можно настроить удобный мониторинг для разных типов исключений
— Можно хранить ошибки дольше и более подробно исследовать их причины
— Можно вручную исправить ошибку и переотправить сообщение из demo-topic.failures
— Усложнение архитектуры. Если исключения возникают редко, и вы можете их обработать более простым способом, можно не усложнять.
— Не стоит использовать DLT для проблем с соединением Consumer'a с другими системами. Это ответственность приложения consumer'a.
— Дополнительная нагрузка на сеть и дополнительное место для хранения ошибок в отдельном топике.
Практика:
— Добавил удобную возможность посылать сообщения, которые вызывают ошибки через Spring Shell.
— Добавил механизм ретраев через ExponentialBackOffWithMaxRetries и интеграционный тест с помощью testcontainers, который проверяет как работает DLT.
Все это по ссылке —
#sandbox_kafka #spring_boot_kafka
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9👍4👀2
Какую следующую тему вы хотели бы увидеть?
Final Results
45%
Основы Kafka Connect
46%
Что такое SSL сертификаты и для чего они нужны?
23%
Обзор Prometheus и Grafana с наиболее популярными exporter'aми
15%
Resilience4j, как работает Circuit Breaker?
Рассмотрим на примере:
У нас есть сайт, где клиент вводит персональные данные (например, данные банковских карточек, паспорта, номера телефонов и т.д.)
Если мы используем на сайте HTTP протокол, то получаем следующие проблемы:
❌ Персональные данные передаются по сети в открытом виде как обычный текст, и злоумышленник, имеющий доступ к сети, может эти данные получить либо изменить.
❌ Поисковики (google и др.) понижают в результатах поиска сайты, использующие HTTP
❌ Браузеры (google chrome и др.) перед переходом на HTTP сайт показывают предупреждение, что он небезопасный
❌ Нет доказательства что наш сайт, принадлежит нашей организации. Т.е. нету сертификата, в котором это прописано. И злоумышленники могут создавать копии нашего сайта.
Для решения этих проблем, нам необходимо перейти на HTTPS. И здесь мы вводим понятия SSL и TLS:
SSL — Secure Sockets Layer — протокол в криптографии для безопасной передачи данных по сети.
SSL является устаревшим и вместо него используется разработанный на его основе TLS — Transport Layer Security, однако терминология часто встречается из старого протокола, и когда говорят SSL сертификат, имеют ввиду TLS сертификат.
HTTPS использует TLS для обеспечения безопасной передачи данных. Фактически HTTPS это HTTP, который использует уровнем ниже TLS.
Благодаря использованию TLS мы получаем:
✅ Конфиденциальность — данные передаются по сети в зашифрованном виде, теперь злоумышленник не увидит наши персональные данные как обычный текст.
✅ Подлинность — в сертификате нашего сайта будет связь между ним и нашей организацией. Перед отправкой данных, клиент проверит сертификат и сможет убедиться, что он попал на оригинальный сайт.
✅ Целостность — данные гарантированно будут получены клиентом/сервером в том виде, в котором они были отправлены клиентом/сервером. Злоумышленник не сможет изменить данные если он их перехватит. (
Сама реализация протокола TLS требует наличие сертификата. Без него работать не будет.
SSL (TLS) сертификат — логически представляет собой цифровой паспорт сервера, а физически это файл, обычно с расширением .cer или .pem
В нем содержится следующая основная информация:
📝 Subject — данные о владельце сертификата (содержит много опциональных полей, например в CN (Common Name) обычно указывают домен)
📝 Issuer — данные о подписчике сертификата (например, можно увидеть какой CA (Certificate Authority) подписал этот сертификат)
📝 Public key — публичный ключ сертификата, используется для проверки подписи и шифрования session key (о нем позже)
📝 Valid from — дата создания сертификата
📝 Valid until — срок действия сертификата
📝 Signature — цифровая подпись сертификата, например подписанная CA
Теперь мы представляем что это и для чего это нужно. Остаются вопросы:
Об этом в следующих статьях. Однако для тех, кто хочет быстрее посмотреть пример Spring Boot сервера c mTLS и скрипт с эмуляцией выдачи CA клиентского и серверного сертификата, можно перейти по ссылке —
#sandbox_spring_web #https
Please open Telegram to view this post
VIEW IN TELEGRAM
👍28❤5🔥4🤯1
Ответим на часть вопросов из предыдущей статьи:
❓ Откуда взять сертификаты?
❓ Какие виды сертификатов есть?
Сертификаты можно получить несколькими способами:
— Сгенерировать самостоятельно
— Получить бесплатно, либо купить в специальной организации, имеющей статус Сertificate Authority (CA)
⚠️ Если любой пользователь может генерировать сертификаты, то как браузер либо любой другой клиент, общающийся с HTTPS сервером, понимает что сертификату сервера можно доверять?
Для ответа на этот вопрос у клиента есть изначальный набор сертификатов, и доверенными сертификатами считаются только те, что находятся в этом наборе, который еще называют truststore.
В браузерах, операционных системах и JDK такие наборы сертификатов идут сразу с установкой. А сами сертификаты берутся у доверенных CA компаний (Например DigiCert, Let's Encrypt).
Это значит, что даже если вы сгенерируете свой сертификат, доверять ему смогут только приложения, где у вас есть прямой доступ к их truststore.
Таким образом, можно выделить виды сертификатов по уровню доверия к ним:
📝 Self-signed — самоподписанные сертификаты. Можно сгенерировать самостоятельно, например, через команду openssl. Доверять таким сертификатам сможете только вы, и пользователи, которые специально добавят их в свой truststore.
Технически, корневые сертификаты от CA, установленные по-умолчанию в браузерах и ОС, тоже являются самоподписанными, но им принято доверять.
Если мы получаем сертификат через CA, то в зависимости от количества проверок со стороны CA, есть следующие виды сертификатов:
📝 DV (Domain Validation) — CA организация проверяет, что указанный домен принадлежит действительно человеку, который обратился за получением сертификата. Это самая минимальная проверка, можно провести автоматически и получить сертификат бесплатно, так делает CA организация — Let's Encrypt.
📝 OV (Organization Validation) — CA помимо домена, проверяет еще что ваша организация действительно существует и у нее есть юридический адрес. Такой сертификат будет уже платный.
📝 EV (Extended Validation) — CA помимо предыдущих проверок, проведет ряд дополнительных проверок вашей организации. Такой сертификат будет стоить еще дороже. Больше подходит корпорациям, например, такой сертификат можно посмотреть на сайте apple.
Остаются вопросы, которые мы рассмотрим в следующих статьях:
❓ С технической точки зрения, как клиент и сервер используют сертификат? (Поговорим о TLS-handshake)
❓ Если мы получили сертификат выданный CA, то как клиенты будут ему доверять? Ведь только что выданный сертификат не появится во всех ОС и браузерах как доверенный в их truststore. (Поговорим о certificate chain)
Заранее добавил пример, демонстрирующий работу с цепочками сертификатов —🐙 Github
#sandbox_spring_web #https
➿ Меню
➿ Подпишись: @developer_sandbox
Сертификаты можно получить несколькими способами:
— Сгенерировать самостоятельно
— Получить бесплатно, либо купить в специальной организации, имеющей статус Сertificate Authority (CA)
⚠️ Если любой пользователь может генерировать сертификаты, то как браузер либо любой другой клиент, общающийся с HTTPS сервером, понимает что сертификату сервера можно доверять?
Для ответа на этот вопрос у клиента есть изначальный набор сертификатов, и доверенными сертификатами считаются только те, что находятся в этом наборе, который еще называют truststore.
В браузерах, операционных системах и JDK такие наборы сертификатов идут сразу с установкой. А сами сертификаты берутся у доверенных CA компаний (Например DigiCert, Let's Encrypt).
Это значит, что даже если вы сгенерируете свой сертификат, доверять ему смогут только приложения, где у вас есть прямой доступ к их truststore.
Таким образом, можно выделить виды сертификатов по уровню доверия к ним:
📝 Self-signed — самоподписанные сертификаты. Можно сгенерировать самостоятельно, например, через команду openssl. Доверять таким сертификатам сможете только вы, и пользователи, которые специально добавят их в свой truststore.
📝 DV (Domain Validation) — CA организация проверяет, что указанный домен принадлежит действительно человеку, который обратился за получением сертификата. Это самая минимальная проверка, можно провести автоматически и получить сертификат бесплатно, так делает CA организация — Let's Encrypt.
📝 OV (Organization Validation) — CA помимо домена, проверяет еще что ваша организация действительно существует и у нее есть юридический адрес. Такой сертификат будет уже платный.
📝 EV (Extended Validation) — CA помимо предыдущих проверок, проведет ряд дополнительных проверок вашей организации. Такой сертификат будет стоить еще дороже. Больше подходит корпорациям, например, такой сертификат можно посмотреть на сайте apple.
Остаются вопросы, которые мы рассмотрим в следующих статьях:
Заранее добавил пример, демонстрирующий работу с цепочками сертификатов —
#sandbox_spring_web #https
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥2
Как вы бы оценили свой уровень знаний?
Anonymous Poll
19%
Только начинаю путь в IT
30%
Trainee (еще не Junior, но кое-что знаю)
22%
Junior Developer
22%
Middle Developer
6%
Senior Developer
2%
Выше чем Senior Developer
Ответим на вопрос из предыдущей статьи:
❓ Если мы получили сертификат выданный CA, то как клиенты будут ему доверять? Ведь только что выданный сертификат не появится во всех ОС и браузерах как доверенный в их truststore.
Чтобы ответить на этот вопрос, нужно понимать как проверяется сертификат.
Рассмотрим на примере:
Перед запросом сертификата от CA, мы генерируем private key и CSR (Certificate Signing Request). В CSR хранится информация о нашем сайте (например, в поле subject указано поле CN=<домен>), а также public key, связанный с нашим private key.
❓ Что такое private key и public key?
Это понятия из криптографии, а именно из ассиметричного шифрования (например, алгоритм RSA). Здесь нам важно понимать что существует связанная пара ключей:
— Public key можно передавать другим людям, он используется для шифрования и проверки signature (цифровая подпись)
— Private key следует хранить в секрете, он используется для дешифрования и создания signature
После того как CA получил CSR, используя его, а также свой CA сертификат и CA private key, он генерирует нам сертификат (в поле issuer нашего сертификата будет указана информация из subject'a CA сертификата) и мы устанавливаем его на сервер.
❓ Что на этом этапе есть на нашем сервере?
— Сгенерированный нами private key
— Сгенерированный нам от CA сертификат, содержащий наш public key и подпись, сделанную CA private key
❓ А что есть у клиента, который отправит запрос на наш сервер?
— У него есть только CA сертификат, по-умолчанию установленный в truststore его браузера
Теперь клиент отправляет запрос на сервер, и проверка сертификата происходит следующим образом:
1⃣ Получаем сертификат сервера
2⃣ Смотрим значение issuer и ищем в truststore сертификат, у которого такой subject (мы его находим, это CA сертификат)
3⃣ Берем public key из CA сертификата, а signature берем из сертификата сервера
4⃣ Т.к. signature была сделана используя CA private key, то используя CA public key мы проверяем ее и достаем из signature информацию о hash'e сертификата сервера.
5⃣ Смотрим какой алгоритм использовался для генерации hash'a сертификата сервера
6⃣ Откидываем signature и считаем hash для body (body это весь файл сертификата, кроме signature)
7⃣ Если hash из signature и только что рассчитанный hash для body равны, то значит сертификат сервера действительно был подписан CA и ему можно доверять.
Таким образом, имея только корневой CA сертификат, мы можем проверять все выданные этим CA сертификаты.
Это позволяет создавать цепочки сертификатов (certificate chain):
— Например, один крупный CA выдает оптом сертификаты другому CA поменьше, а он уже выдает сертификаты физическим лицам.
— Тогда на сервере будет цепочка сертификатов от разных CA (обязательно в той последовательности, в которой они выдавались)
— Но клиенту все равно достаточно иметь только один корневой сертификат в truststore, который от крупного CA
— Проверка по алгоритму, описанному выше, пройдет по всей цепочке, начиная от корневого сертификата
Этот алгоритм можно полностью самостоятельно провести на практике, я описал скрипт для ручной проверки сертификата (поиск по Manual certificate validation), а также добавил https клиент —🐙 Github
#sandbox_spring_web #https
➿ Меню
➿ Подпишись: @developer_sandbox
Чтобы ответить на этот вопрос, нужно понимать как проверяется сертификат.
Рассмотрим на примере:
Перед запросом сертификата от CA, мы генерируем private key и CSR (Certificate Signing Request). В CSR хранится информация о нашем сайте (например, в поле subject указано поле CN=<домен>), а также public key, связанный с нашим private key.
— Public key можно передавать другим людям, он используется для шифрования и проверки signature (цифровая подпись)
— Private key следует хранить в секрете, он используется для дешифрования и создания signature
— Сгенерированный нами private key
— Сгенерированный нам от CA сертификат, содержащий наш public key и подпись, сделанную CA private key
— У него есть только CA сертификат, по-умолчанию установленный в truststore его браузера
Теперь клиент отправляет запрос на сервер, и проверка сертификата происходит следующим образом:
Таким образом, имея только корневой CA сертификат, мы можем проверять все выданные этим CA сертификаты.
Это позволяет создавать цепочки сертификатов (certificate chain):
— Например, один крупный CA выдает оптом сертификаты другому CA поменьше, а он уже выдает сертификаты физическим лицам.
— Тогда на сервере будет цепочка сертификатов от разных CA (обязательно в той последовательности, в которой они выдавались)
— Но клиенту все равно достаточно иметь только один корневой сертификат в truststore, который от крупного CA
— Проверка по алгоритму, описанному выше, пройдет по всей цепочке, начиная от корневого сертификата
Этот алгоритм можно полностью самостоятельно провести на практике, я описал скрипт для ручной проверки сертификата (поиск по Manual certificate validation), а также добавил https клиент —
#sandbox_spring_web #https
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤1
Sandbox
Java Sandbox
Spring Context Sandbox
Spring Web Sandbox
Spring Data JPA Sandbox
PostgreSQL Sandbox
Apache Kafka Sandbox
Other
Please open Telegram to view this post
VIEW IN TELEGRAM
👍40❤11🤯3
Developer's Sandbox pinned «🔤 🔤 🔤 🔤 Sandbox 📦 🔤 Сравнение JDBC, Spring JDBC, Hibernate, Spring Data JPA 🔤 Логирование JDBC запросов 🔤 Обзор Spring Data JDBC, MyBatis, JOOQ 🔤 Что такое Spring Boot и для чего он используется? Java Sandbox ☕️ 🔤 В чем разница между анонимным классом и λ-выражением?…»
Недавно вышла общедоступная версия Java 21, которая является следующей LTS (Long-term support) версией после Java 17
Смотрел, какие новые фичи добавили в язык и захотел поделиться с вами полезным ресурсом, где я обычно смотрю обновления — javaalmanac
Здесь можно найти информацию по каждой версии Java, начиная с первой и заканчивая той, что на данный момент в разработке (Java 22)
❓ Что тут можно найти?
— Ссылки на спецификации — языка, API, виртуальной машины
— Ссылки на release notes
— Если перейти на конкретную версию, то по каждому уровню (JVM, Language, API), можно увидеть список добавленных фич, многие из которых объясняются с примерами
— В колонке "Compare API to" можно выбрать предыдущие версии, сравнив API до самых мелочей, например, между Java 21 и Java 20 добавился метод isEmoji(int) в Character классе
Заодно решил обновить свои примеры на самые последние версии:
— Перешел на Java 21
— Отрефакторил build.gradle и перешел в нем с Groovy на Kotlin
— Обновил все версии библиотек, а где используется docker — обновил версии imag'ей
Теперь структура примеров еще проще:
🌱 sandbox-spring-context
🌱 sandbox-spring-web
📖 sandbox-kafka
☕️ sandbox-java
#note #sources
➿ Меню
➿ Подпишись: @developer_sandbox
Смотрел, какие новые фичи добавили в язык и захотел поделиться с вами полезным ресурсом, где я обычно смотрю обновления — javaalmanac
Здесь можно найти информацию по каждой версии Java, начиная с первой и заканчивая той, что на данный момент в разработке (Java 22)
— Ссылки на спецификации — языка, API, виртуальной машины
— Ссылки на release notes
— Если перейти на конкретную версию, то по каждому уровню (JVM, Language, API), можно увидеть список добавленных фич, многие из которых объясняются с примерами
— В колонке "Compare API to" можно выбрать предыдущие версии, сравнив API до самых мелочей, например, между Java 21 и Java 20 добавился метод isEmoji(int) в Character классе
Заодно решил обновить свои примеры на самые последние версии:
— Перешел на Java 21
— Отрефакторил build.gradle и перешел в нем с Groovy на Kotlin
— Обновил все версии библиотек, а где используется docker — обновил версии imag'ей
Теперь структура примеров еще проще:
#note #sources
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31
Delivery semantics [delivery guarantees, processing guarantees] — это способы доставки сообщений, т.е. как именно будут взаимодействовать между собой Producer, Broker и Consumer для того чтобы доставить сообщение.
Рассмотрим на примере классической схемы. У нас есть:
Шаг 1. Producer читает данные из БД
Шаг 2. Producer отправляет сообщение Broker’y в demo.topic
Шаг 3. Broker сохраняет сообщение в demo.topic’e
Шаг 4. Broker уведомляет Producer’a, подтверждая что сообщение сохранено [acknowledgment]
Шаг 5. Consumer читает сообщение из demo.topic’a
Шаг 6. Consumer уведомляет Broker’a, что сообщение успешно прочитано [offset commit]
Шаг 7. Consumer сохраняет данные в БД
На каждом шаге может произойти сбой, например:
❌ Закончилась оперативная память — OutOfMemoryError
❌ Закончилось место на диске
❌ Временный сбой в сети
❌ Случился timeout, например, Шаг 3 — Broker слишком долго сохранял сообщение
В зависимости от того, какие гарантии мы хотим получить в случае если что-то пойдет не так, мы используем разные delivery semantics.
Delivery semantics для Producer’a:
Тут может быть ситуация, если Broker записал сообщение, но вышел из строя на этапе отправки acknowledgment’a, и когда Broker восстановится и Producer переотправит сообщение, то мы по сути создадим дубликат, сохранив в Broker’e дважды одно сообщение.
Delivery semantics для Consumer’a:
У нас Шаг 7, например, Spring приложение Consumer упало с OOM и потом поднялось, но перечитывать сообщение не будет хоть и могло бы записать что-то в БД. Тут мы теряем обработку сообщения.
У нас Шаг 6 и Шаг 7 меняются местами, однако, например, мы делаем транзакцию в БД, хотим сделать commit offset и падаем с OOM, и когда поднимаемся, то перечитываем сообщение и делаем ту же транзакцию, что может создать дубликат в БД.
Чтобы не создать дубликат и не потерять обработку сообщения у нас есть 2 варианта:
— Транзакция в БД идемпотентна и если мы повторим ее, то ничего не изменится
— Мы делаем commit offset в рамках транзакции к БД [необязательно хранить offset в Broker’e, можно хранить их в БД], чтобы Шаг 6 и Шаг 7 был одним атомарным шагом. Тогда у нас нет дубликатов и обработку сообщения мы не теряем
Немного рефакторинга —
#sandbox_kafka #spring_boot_kafka
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥14👍7❤4
Какое количество технических собеседований у вас было?
Anonymous Poll
32%
0
38%
1-5
11%
5-10
18%
10+
Планирую выбрать новое название для канала, что думаете?
Anonymous Poll
30%
Dev Sandbox
17%
IT Sandbox
3%
Другое (предложить свой вариант в комментариях)
50%
Оставить текущее название
После продолжительного перерыва, я вернулся с новой статьей. Буду стараться писать одну/две статьи в неделю.
Давайте напишем одинаковое приложение, используя JDBC, Spring JDBC, Hibernate и Spring Data JPA. Посмотрим наглядно, как исторически повышался уровень абстракции при работе с БД в Java мире.
❓ Какое приложение напишем?
CRUD для работы с сущностью Book и ее связями — Author, Comment, Genre
Реализуем API для:
1⃣ Получения всех книг и ее связей
2⃣ Получения книги по id и ее связей
3⃣ Создания книги и ее связей
4⃣ Обновления книги и ее связей
5⃣ Удаления книги и ее комментариев и информации о жанрах
Модель данных опишем таблицами:
1⃣ books — данные о книгах
2⃣ authors — данные об авторах. С books “one-to-one”
3⃣ genres — данные о жанрах
4⃣ comments — данные о комментариях к книгам. С books “one-to-many”
5⃣ books_genres — промежуточная таблица для создания “many-to-many” между books и genres
Начнем в порядке повышения уровня абстракции:
📚 JDBC [Java Database Connectivity] — спецификация синхронного API для работы с реляционными БД из Java приложений. Входит в состав Java SE.
Реализацию API предоставляет JDBC драйвер.
Например, для PostgresSQL есть драйвер postgresql-42.6.0.jar, внутри есть класс PgResultSet, реализующий интерфейс java.sql.ResultSet из JDBC спецификации.
Для отправки SQL запроса, нужно:
1⃣ Получить Connection
2⃣ Создать Statement, передав SQL запрос в виде String
3⃣ Если это параметризованный запрос, то передать параметры через .set методы в Statement’e
4⃣ Выполнить запрос и получить ResultSet
5⃣ Разобрать ResultSet, получив из него данные для создания объектов Book, Author, Comment, Genre
6⃣ Закрыть ResultSet
7⃣ Закрыть Statement
8⃣ Закрыть Connection
Пример доступен на🐙 Github
🌱 Spring JDBC — набор абстракций, упрощяющий написание кода при работе с JDBC. Чтобы как можно меньше шагов пришлось писать самому.
Например, аннотация Transactional для механизма транзакций, класс NamedParameterJdbcOperations для выполнения запросов.
Теперь нам не нужно самостоятельно открывать Connection и закрывать его вместе с Statement и ResultSet. Однако разбирать данные из ResultSet'a все еще нужно вручную.
Пример доступен на🐙 Github
🪞 Hibernate — ORM [Object Relational Mapping] фреймворк. Реализует JPA спецификацию. Переход от реляционной парадигмы в ООП парадигму. Сама реализация для доступа к БД использует тот же JDBC.
Мы начинаем работать с таблицами из БД как с Java объектами. Убирается необходимость самостоятельного разбора ResultSet'ов. Вводится понятие HQL [в спецификации JPA называется JPQL], как универсального языка запросов, для обеспечения независимости от реализации БД.
Однако появляется N+1 проблема, и множество других подводных камней, которые нужно учесть, чтобы ORM фреймворк генерировал оптимальный SQL.
Пример доступен на🐙 Github
🌱 Spring Data JPA — часть umbrella проекта Spring Data, представляет дополнительный уровень абстракции над JPA. По-умолчанию использует Hibernate как JPA реализацию.
Благодаря абстракции Repository, позволяет генерировать запросы на основе имени метода, убирая возможность в некоторых ситуациях писать даже JPQL. Помимо этого имеет и много других возможностей, значительно ускоряя написание кода.
Содержит все те же недостатки что и Hibernate [в случае если используется именно он как реализация JPA].
Пример доступен на🐙 Github
#sandbox_java_database_tools
➿ Меню
➿ Подпишись: @developer_sandbox
Давайте напишем одинаковое приложение, используя JDBC, Spring JDBC, Hibernate и Spring Data JPA. Посмотрим наглядно, как исторически повышался уровень абстракции при работе с БД в Java мире.
CRUD для работы с сущностью Book и ее связями — Author, Comment, Genre
Реализуем API для:
Модель данных опишем таблицами:
Начнем в порядке повышения уровня абстракции:
Реализацию API предоставляет JDBC драйвер.
Например, для PostgresSQL есть драйвер postgresql-42.6.0.jar, внутри есть класс PgResultSet, реализующий интерфейс java.sql.ResultSet из JDBC спецификации.
Для отправки SQL запроса, нужно:
Пример доступен на
Например, аннотация Transactional для механизма транзакций, класс NamedParameterJdbcOperations для выполнения запросов.
Теперь нам не нужно самостоятельно открывать Connection и закрывать его вместе с Statement и ResultSet. Однако разбирать данные из ResultSet'a все еще нужно вручную.
Пример доступен на
Мы начинаем работать с таблицами из БД как с Java объектами. Убирается необходимость самостоятельного разбора ResultSet'ов. Вводится понятие HQL [в спецификации JPA называется JPQL], как универсального языка запросов, для обеспечения независимости от реализации БД.
Однако появляется N+1 проблема, и множество других подводных камней, которые нужно учесть, чтобы ORM фреймворк генерировал оптимальный SQL.
Пример доступен на
Благодаря абстракции Repository, позволяет генерировать запросы на основе имени метода, убирая возможность в некоторых ситуациях писать даже JPQL. Помимо этого имеет и много других возможностей, значительно ускоряя написание кода.
Содержит все те же недостатки что и Hibernate [в случае если используется именно он как реализация JPA].
Пример доступен на
#sandbox_java_database_tools
Please open Telegram to view this post
VIEW IN TELEGRAM
❤26🔥10👍6
Хотел написать в одной статье о типах связей в реляционных БД, и как их реализовать в JPA
Однако в одну статью с примерами кода не поместилось, поэтому разделил на две статьи и создал отдельные репозитории:
🐘 sandbox-postgresql
🌱 sandbox-spring-data-jpa
Если в статье SQL код неправильно отображается, нужно обновить Telegram.
❓ Какие существуют типы связей в реляционных БД?
Рассмотрим на примере нашей любимой доменной модели — Библиотеки
У нас будут две сущности — Книга, Автор
В зависимости от наших требований к системе, мы будем строить нужную связь между сущностями
Требование:
В нашей системе мы хотим чтобы у одной книги был только один автор. А также, чтобы автор имел возможность написать только одну книгу.
Решение:
Для реализации такой модели данных нам подойдет отношение One to One [читается как “один автор — одна книга”]:
Здесь важно установить UNIQUE constraint, в нашем случае на поле author_id, чтобы разные книги не могли ссылаться на одного автора.
Также вместо author_id, можно сделать book_id в таблице authors, и наше требование тоже выполнится.
Таким образом мы выбираем, кто будет владельцем связи, Book или Author [об этом будет подробнее в статье про Spring Data JPA, но если кратко, тот у кого в таблице foreign key]
Пример доступен на🐙 Github
Требование:
В нашей системе мы хотим чтобы у одной книги был только один автор. Однако, автор может написать сколько угодно книг.
Решение:
В этом случае нам подойдет отношение One to Many [читается как “один автор — множество книг”]
Иногда выделяют отношение Many to One [читается как “множество книг — один автор”], разницы в реализации между ними нету, мы только меняем акцент, когда говорим что с чем связано
Единственная разница в реализации между One to One и One to Many, что теперь у нас нету UNIQUE constraint для поля author_id
Также если мы сделаем book_id в таблице authors вместо author_id в таблице books, то наше требование не выполнится, потому что тогда автор сможет иметь только одну книгу
[Поэтому в JPA у аннотации ManyToOne нету параметра mappedBy, потому что такая сущность точно является владельцем связи, т.е. имеет foreign key на другую сущность]
Пример доступен на🐙 Github
Требование:
В нашей системе мы хотим чтобы у одной книги было сколько угодно авторов. А также, автор может написать сколько угодно книг.
Решение:
Здесь нам подходит Many to Many [читается как “множество авторов — множество книг”]:
Создается дополнительная таблица books_authors, указывающая нужные связи между сущностями
Не стоит также забывать о добавлении UNIQUE constraint’a на связь book_id и author_id, чтобы связь была уникальной
Пример доступен на🐙 Github
#sandbox_postgresql #relationships
➿ Меню
➿ Подпишись: @developer_sandbox
Однако в одну статью с примерами кода не поместилось, поэтому разделил на две статьи и создал отдельные репозитории:
Если в статье SQL код неправильно отображается, нужно обновить Telegram.
Рассмотрим на примере нашей любимой доменной модели — Библиотеки
У нас будут две сущности — Книга, Автор
В зависимости от наших требований к системе, мы будем строить нужную связь между сущностями
Требование:
В нашей системе мы хотим чтобы у одной книги был только один автор. А также, чтобы автор имел возможность написать только одну книгу.
Решение:
Для реализации такой модели данных нам подойдет отношение One to One [читается как “один автор — одна книга”]:
CREATE TABLE authors
(
id BIGSERIAL NOT NULL PRIMARY KEY,
name VARCHAR(64) NOT NULL
);
CREATE TABLE books
(
id BIGSERIAL NOT NULL PRIMARY KEY,
title VARCHAR(128) NOT NULL,
author_id BIGINT NOT NULL UNIQUE REFERENCES authors (id)
);
Здесь важно установить UNIQUE constraint, в нашем случае на поле author_id, чтобы разные книги не могли ссылаться на одного автора.
Также вместо author_id, можно сделать book_id в таблице authors, и наше требование тоже выполнится.
Таким образом мы выбираем, кто будет владельцем связи, Book или Author [об этом будет подробнее в статье про Spring Data JPA, но если кратко, тот у кого в таблице foreign key]
Пример доступен на
Требование:
В нашей системе мы хотим чтобы у одной книги был только один автор. Однако, автор может написать сколько угодно книг.
Решение:
В этом случае нам подойдет отношение One to Many [читается как “один автор — множество книг”]
Иногда выделяют отношение Many to One [читается как “множество книг — один автор”], разницы в реализации между ними нету, мы только меняем акцент, когда говорим что с чем связано
CREATE TABLE authors
(
id BIGSERIAL NOT NULL PRIMARY KEY,
name VARCHAR(64) NOT NULL
);
CREATE TABLE books
(
id BIGSERIAL NOT NULL PRIMARY KEY,
title VARCHAR(128) NOT NULL,
author_id BIGINT NOT NULL REFERENCES authors (id)
);
Единственная разница в реализации между One to One и One to Many, что теперь у нас нету UNIQUE constraint для поля author_id
Также если мы сделаем book_id в таблице authors вместо author_id в таблице books, то наше требование не выполнится, потому что тогда автор сможет иметь только одну книгу
[Поэтому в JPA у аннотации ManyToOne нету параметра mappedBy, потому что такая сущность точно является владельцем связи, т.е. имеет foreign key на другую сущность]
Пример доступен на
Требование:
В нашей системе мы хотим чтобы у одной книги было сколько угодно авторов. А также, автор может написать сколько угодно книг.
Решение:
Здесь нам подходит Many to Many [читается как “множество авторов — множество книг”]:
CREATE TABLE authors
(
id BIGSERIAL NOT NULL PRIMARY KEY,
name VARCHAR(64) NOT NULL
);
CREATE TABLE books
(
id BIGSERIAL NOT NULL PRIMARY KEY,
title VARCHAR(128) NOT NULL
);
CREATE TABLE books_authors
(
id BIGSERIAL NOT NULL PRIMARY KEY,
book_id BIGINT NOT NULL REFERENCES books (id),
author_id BIGINT NOT NULL REFERENCES authors (id),
UNIQUE (book_id, author_id)
);
Создается дополнительная таблица books_authors, указывающая нужные связи между сущностями
Не стоит также забывать о добавлении UNIQUE constraint’a на связь book_id и author_id, чтобы связь была уникальной
Пример доступен на
#sandbox_postgresql #relationships
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16❤4🔥4
