Русский
Русский
English
Статистика
Реклама

Event sourcing

Очень технический выпуск про DDD и проектирование сложных систем

12.02.2021 16:06:23 | Автор: admin

В свежем выпуске подкаста Сушите вёсла обсудили методологии проектирования сложных систем. Много говорили о Domain Driven Design, Event Sourcing и CQRS. Тема непростая, но, как говорится, очень интересная.

Артём Кулаков и Рома Чорыев разработчики Redmadrobot, они записывают подкаст, где обсуждают различные стороны создания ИТ-продуктов. Ниже ссылка на новый выпуск, тайминг и ответы на душещипательные вопросы. Но вначале небольшой дисклеймер:

Почему все больше и больше ведется разговоров о различных аспектах и методологиях проектирования систем? Потому что наши системы стали действительно большими. Чтобы разобраться, как проектировать такие системы, мы позвали Алексея Мерсона системного архитектора из Karuna. В выпуске попробовали разобраться, что такое Domain Driven Design, как он связан с Event Sourcing и при чем тут CQRS и микросервисы. Снять удалось только первый слой, да и то неравномерно. Но всем, кто хочет начать погружаться в тему, этот выпуск будет несомненно полезен. И обязательно ознакомьтесь с материалами к выпуску.

Тайминг

02:29 Гость студии Алексей Мерсон и как он начинал;

05:02 .Net и DDD;

12:26 почему сейчас все чаще говорят о DDD;

15:30 полезная литература о DDD;

23:01 как начать проектировать систему по DDD;

25:05 Event storming и Miro;

45:15 что такое Event sourcing;

55:00 CQRS и его связь с DDD и Event sourcing;

01:06:10 с чего начать.

DDD что это и почему сейчас?

Domain-Driven Design предметно-ориентированное проектирование. Понятие известно давно, но в последнее время в русскоязычном сообществе о нем говорят всё чаще.

Алексей считает, что возможно, это связано с тем, в Agile-мире запускаются проекты, которые без применения DDD скатятся в печальное состояние, потому что появится расхождение между предметной областью и реализацией.

В первую очередь Domain-Driven Design это история о проектировании, и предметная область в нем ставится во главу угла. И основной акцент в этом подходе делается на взаимодействии с бизнесом с заказчиками ПО и приложений.

Если проще, то бывает, что для решения бизнес-задач конвейер производства ПО растягивается, и в конечном счете в реализации решения этих задач могут оказаться совсем не такими, какими задумывались изначально. И вот тут, чтобы не играть в испорченный телефон, применяется DDD. Его цель сократить расстояние между бизнесом и разработчиками, чтобы последние максимально точно понимали, что за бизнес-процессы они реализуют.

Как спроектировать сложную систему с нуля?

В студии прозвучал резонный вопрос: представим, что мы поняли, что у нас сложная система, которую будем делать по DDD и у нас на это даже есть много времени. С чего стоит начать? Алексей дал несколько советов.

Первое конечно же, придется стартовать с MVP, то есть с маленьких кусочков, которые затем будут разрастаться во что-то большее. Второе понять процессы, которые нужно автоматизировать. При этом важно находиться в контакте с теми, кто ставит задачи. Например, с продактами или с кем-то из бизнеса, топ-менеджерами. Дальше расписать сценарии таким образом, чтобы стал понятен контекст, в котором существуют заданные бизнес-процессы.

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

В Event storming собираются все заинтересованные лица и на доске с помощью стикеров выстраивают последовательность событий и тех объектов, которые генерируют эти события. Получается некая визуальная карта, в которой становится понятно, как взаимодействуют различные сущности и как они объединяются по контекстам.

Event Storming фото Daniel GomesEvent Storming фото Daniel Gomes

Изначально активность проводили офлайн, но сейчас подобное можно спокойно провести онлайн, например, в Miro.

Event Sourcing (не путать с Event storming)

Event Sourcing еще одна популярная сегодня тема. Это архитектурный шаблон, упоминание которого часто всплывает в связи с DDD.

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

Недавно в сообществе SpbDotNet был митап, где рассказывали о том, как одна команда применяла Event Sourcing. Они применяли его в приложении, которое реализовывало аукционы. Там есть ставки, и они, по сути, события, которые конкурируют: важно, в какой момент каждое из них произошло, важно получить из них правильную последовательность, чтобы понять конечный статус агрегата, например, лота или аукциона. И в этой ситуации Event Sourcing вполне оправдан.

Но иногда случается, что Event Sourcing это просто ненужное усложнение процесса. Ведь его легко сделать неправильно и очень сложно сделать правильно, потому что в нем есть много мест, где можно свернуть не туда.

Event Sourcing лучше всего применять в конкурентных и неизменяемых историях, говорит Алексей. Классическое место для этого шаблона финансовые транзакции. Есть финансовые события: зачисления или списания, и разработчику важно, чтобы их последовательность была, во-первых, четкой. Во-вторых, ее невозможно было отменить необходим однозначный конечный баланс. И Event Sourcing дает возможность сделать это так, чтобы цепочка событий всегда шла только вперед.

Подробнее обо всём начинается с 45:15

CQRS yay or nay?

Ребята обсудили, что CQRS это, скорее, паттерн, применяемый в технической области. Связан ли CQRS и DDD?

DDD больше заточено на side effects и изменения, а CQRS больше относится к отображению. И это его качество, как раз, применяется в Event Sourcing, потому что фактически есть только набор ивентов, а показывать, как правило, нужно данные, состояния объектов. А для того чтобы данные эти получить, нужно из ивентов делать проекции. В общем, если смотреть на CQRS под этим углом, получается история о синхронном взаимодействии с точки зрения UI/UX.

Подробное обсуждение этого непростого вопроса с 55:00.

Где и как научиться всему этому? (желательно до выхода на пенсию)

Алексей посоветовал начать с его доклада. Он подметил, что для того и рассказывал, чтобы дать интро по теме.

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

Можно ещё подписаться на сообщество DDDevotion и спросить там обо всем, что интересует. Подписчики могут проконсультировать в самых разных вопросах, например, как применять DDD в PHP, а также в других стэках.

Под конец разговора Рома ещё задал интересный вопрос: Kакая проблема должна стоять перед разработчиком, чтобы он понял, что пришло время углубиться в DDD? Если коротко, то сложно ответить коротко :) А подробно рассказали с 1:10:00.

Полезные материалы

Предыдущие выпуски подкаста Сушите вёсла

Подробнее..

Мир изменился CQRS и ES встречаются в PHP чаще, чем кажется

30.04.2021 20:15:00 | Автор: admin

Генри Форд чуть не прогорел на своей классической фразе про пятьдесят оттенков черного. General Motors стала предлагать разноцветные модели Chevrolet, Pontiac, Buick, Oldsmobile и Cadillac и не прогадала. Глядя на это, даже упрямый Форд изменил свое мышление и разработал новый Ford A, вернувший его на автомобильный Олимп. Бывают времена, когда парадигма мышления должна стать новой ибо человек умирает тогда, когда перестаёт меняться Генри Форд.

Пришло время и для разработчиков. Command Query Responsibility Segregation (CQRS) и Event Sourcing (ES) уже не миф они реально работают. Конечно, не для всех задач как и классический черный цвет Форда, PHP никуда не исчез и нужен по-прежнему. Но теперь уже есть задачи, где мы встречаемся с CQRS и ES чаще, чем нам кажется. Антон Шабовта на PHP Russia 2021 расскажет, как смена парадигмы и взгляд с другой стороны помогают разработчикам. А перед конференцией мы расспросили Антона подробнее о его новых взглядах на разработку, PHP и, конечно, оCQRS и ES.

Антон, расскажи о себе и о своей работе. Чем ты занимаешься?

Последние 12 лет я в коммерческой разработке и большая часть времени занимался проектами связанными с E-Commerce. Но 3 года назад мне захотелось применить свои знания в проектах другой сферы. Так я пришел в сервисную команду Onlinerа это крупнейший белорусский медиа портал с огромным количеством сервисов. Нашу команду разработки можно условно разделить на две части. Команда каталога занимается основном продуктом каталогом товаров. В нем почти два миллиона позиций от тысяч магазинов а это десятки миллионов товарных позиций. И этот действительно большой и сложный E-Commerce продукт, который продолжает развиваться и расти.

Команда сервисов, в которой я и работаю, занимается остальными нашими продуктами. Это сервисы аренды и продажи квартир, сервис поиска и предоставления услуг, авто- и мотоклассифайды и т.д. Есть еще огромный новостной портал с кучей инфраструктуры и сервисов вокруг него (комментарии, система личных сообщений, идентификация пользователей и пр.) Конечно, есть и сервисы, связанные с оплатой банковскими карточками и т.д. То есть это огромное скопление проектов в разных сферах и предметных областях.

По сравнению с E-Commerce это совершенно другой мир и другие задачи. И мне было интересно понять, могу ли я применить знания из предыдущих проектов подстроить, преобразить и переложить опыт из одной сферы на другую. Но и новому тоже хотелось учиться.

Твой доклад на конференции будет про долгий путь к CQRS и Event Sourcing. Это связано с твоей карьерой разработчика?

Да. Впервые я столкнулся с подходами Command Query Responsibility Segregation (CQRS) и Event Sourcing (ES) еще при работе с E-Commerce в 2015 году. И это стало важной вехой в моей карьере разработчика. Информации о CQRS и ES было много, но столько же возникало вопросов, мифов и недопонимания. Что именно представляют собой эти технологии? Как их использовать? Где стоит применять и какие проблемы они действительно призваны решать? Так вот одна из моих целей на PHP Russia 2021 развенчать часть этих мифов и показать, что мы сталкиваемся с CQRS и ES намного чаще, чем кажется, даже если раньше мы никогда не слышали эти слова.

В 2017 году, проработав два года с CQRS и ES, я сделал доклад об этом в рамках митапов Минской PHP User Group. Но, пересмотрев слайды, я понял, что в корне неверно подходил к объяснению этих технологий. За пять лет мое понимание значительно преобразилось, и я надеюсь, что на этот раз смогу лучше объяснить. Так что во многом доклад для PHP Russia 2021 это еще и работа над ошибками.

У тебя есть опыт с Erlang и Java (про С/С++, C# и Python знаем), или же ты целенаправленно изучаешь практики оттуда, чтобы рассмотреть их для PHP?

По-разному, it depends. Исторически так сложилось, что многие книги по архитектуре программных систем используют примеры и понятия из Java-мира. И чтобы не упустить какие-то ключевые моменты и важные нюансы, пришлось разбираться в Java. Недавно стряхнул пыль с этих знаний, когда искал решения для своих проектов и разбирался с фреймворками Axon и Akka. В целом же, практики из одного языка, по крайней мере, из Java, очень легко и просто переносятся на PHP.

С# я начал изучать, когда разбирался в устройстве фреймворка NServiceBus. В нем реализовано много классных решений, связанных с MBA (message-based architecture), SOA (service-oriented architecture) и сопутствующими технологиями.

Erlang это вообще отдельная история. Интерес к нему пришел в процессе изучения классического понятия ООП (объектно-ориентированного программирования) от Алана Кея и модели экторов. Это реально классный язык, совершенно непохожий на другие. Не могу сказать, что готов сейчас писать на нем production ready код, но изучать его концепции, конечно, продолжу.

Получается, что ты изучаешь, условно говоря, не какие-то языки, а перенимаешь практики из других языков, которые там успешны?

Не всегда то, что успешно работает в одном языке, будет работать в другом. Но в процессе изучения я вижу, когда какие-то практики можно попробовать.

Помогает ли знание других языков лучше писать на PHP?

И да, и нет. С одной стороны, многие практики и идеи можно (и нужно!) применять в PHP, особенно из близких по духу по подходам языков (Java, C#). ООП-модель PHP очень близка к этим языкам. К тому же мир разработки в PHP очень сильно изменился, например, после выхода фреймворка Symfony 2. Команда Symfony проделала колоссальную работу по прививанию паттернов проектирования в PHP community. Но большинство паттернов были придуманы не для PHP, а для других языков, в том числе, для Smalltalk и Java.

С другой стороны, из-за технических ограничений, некоторые интересные концепции невозможно развивать и применять в PHP. Например, многие подходы из мира функционального программирования и модели экторов, пропагандируемые Erlangом. Мы ограничены технологиями своего времени. Но, возможно, часть этих технологий в будущем можно будет применить и в PHP.

Когда нужны подходы из других языков, а когда лучше по старинке или попроще?

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

Я стараюсь для себя придерживаться KISS-принципа, то есть Keep it simple, stupid: если есть возможность делать что-то проще и не усложнять, то лучше так и сделать. Такие серьезные подходы как CQRS и ES несут много изменений не только в коде, а даже в самой модели мышления программиста. Мы ставим себя в определенные рамки, и за это придется платить. Не бывает серебряной пули в программировании.

Поэтому внедрять CQRS и ES не глядя, просто потому что можем очень-очень плохая идея. Можно получить намного больше проблем, чем пользы. Конечно, когда-то это оправдано, но не всегда. Поэтому нужно хорошее изучение problems face, чтобы понимать, зачем мы внедряем эту технологию и какую проблему бизнеса пытаемся ею решить.

Что дают эти подходы разработчику, в чем помогают?

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

Поэтому нет популярных фреймворков для CQRS и ES?

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

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

Создатель этих подходов Грег Янг любит повторять в своих докладах, что для реализации ES и CQRS достаточно двух операций:

  1. Сравнение по образцам (pattern matching);

  2. Лево-ассоциативная свертка списка (left fold) функция высшего порядка.

И многие языки поддерживают эти операции уже на уровне стандартной библиотеки. Например, тот же left fold в PHP существует как array_reduce, и дополнительно можно придумать другие варианты реализации.

Pattern matching, к сожалению, полностью в PHP еще не реализован, хотя работа в этом направлении ведется. Но та малая часть из pattern matching, которая нужна для имплементации ES, легко эмулируется в user-land коде.

Есть также много технологий, которые работают вокруг и рядом с CQRS и ES те же message-based architecture и service-oriented architecture. Для этих технологий уже есть фреймворки, хотя достаточно популярных в PHP-мире пока не сформировалось. Какие-то работы сейчас ведутся и какие-то фреймворки вырастают. Но enterprise production ready, решений уровня того же NServiceBus в C# либо Axon в Java, пока в PHP не сложилось. Ждем!

А есть ли учебник, где на пальцах правильно объясняются эти подходы?

Изучать CQRS и ES стоит с просмотра докладов отца-основателя Грега Янга, с его публичных выступлений, статей, материалов и записей в блоге. Он подробно пишет, как он пришел к этим подходам, и из каких проблем они возникли. Для продолжения есть его книга Versioning in an Event Sourced System там вы найдете для себя кое-какие нюансы.

Много материалов по ES и CQRS подходам можно найти в документации Microsoft. У них есть даже более развернутый вариант, который вышел в виде отдельной книги Exploring CQRS and Event Sourcing. Предисловие к книге написал тот же Грег Янг.

Еще этим технологиям много внимания уделяют те, кто пишут и работают с DDD-подходом (Domain-Driven Design), например, Vaugh Vernon. И у него есть книга Implementing Domain-Driven Design, в которой большая глава посвящена именно ES и CQRS.

Кому можно верить, не проверяя, в мире разработки и PHP: Фаулеру, Мартину, кому-то еще?

Никому. Серьезно. Мартин Фаулер, Роберт Мартин, тот же Грег Янг, а также другие авторы тратят сотни часов времени, чтобы поделиться своими знаниями в статьях, в записях блогов, в докладах и в книгах. Иногда пишутся целые научные работы по каким-то подходам. Это действительно круто, что мы имеем доступ к этой информации.

Но часто разработчик, прочитав статью или увидев доклад о той или иной технологии, тут же бежит её внедрять на своем проекте, забывая о проблеме, которую она должна решать. DDD, CQRS, ES и все другие сложные подходы появились для решения конкретных проблем, с которыми столкнулись их создатели. Вот что должно быть первоочередным для хорошего разработчика.

Я считаю, что безоговорочное доверие авторитетам, этот аристократичный синдром, наравне с культом карго это одна из ключевых проблем современного IT.

То есть ты сам не придерживаешься этого всего?

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

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

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

Чего ты ждёшь от конференции в этом году?

Онлайн-формат это, конечно, интересно и круто. Но пока я не могу сказать, что он может заменить оффлайн. Поэтому в первую очередь я жду, конечно, отличных докладов, много профессионального общения и интересных обсуждений в кулуарах. Я считаю, что эти обсуждения даже более ценны, чем доклады. Зажав спикера в кольцо, можно ему задать важные вопросы, которые не всегда есть время раскрыть в докладе. Очень часто какие-то действительно problem spaces остаются за рамками докладов.

Еще я жду новостей! С такими переносами, я думаю, к моменту начала конференции у нас их будет немало. Хотелось бы знать:

  • Что нас ждет в PHP 9?

  • Какая будет следующая большая цель на этот релиз? Возможно, это будет асинхронный PHP это важный лично для меня вопрос. На прошлом PHP Russia я читал доклад именно про асинхронный PHP.

  • Вопрос, волнующий всех: появятся ли у нас Generic-типы? Недавно добавили Union-типы. Скорее всего, скоро добавят пересечения, но Generic это то, что возникает так или иначе в вопросах на каждой PHP-конференции.

И афтепати, конечно!

PHP Russia 2021 пройдёт в гибридном формате будет и офлайн, и онлайн. Онлайн-зрители смогут задавать вопросы спикерам в зале, принимать участие в дискуссиях и участвовать в активностях на стендах партнёров.

Мы с нетерпением ждём нашу встречу в офлайне 28 июня 2021 года. Сегодня последний день до повышения цены сейчас стоимость очного участия 27 000 рублей

Подписывайтесь на наши соцсети, чтобы быть в курсе новостей (FB,VK,Telegram-канал,Twitter), общайтесь с коллегами в чате.

Подробнее..

Как построить надежное приложение на базе Event sourcing?

15.09.2020 14:04:30 | Автор: admin

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



The Project


Проект JoomAds предлагает продавцам инструменты продвижения товаров в Joom. Для продавца процесс продвижения начинается с создания рекламной кампании, которая состоит из:


  • списка товаров, продажи которых он хочет повысить;
  • бюджета того, сколько денег он готов потратить на продвижение товаров;
  • ставок на продукты того, какую долю от цены каждого товара продавец готов уступить за оптимизацию продаж или просмотров;
  • параметров таргетирования например, таргетирование на ключевые слова в поиске на манер AdWords.

Рекламная кампания это одна из частей состояния рекламного товара (см. Рис. 1), в которое также входят метаданные товара (наименование, доступные варианты, принадлежность к категории, и т.д.) и данные ранжирования (например, оценки эффективности показов).



Рис. 1


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


JoomAds API может изменять часть состояния при регистрации покупок успешно прорекламированных товаров, корректируя остаток бюджета рекламных кампаний (Рис. 1). Настройками кампаний управляет сервис кампаний JoomAds Campaign, метаданными продукта сервис Inventory, данные ранжирования расположены в хранилище аналитики (Рис. 2).


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



Рис. 2
JoomAds API выступает в роли медиатора данной микросервисной системы.


Pure Microservices equals Problems


Вы можете задать справедливый вопрос: Есть ли проблема в таком количестве внешних коммуникаций? Всего три вызова....


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


Быстродействие


Любые внешние коммуникации (например, поход за метаданными товара в Inventory) это дополнительные накладные расходы, увеличивающие время ответа медиатора. Такие расходы не проблема на ранних этапах развития проекта: последовательные походы в JoomAds Campaign, Inventory и хранилище аналитики вносили небольшой вклад во время ответа JoomAds API, т.к. количество рекламируемых товаров было небольшим, а рекламная выдача присутствовала только в разделе Лучшее.


Однако с ростом количества товаров в рекламе и подключением трафика других разделов Joom, 95-й перцентиль времени JoomAds API достиг сотен миллисекунд вместо желаемых десятков. Такая ситуация является результатом несоответствия текущих условий эксплуатации исходным требованиям, использованным при разработке отдельных компонентов.


Например, поиск товаров Inventory не был рассчитан на высокие частоты запросов, но он нам нужен именно таким.


Отказоустойчивость


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


Отказ любой зависимости JoomAds API ведет к некорректной или неповторяемой рекламной выдаче, либо к ее полному отсутствию.


Сложность поддержки


Микросервисная архитектура позволяет снизить сложность поддержки узкоспециализированных приложений, таких как Inventory, но значительно усложняет разработку приложений-медиаторов, таких как JoomAds API.


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


Осложняется отладка приложений-медиаторов в процессе разработки, т.к. для этого требуются либо репрезентативные копии микросервисов, либо точные mock-объекты, поддержка которых тоже требует времени.


Эти наблюдения привели нас к осознанию необходимости изменений. Новый JoomAds должен генерировать экономически эффективную и согласованную рекламную выдачу при отказе JoomAds Campaign, Inventory или хранилища аналитики, а также иметь предсказуемое быстродействие и отвечать на входящие запросы быстрее 100 мс в 95% случаев.


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


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


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


Monolith over microservices (kind of)


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


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


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


Materialization


Совместить лучшие качества микросервисов и монолитной архитектуры нам позволил подход, именуемый Materialized View. Материализованные представления часто встречаются в реализациях СУБД. Основной целью их внедрения является оптимизация доступа к данным на чтение при выполнении конкретных запросов.


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


Например, для запросов состояния продукта по его идентификатору (см. Рис. 3) или запросов состояния множества продуктов по идентификатору рекламной кампании.



Рис. 3


Материализованное представление данных расположено во внутреннем хранилище JoomAds API, поэтому замыкание входящих коммуникаций на него положительно сказывается на производительности и отказоустойчивости системы, т.к. доступ на чтение теперь зависит только от доступности / производительности хранилища данных JoomAds, а не от аналогичных характеристик внешних ресурсов. JoomAds API является надежным монолитным приложением!


Но как обновлять данные Materialized View?


Data Sourcing


Разработку стратегии обновления данных мы начали с формализации требований, которым она должна соответствовать:


  • Изолировать клиентскую сторону от проблем доступа к внешним ресурсам.
  • Учитывать возможность высокого времени ответа компонентов инфраструктуры JoomAds.
  • Предоставлять механизм восстановления на случай утраты текущего состояния Materialized View.

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


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


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


Обработка набора событий конкретного товара в порядке их поступления дает одинаковый результат при идентичном нулевом состоянии это свойство отлично подходит для реализации плана восстановления Materialized View в случае нештатных ситуаций.


Event Sourcing


Описанный в предыдущем разделе способ управления данными известен под названием Event Sourcing. Он предполагает наличие объектов-событий, содержащих информацию об изменениях в системе с возможностью установления хронологического порядка их наступления, благодаря чему мы можем восстановить состояние системы на определенный момент времени.


В результате адаптации Event Sourcing подхода в инфраструктуре JoomAds появились три новых компонента: хранилище материализованного представления (MAT View Storage), конвейер материализации (Materialization Pipeline), а так же конвейер ранжирования (Ranking Pipeline), реализующий поточное вычисление потоварных score'ов ранжирования (см. Рис. 4).



Рис. 4


Discussion, Technologies


Materialized View и Event Sourcing позволили нам решить основные проблемы ранней архитектуры проекта JoomAds.


Специализированные Materialized View значительно повысили надежность и быстродействие клиентских запросов. Обновление данных с использованием Event Sourcing подхода повысило надежность коммуникации с внешними сервисами, предоставило инструменты контроля консистентности данных и позволило избавиться от неэффективных запросов к внешним ресурсам.


Однако у всех решений есть цена. Чем больше несовместимых классов запросов реализует ваше приложение, тем больше материализованных представлений вам требуется собрать. Такой подход увеличивает потребление ресурсов по памяти, системе хранения данных и CPU. Материализованные представления JoomAds располагаются в хранилище Apache Cassandra, поэтому процесс порождения новых представлений, удаления старых или модификации существующих можно назвать безболезненным.


В нашем случае MAT View целиком хранится в одной таблице Cassandra: добавление колонок в таблицы Cassandra безболезненная операция, удаление MAT View осуществляется удалением таблицы. Таким образом, крайне важно выбрать удачное хранилище для реализации Materialized View в вашем проекте.


Event Sourcing предъявляет серьезные требования к своим пользователям. Генерация событий изменения данных во всех интересующих подсистемах в заданном формате с возможностью установления хронологического порядка следования это сложная организационно-техническая задача, которую крайне трудно реализовать в середине жизненного цикла ПО. Можно назвать удачей, что хранилище данных Inventory уже имело функцию генерации событий на обновление метаданных продуктов.


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


Вместо этого мы воспользовались популярными open-source решениями, развивающимися при участии Apache Software Foundation: Apache Kafka и Apache Flink.


Помимо организационно-технологических сложностей, событийно-ориентированным системам свойственно т.н. eventually consistent состояние данных, что может вносить дополнительную сложность в процессы обработки информации.


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


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


Takeaway


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


P.S. Этот пост был впервые опубликован в блоге Joom на vc, вы могли его встречать там. Так делать можно.

Подробнее..

Перевод Знакомимся с Event Sourcing. Часть 1

08.09.2020 18:17:15 | Автор: admin
Перевод статьи подготовлен в преддверии старта курса Java Developer. Professional.



Event sourcing (источники событий, регистрация событий, генерация событий) это мощный архитектурный шаблон, при котором все изменения, вносимые в состояние приложения, сохраняются в той последовательности, в которой они происходили. Эти записи служат как источником для получения текущего состояния, так и журналом аудита того, что происходило в приложении за время его существования. Event sourcing способствует децентрализованному изменению и чтению данных. Такая архитектура хорошо масштабируется и подходит для систем, которые уже работают с обработкой событий или хотят перейти на такую архитектуру.

Что такое Event Sourcing


Эксперты предметной области обычно описывают свои системы как совокупность сущностей (entity), представляющих собой контейнеры для хранения состояния и событий (event), отображающих изменения сущностей в результате обработки входных данных в рамках различных бизнес-процессов. Часто события инициируется командами (command), исходящими от пользователей, фоновых процессов или интеграций с внешними системами.

По сути, Event sourcing фокусируется на событиях, связанных с изменениями в системе.

Многие архитектурные шаблоны рассматривают сущности как первоочередную концепцию. Эти шаблоны описывают то, как их сохранять, как к ним получать доступ и как их модифицировать. В рамках такого архитектурного стиля события часто находятся сбоку: являются последствиями изменения сущностей.

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

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

Ниже показано сравнение хранилища событий (Event Store) с хранилищем сущностей (Entity Store) (подробнее будет описано далее):



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

  • Помогает уменьшить несоответствие импеданса и необходимость в сопоставлении концепций, позволяя технологическим командам говорить на одном языке с бизнесом при обсуждении системы.
  • Поощряет разделение ответственности на команды и запросы (command/query responsibility), позволяя оптимизировать запись и чтение независимо друг от друга.
  • Обеспечивает темпоральность и историю изменений, как само собой разумеющееся, позволяя отвечать на вопросы о том, как система выглядела в определенные моменты в прошлом и какие события происходили до этого момента.


Принцип работы Event Sourcing


Рассмотрим простой пример с банковским счетом. У нас будет сущность (entity), представляющая собой банковский счет (Bank Account). Для простоты сделаем только один счет без его идентификации с помощью номера счета или каким-либо другим способом. Счет будет хранить текущий остаток средств.

Для счета будут доступны две команды (command): внести деньги (deposit) и снять деньги (withdraw). В командах будет указываться сумма для внесения или снятия. Также определим бизнес-правило, которое проверяет, что команда на снятие средств может быть обработана только в том случае, если запрашиваемая сумма равна или меньше текущего остатка на счете.

При таком подходе можно выделить два события (event) Account Credited (Счет пополнен) и Account Debited (Средства списаны со счета). В этих событиях есть информация о сумме (amount), которая была внесена или снята. Здесь можно было бы упростить до одного события с положительной или отрицательной суммой, но в данном примере мы их разделим.

На диаграмме ниже показана модель данных.



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

Последовательность команд может выглядеть следующим образом:

1. deposit { amount: 100 } внести 100
2. withdraw { amount: 80 } снять 80
3. withdraw { amount: 50 } снять 50

Самая простая реализация Event Sourcing требует журнала событий (event log), который представляет собой просто последовательность событий. При обработке команд, приведенных выше, получится такой журнал.



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

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

  • bank account { current balance: 0 } (starting state)
    банковский счет {текущий баланс: 0 } (начальное состояние)
  • bank account { current balance: 100 } (processed: Account Credited, +100)
    банковский счет {текущий баланс: 100 } (обработано: Счет пополнен, +100)
  • bank account { current balance: 20 } (processed: Account Debited, -80)
    банковский счет {текущий баланс: 20 } (обработано: Средства списаны со счета, -80)


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

Это законченный (хоть и тривиальный) пример Event Sourcing. В реальной системе, скорее всего, этот пример придется расширить.

Возможно, потребуется сохранять последовательность команд, чтобы была возможность идентифицировать, как возникло событие, а также сделать отдельный журнал ошибочных событий (error event), в который записывать команды, которые не удалось выполнить, для дальнейшей обработки ошибок и ведения полной истории успешных и неуспешных команд.

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

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



Очевидно, что по сравнению с полноценным хранилищем событий (Event Store), это очень примитивный пример. И это одна из причин, по которой многие разработчики используют только хранилище сущностей. В этом случае текущий остаток на счете доступен сразу и нет необходимости обрабатывать все исторические события.

Однако Event Sourcing не исключает хранилища сущностей. Часто хранилища сущностей присутствуют и в Event Sourcing проектах.

Конец первой части.
Подробнее..

Перевод Знакомимся с Event Sourcing. Часть 2

24.09.2020 16:22:36 | Автор: admin
Перевод статьи подготовлен в преддверии старта курса Java Developer. Professional.
Читать первую часть.



Особенности реализации Event Sourcing


С технической точки зрения для Event Sourcing требуется только реализация записи событий в журнал и чтения из журнала.

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

Журнал событий (event log) очень распространенный паттерн, используемый совместно с системами обмена сообщениями (Message broker, Message-oriented middleware) и системами обработки потоков событий. Брокер сообщений, используемый как журнал событий, при необходимости может хранить всю историю сообщений.

Реляционные и документные модели обычно фокусируются на моделировании сущностей. В таких моделях текущее состояние легко получить, прочитав одну или несколько строк или документов. Стоит отметить, что Event Sourcing и реляционная модель не исключают друг друга. Event Sourcing-системы часто включают в себя и то и другое. Ключевое отличие Event Sourcing заключается в том, что к хранилищу сущностей уже не относятся как к исходным данным. Его можно заменить или перестроить через повторную обработку журнала событий.

В более сложных Event Sourcing-системах должны присутствовать производные хранилища состояния для эффективных запросов на чтение, так как получение текущего состояния через обработку всего журнала событий со временем может перестать масштабироваться. И реляционные, и документные БД могут использоваться и как журнал событий и как хранилище производных сущностей, через которые можно быстро получить текущее состояние. Фактически такое разделение задач представляет собой CQRS (Command Query Responsibility Segregation, разделение ответственности на команды и запросы). Все запросы направляются в производное хранилище, что позволяет оптимизировать его независимо от операций записи.

Помимо технической части есть и другие моменты, на которые стоит обратить внимание.

Потенциальные проблемы Event Sourcing


Несмотря на преимущества Event Sourcing, у него есть и недостатки.

Самые большие сложности обычно связаны с мышлением разработчиков. Разработчики должны выйти за рамки обычных CRUD-приложений и хранилищ сущностей. Теперь основной концепцией должны стать события.

При Event Sourcing много сил тратится на моделирование событий. После записи событий в журнал они должны считаться неизменными, иначе, и история и состояние могут быть повреждены или искажены. Журнал событий это исходные данные, а это значит, что необходимо очень внимательно следить за тем, чтобы они содержали всю информацию, необходимую для получения полного состояния системы на определенный момент времени. Также необходимо учитывать, что события могут интерпретироваться повторно, поскольку система (и бизнес, который она представляет) со временем изменяются. И не надо забывать про ошибочные и подозрительные события с корректной обработкой валидации данных.

Для простых моделей предметных областей такое изменение мышления может быть довольно легким, но для более сложных может стать проблемой (особенно с большим количеством зависимостей и отношений между сущностями). Могут возникнуть сложности интеграции с внешними системами, которые не предоставляют данные на определенный момент времени.

Event Sourcing может хорошо работать в больших системах, так как паттерн журнал событий естественным образом масштабируется горизонтально. Например, журнал событий одной сущности необязательно должен физически находиться вместе с журналом событий другой сущности. Однако, такая легкость масштабирования приводит к дополнительным проблемам в виде асинхронной обработки и согласования данных в конечном счете (eventually consistent). Команды на изменение состояния могут приходить на любой узел, после чего системе необходимо определить, какие узлы отвечают за соответствующие сущности и направить команду на эти узлы, после чего обработать команду, а затем реплицировать сгенерированные события на другие узлы, где хранятся журналы событий. И только после завершения этого процесса новое событие становится доступным как часть состояния системы. Таким образом, Event Sourcing фактически требует, чтобы обработка команд была отделена от запроса состояния, то есть CQRS.

Поэтому Event Sourcing-системам необходимо учитывать промежуток времени между выдачей команды и получением уведомления об успешной записи события в журнал. Состояние системы, которое пользователи видят в это время, может быть неправильным. Или, точнее, немного устаревшим. Для уменьшения влияния этого фактора необходимо его учитывать при проектировании интерфейса пользователя и в других компонентах. Также необходима правильная обработка ситуаций, когда команда завершается ошибкой, отменяется в процессе выполнения или одно событие заменяется более новым при корректировке данных.

Еще одна проблема возникнет, когда со временем накопятся события и с ними нужно будет работать. Одно дело только записывать их после обработки, другое работать со всей историей. Без этого функционала журнал событий полностью теряет свою ценность. Особенно это актуально для восстановления после сбоя или при миграциях производных хранилищ, когда для актуализации данных может потребоваться повторная обработка всех событий. Для систем с большим количеством событий повторная обработка всего журнала может превысить допустимое время восстановления. Здесь могут помочь периодические снимки состояния системы (snapshot), чтобы можно было начать восстановление с более позднего исправного состояния.

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

Выводы


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

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

И напоследок, не забывайте самый важный принцип программной инженерии стремиться к тому, чтобы все было как можно проще (принцип KISS).

Читать первую часть

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru