Автор статьи: Артем Михайлов


Введение в концепцию event-driven архитектуры


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

Обзор основных принципов и преимуществ использования event-driven архитектуры

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

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

Как event-driven архитектура отличается от традиционной монолитной архитектуры?

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

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

Применение event-driven архитектуры на практике


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

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

Для Python существует множество популярных библиотек для реализации event-driven подхода. Одна из самых популярных – это asyncio, которая является частью стандартной библиотеки Python с версии 3.4. asyncio позволяет выполнять асинхронные операции и обрабатывать события, не блокируя поток.

Еще одной фундаментальной библиотекой для event-driven подхода в Python является Twisted. Она предоставляет общие базовые классы для создания асинхронных приложений, асинхронного сетевого программирования, а также реализацию стандартных протоколов (HTTP, FTP и других). Twisted используется в таких проектах, как Dropbox, BitTorrent и Skype.

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

Мы можем создать простое event-driven приложение на примере чата, используя библиотеку asyncio. В качестве основы будем использовать пример из официальной документации Python. Мы можем создать сервер, который будет обрабатывать подключения клиентов, получать от них сообщения и распространять их на всех подключенных пользователей.

Пример кода выглядит следующим образом:
import asyncio
import websockets
 
connected = set()
 
async def handler(websocket, path):
    # Регистрация нового подключения 
    connected.add(websocket)
    try:
        while True:
            # Чтение сообщения от клиента
            message = await websocket.recv()
            # Отправка сообщения подключенным пользователям
            await asyncio.gather(*[ws.send(message) for ws in connected])
    finally:
        # Удаление сокета из списка подключений
        connected.remove(websocket)
 
# Запуск сервера
async def main():
    async with websockets.serve(handler, "localhost", 8080):
        await asyncio.Future()  # run forever
 
asyncio.run(main())


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

Использование event-driven подхода позволяет создать быстрое и отзывчивое приложение на Python. Если вы хотите создать асинхронное приложение, которое будет быстро реагировать на события, то рекомендуется использовать asyncio. Однако при решении конкретных задач можно использовать и другие библиотеки, которые специализируются на определенных областях.

Паттерны проектирования для event-driven архитектуры


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

Рассмотрим несколько популярных паттернов проектирования для event-driven архитектуры.

1. Observer

Паттерн Observer используется для оповещения об изменениях в объекте других объектов, которые на него подписаны. В event-driven архитектуре этот паттерн используется для регистрации и обработки событий.

Пример реализации на Python:

class Sensor:
    def __init__(self):
        self.observers = []

    def register_observer(self, observer):
        self.observers.append(observer)

    def notify_observers(self, data):
        for observer in self.observers:
            observer.update(data)

class AlertSystem:
    def update(self, data):
        if data > 100:
            print("Alert! Temperature is too high")

class DataRecorder:
    def update(self, data):
        print("Recording data: {}".format(data))

sensor = Sensor()
alert_system = AlertSystem()
data_recorder = DataRecorder()

sensor.register_observer(alert_system)
sensor.register_observer(data_recorder)

sensor.notify_observers(80)
sensor.notify_observers(110)


В данном примере у нас есть класс Sensor, который может генерировать данные (например, температуру). У этого класса есть список observers – объектов, которые должны быть оповещены об изменениях данных. Когда вызывается метод notify_observers, все объекты из списка observers получают уведомление об изменениях. Классы AlertSystem и DataRecorder являются примерами таких объектов.

2. Command

Паттерн Command используется для инкапсуляции запроса как объект и передачи его другим объектам, которые могут его обработать. В event-driven архитектуре этот паттерн используется для обработки событий.

Пример реализации на Python:

class Sensor:
    def __init__(self):
        self.command = None

    def set_command(self, command):
        self.command = command

    def generate_data(self, data):
        self.command.execute(data)

class AlertCommand:
    def execute(self, data):
        if data > 100:
            print("Alert! Temperature is too high")

class RecordCommand:
    def execute(self, data):
        print("Recording data: {}".format(data))

sensor = Sensor()
alert_command = AlertCommand()
record_command = RecordCommand()

sensor.set_command(alert_command)
sensor.generate_data(80)
sensor.generate_data(110)

sensor.set_command(record_command)
sensor.generate_data(80)


В данном примере у нас есть класс Sensor, который может генерировать данные, и классы AlertCommand и RecordCommand, которые могут обработать эти данные. Когда вызывается метод generate_data, объект Sensor передает данные в команду, которая была установлена ранее методом set_command.

3. Mediator

Паттерн Mediator используется для координации действий между различными объектами. В event-driven архитектуре этот паттерн используется для координации обработки событий.

Пример реализации на Python:

class Sensor:
    def __init__(self, mediator):
        self.mediator = mediator

    def generate_data(self, data):
        self.mediator.process_data(data)

class AlertSystem:
    def process_data(self, data):
        if data > 100:
            print("Alert! Temperature is too high")

class DataRecorder:
    def process_data(self, data):
        print("Recording data: {}".format(data))

class Mediator:
    def __init__(self):
        self.alert_system = AlertSystem()
        self.data_recorder = DataRecorder()

    def process_data(self, data):
        self.alert_system.process_data(data)
self.data_recorder.process_data(data)

mediator = Mediator()
sensor = Sensor(mediator)

sensor.generate_data(80)
sensor.generate_data(110)


В данном примере мы используем класс Mediator, который координирует действия объектов AlertSystem и DataRecorder. Класс Sensor использует этот медиатор для передачи сгенерированных данных.

У нас есть множество других паттернов, которые можно использовать для проектирования event-driven архитектуры, таких как Chain of Responsibility, Factory Method, и т.д. Использование этих паттернов позволяет создавать более гибкие и расширяемые приложения, которые могут обрабатывать большое количество событий и данных.

Инструменты для мониторинга и отладки event-driven приложений


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

Среди этих инструментов можно выделить:

1. New Relic — платформа мониторинга, которая предоставляет информацию о состоянии приложения в режиме реального времени. Она позволяет отслеживать работу приложения на уровне кода, инфраструктуры и пользовательского опыта. New Relic также предоставляет метрики производительности, анализ данных и оптимизацию кода.

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

3. Stackify — это инструмент мониторинга и отладки, который позволяет отслеживать состояние ресурсов, проблемы производительности и ошибки в приложении. Stackify позволяет отслеживать добавление файлов в приложение, редактирование таблиц базы данных, анализ времени выполнения функций и другие аспекты приложения.

4. AppDynamics — это платформа мониторинга приложений, которая предоставляет информацию о производительности, статистики на протяжении всего жизненного цикла приложения. Она позволяет анализировать производительность приложения через интеграцию с другими инструментами, такими как Jira, Git и другие.

5. Dynatrace — это интеллектуальная платформа мониторинга, которая автоматически анализирует состояние приложения в реальном времени. Она позволяет отслеживать производительность, анализировать пользовательский опыт и определить ошибки в приложении.

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

Выводы


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

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

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

В конце статьи хочу порекомендовать вам бесплатный вебинар, а рамках которого эксперты OTUS расскажут, как использовать события для асинхронного взаимодействия, какие это дает плюсы и минусы по сравнению с request-reply архитектурой. Также будут рассмотрены некоторые паттерны реализации систем с использованием событий. Зарегистрироваться на вебинар можно по ссылке ниже.

Комментарии (6)


  1. sergey_prokofiev
    08.06.2023 06:46
    +4

    Event-driven архитектура — это новая концепция программирования

    НОВАЯ


    1. shai_hulud
      08.06.2023 06:46

      для всех нет, для автора да

      Hidden text

      если так придираться, то все "новые" концепции уже были изобретены бородачами в 60х, что растовские контракты памями, что async/await итд.


    1. cupraer
      08.06.2023 06:46

      Через годик ждем текст про акторную модель.


  1. iggr63
    08.06.2023 06:46
    +1

    Сразу вспомнилось Борланд Турбо С++ и event-driven paradigm.


  1. jenki
    08.06.2023 06:46
    +1

    Практически все оконные интерфейсы построены в event-driven paradigm много лет тому назад. С компьютерными игрушками тоже самое много лет тому назад. Практически основа облака Амазон. Их первый сервис был как раз брокер сообщений, а не виртуальные машины. Это совсем не новый, но крайне палезный паттерн в случае микросервисов. Только его надо уметь, чтобы не скатиться в синхронную архитектуру через брокер сообщений, или как ещё назвать))

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


    1. iggr63
      08.06.2023 06:46

      Точно. VisiBroker!