Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

Я вижу, что Oleh Dokuka, из Project Reactor (отсутствует упоминание о нем), отправил ответ уже, однако, многие из его предположений о Akka Streams и Реактивный Потоки неверны, поэтому позвольте мне пояснить ниже.

Отказ от ответственности: Я принимал участие в оперативных потоках с ранних дней, а авторский комплект совместимости технологий. Я также поддерживаю потоки Акка и Акка.

Также обратите внимание, что: Реактивные потоки были включены в Java 9 и известны как java.util.concurrent.Flow. * so все комментарии, приведенные ниже относительно RS, точно так же относятся к j.u.c.Flow.Subscriber и другим типам.


Ответ

Реактивные потоки - это спецификация интерфейса поставщика услуг (SPI)

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

В самые ранние дни спецификации даже типы spec пытались скрыть Publisher, Subscriber и другие типы. К сожалению, типы будут течь независимо от того, что тогда было рассмотрено API, таким образом, API (!) Был удален, и все типы SPI остались.

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

Для справки, RxJava 2.0, а также Reactor действительно расширяют эти типы, в то время как потоки Akka остаются верными дизайну и принципам RS, скрывая их как интерфейс программирования разработчиков приложений - вот почему Sink не расширяет Subscriber. Это не имеет никакого отношения к тому, чтобы быть "родной поддержкой", как я видел, как люди утверждают, что прямые отношения IS-A (а скорее, утверждают, что библиотека inter-op, являющаяся вашим "родным", является непониманием концепции).

Раковины и подписчики, источники и издатели

Понятия раковины и подписчика кажутся мне похожими.

Правильно, они, по назначению и по дизайну, похожи.

Поскольку Sink является отмененным представлением того, что эффективно дает Абоненту. Чтобы упростить, вы можете думать о нем как о "подписчике factory" (точнее, "Раковина" - это "план", а материализатор берет проект раковины и создает соответствующие ступени RS, в том числе "Издатели для источников и подписчиков для стоков", Поэтому, когда вы говорите, что Sink.ignore на самом деле представляет собой factory, это приведет к созданию Абонента, который выполняет все запросы и игнорирует, как в соответствии с реактивными потоками. То же самое со всеми другими методами, объявленными в Sink.

То же самое относится к Source, который связывает 1:1 с реактивными потоками Publisher. Таким образом, Source.single(1) - это то, что внутренне материализуется в Publisher, которое делает это задание, - испускает этот 1 элемент, если он разрешает это делать по нему.

A.K.A. Почему нет раковины в реактивных потоках?

Как упоминалось выше, Akka Sink напрямую не расширяет подписчика. Это, однако, в основном factory для них.

Вы можете спросить: "Пользователь никогда не видит эти типы Publisher/Subscriber вообще, хотя во время обычного использования?" И ответ: да, и это особенность, а также цель дизайна (в соответствии с тем, что происходит с реактивными потоками). Если базовые экземпляры Publisher и Subscriber были открыты для пользователей все время напрямую, их можно назвать неправильными, вызывая ошибки и путаницу. Если эти типы никогда не раскрываются, если их явно не задают, вероятность случайных ошибок меньше!

Некоторые из них неправильно поняли этот дизайн и заявили, что в потоках Akka нет "родной" поддержки (что неверно). Давайте посмотрим, что отделяет нас от Абонента в API:

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

Действительно, Sinks не являются частью Reactive Streams, и это абсолютно нормально.

Преимущества от избежания "Подписчика IS-A Sink"

Sink являются частью потоков Akka, и их целью является предоставление свободного DSL, а также заводы для Subscribers. Другими словами, если подписчик является блоками LEGO, то Sink - это то, что их создает (и поток Akka Materializer - это то, что объединяет различные блоки LEGO, чтобы "запустить" их).

На самом деле, полезно пользователям, что Sink не несет какой-либо окончательный IS-A с подписчиком (sic!), как это делают другие библиотеки:

Это связано с тем, что поскольку org.reactivestreams.Subscriber теперь включен в Java 9 и стал частью самой Java, библиотеки должны перейти на использование java.util.concurrent.Flow.Subscriber вместо org.reactivestreams.Subscriber. Библиотеки, которые выбрали для раскрытия и прямого распространения типов реактивных потоков, теперь будут иметь более жесткое время для адаптации типов JDK9 - все их классы, которые расширяют подписчиков и друзей, необходимо будет скопировать или изменить, чтобы расширить тот же интерфейс, но из другой упаковка. В Akka мы просто выставляем новый тип, когда его просят - уже поддерживая типы JDK9, со дня выпуска JDK9.

С реактивными потоками, являющимися SPI - интерфейсом поставщика услуг - он предназначен для того, чтобы библиотеки могли делиться такими, чтобы они могли "говорить одни и те же типы и протокол". Все сообщения, которые делают Akka Streams, и другие библиотеки Reactive Streams, соответствуют этим правилам, и если вы хотите подключить какую-то другую библиотеку к потокам Akka, вы сделаете именно это - дайте Akka Streams межоперационный тип, который является подписчиком, процессором или издателем; а не Sink, так как именно Akka "Akka specific" DSL (доменный язык), который добавляет удобство и другие тонкости поверх него, скрывает (по назначению!) тип подписчика.

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

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