«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Почему мы исключили архитектуру реактивных систем из нашего кода?

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

Опубликовано 2 сентября 2024 г.
Просматривать:878

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

Понимание стиля реактивной архитектуры

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

  1. Отзывчивость: Способность быстро обрабатывать запросы даже при больших нагрузках.
  2. Устойчивость: Способность восстанавливаться после сбоев с минимальным временем простоя.
  3. Эластичность: Возможность адаптации к изменяющимся рабочим нагрузкам путем соответствующего масштабирования ресурсов.
  4. Управление сообщениями: Использует асинхронный обмен сообщениями для повышения отказоустойчивости и разделения компонентов.

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

Why we discarded Reactive systems architecture from our code?

Рис. 1. Традиционная многопоточность


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

Модель реактивного выполнения

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

Why we discarded Reactive systems architecture from our code?

Рис. 2. Реактивный цикл обработки событий


Кваркус и реактивный

Quarkus использует реактивный механизм на базе Eclipse Vert.x и Netty, облегчающий неблокирующее взаимодействие ввода-вывода. Mutiny, предпочтительный подход к написанию реактивного кода с помощью Quarkus, использует парадигму, управляемую событиями, в которой реакции запускаются полученными событиями.

Mutiny предлагает два событийно-ориентированных и ленивых типа:

  1. Uni: Выдает одно событие (элемент или сбой), подходящее для представления асинхронных действий с нулевым или одним результатом.
  2. Multi: Генерирует несколько событий (n элементов, один сбой или одно завершение), представляющих потоки элементов, потенциально неограниченные.

Проблемы с реактивом

Хотя реактивные системы обладают преимуществами, во время разработки мы столкнулись с рядом проблем:

  • Смена парадигмы: Реактивное программирование требует фундаментального изменения в мышлении разработчиков, что может оказаться непростой задачей, особенно для разработчиков, привыкших к императивному программированию. В отличие от вспомогательных инструментов, таких как Streams API, реактивный подход требует полного пересмотра мышления.
  • Чтение и понимание кода. Реактивный код создает трудности для понимания новых разработчиков, что приводит к увеличению времени, затрачиваемого на его расшифровку и понимание. Сложность, привносимая реактивными парадигмами, усугубляет эту проблему.

»Действительно, соотношение времени, затрачиваемого на чтение и запись, значительно превышает 10 к 1. Мы постоянно читаем старый код, пытаясь написать новый код. ...[Следовательно] облегчение чтения делает его более простым для чтения. легче писать."
Роберт К. Мартин, Чистый код: справочник по гибкому мастерству разработки программного обеспечения

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

Вот пример реактивного кода с использованием Mutiny, чтобы проиллюстрировать сложность:

Multi.createFrom().ticks().every(Duration.ofSeconds(15))
    .onItem().invoke(() - > Multi.createFrom().iterable(configs())
    .onItem().transform(configuration - > {
  try {
    return Tuple2.of(openAPIConfiguration,
        RestClientBuilder.newBuilder()
            .baseUrl(new URL(configuration.url()))
            .build(MyReactiveRestClient.class)
            .getAPIResponse());

  } catch (MalformedURLException e) {
    log.error("Unable to create url");

  }
  return null;
}).collect().asList().toMulti().onItem().transformToMultiAndConcatenate(tuples - > {

  AtomicInteger callbackCount = new AtomicInteger();
  return Multi.createFrom().emitter(emitter - > Multi.createFrom().iterable(tuples)
      .subscribe().with(tuple - >
          tuple.getItem2().subscribe().with(response - > {
              emitter.emit(callbackCount.incrementAndGet());

  if (callbackCount.get() == tuples.size()) {
    emitter.complete();
  }
                    })
                ));

}).subscribe().with(s - > {},
Throwable::printStackTrace, () - > doSomethingUponComplete()))
    .subscribe().with(aLong - > log.info("Tic Tac with iteration: "   aLong));

Перспективы будущего: ткацкий станок проекта и не только

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

"Project Loom убьет реактивное программирование"
Брайан Гетц

Заключение

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

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

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

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

Why we discarded Reactive systems architecture from our code?

Заявление о выпуске Эта статья воспроизведена по адресу: https://dev.to/yanev/why-we-discarded-reactive-systems-architecture-from-our-code-19ni?1 Если есть какие-либо нарушения, пожалуйста, свяжитесь с [email protected] удалить его
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3