Reactor netty что это
Конфигурация Пружинного загрузочного реактора Нетти
Узнайте о различных параметрах конфигурации сервера Reactor Netty в приложении Spring Boot
1. Обзор
В этом уроке мы рассмотрим различные варианты конфигурации сервера Reactor Netty в приложении Spring Boot. В конце концов, у нас будет приложение, демонстрирующее различные подходы к настройке.
2. Что Такое Реактор Нетти?
Прежде чем мы начнем, давайте посмотрим, что такое реактор Нетти и как он связан с Spring Boot.
Теперь давайте посмотрим, где Весна и Весенний ботинок входят в картину.
Теперь мы создадим приложение, чтобы узнать, как мы можем настроить ваш автоматически настроенный сервер Reactor Netty. После этого мы рассмотрим некоторые распространенные сценарии конфигурации.
3. Зависимости
Во-первых, мы добавим необходимую зависимость Maven.
Чтобы использовать сервер Reactor Netty, мы добавим spring-boot-starter-web flux в качестве зависимости в ваш файл pom:
Это также втянет spring-boot-starter-reactor-netty в качестве транзитивной зависимости в наш проект.
4. Конфигурация сервера
4.1. Использование файлов Свойств
В качестве первого варианта мы можем настроить сервер Netty с помощью файлов свойств. Spring Boot предоставляет некоторые из распространенных конфигураций сервера в файле application properties:
Давайте определим порт сервера в application.properties :
Или мы могли бы сделать то же самое в application.yml :
4.2. Использование Программной Конфигурации
Давайте используем эти классы для настройки порта Netty, как мы делали ранее с нашим файлом свойств:
Spring Boot подберет наш настроенный на заводе компонент во время запуска и настроит порт сервера.
В качестве альтернативы мы можем реализовать Netty Server Customizer :
И добавьте его на фабрику серверов:
Эти два подхода дают нам большую гибкость при настройке нашего встроенного сервера Reactor Netty.
Кроме того, мы также можем получить доступ к классу Server Bootstrap из Netty framework и выполнить там ваши настройки:
Однако в этом случае есть одно предостережение. Поскольку Spring Boot автоматически настраивает сервер Netty, нам может потребоваться пропустить автоматическую настройку, явно определив наш NettyReactiveWebServerFactory bean.
Для этой цели мы должны определить ваш компонент в классе конфигурации и добавить туда наши настройки:
Далее мы продолжим с некоторыми распространенными сценариями конфигурации Netty.
5. Настройка SSL
Давайте посмотрим, как мы можем настроить SSL.
Здесь мы определили наши свойства, связанные с хранилищем ключей, отключили HTTP/2 и установили порт на 8443.
6. Конфигурация журнала доступа
Spring Boot позволяет нам настроить ведение журнала доступа в файле свойств приложения для Tomcat, Jetty и Undertow. Однако у Нетти пока нет такой поддержки.
Чтобы включить ведение журнала доступа Netty, мы должны установить -Director.netty.http.server.access Log Enabled=true при запуске нашего приложения:
7. Заключение
В этой статье мы рассмотрели, как настроить сервер Reactor Netty в приложении Spring Boot.
Во-первых, мы использовали общие возможности конфигурации на основе свойств Spring Boot. А затем мы изучили, как программно настроить Netty в мелкозернистой манере.
Java и Project Reactor
Всем привет! Меня зовут Лёха, и я работаю бэкенд-разработчиком в FunCorp. Сегодня мы поговорим про реактивное программирование, библиотеку Reactor и немного про веб.
Реактивное программирование часто «подвергается упоминанию», но если вы (как и автор статьи) всё ещё не знаете, что это такое — устраивайтесь поудобнее, попробуем разобраться вместе.
Что же такое реактивное программирование?
Реактивное программирование — это управление асинхронными потоками данных. Вот так просто. Мы люди нетерпеливые и не вникаем во все эти ваши манифесты с подробностями, а стоило бы.
Причём тут веб?
Ходят слухи, что если выстраивать свою систему реактивно, согласно всем канонам Reactive Manifesto, начиная с HTTP-сервера и заканчивая драйвером БД, можно вызвать второе пришествие. Ну, или хотя бы построить действительно качественный бэкенд.
Это, конечно, лёгкое лукавство. Но если ваш юзкейс — обработка множественных и не всегда быстрых запросов, а контейнер сервлетов перестаёт справляться — добро пожаловать в прекрасный мир реактивного!
If you have 128 continuous parallel requests, a servlet container is probably not the right tool for the job.
А на чём писать реактивно, если не на Netty? Стоит отметить, что написание бэкенда на голом Netty утомительно, и приятно иметь абстракции для работы.
Годных серверных абстракций для Netty много не бывает, поэтому ребята из Pivotal добавили в Spring Boot 2 его поддержку. 1 марта 2018 года всё это даже зарелизилось. Чтобы сделать нам совсем приятно, они создали модуль WebFlux, который является альтернативой Spring MVC и представляет собой реактивный подход для написания веб-сервисов.
WebFlux позиционирует себя как микрофреймворк (микрофреймворк и Spring, ха-ха), обещает вписаться в эти ваши (наши) модные микросервисы, представляет API в функциональном стиле и уже упоминался на Хабре. Более подробно (в т.ч. об отличиях от Spring MVC) можно почитать здесь. Но сегодня о другом. В основе WebFlux лежит библиотека Reactor. О ней и поговорим.
Reactor — это реактивная (внезапно!) open-source-платформа, разрабатываемая Pivotal. Я решился на вольный пересказ (с комментариями) введения в эту замечательную библиотеку.
Blocking code (для самых маленьких)
Программный код на языке Java обычно блокирующий. Например, вызовы по HTTP или запросы к БД вешают наш текущий поток до момента, пока нам не ответит сторонний сервис. Это нормальная практика, если сервис отвечает за приемлемое время. В противном случае это дело превращается в bottleneck. Мы вынуждены его распараллелить, запускать больше потоков, которые будут выполнять один и тот же блокирующий код. Попутно приходится решать возникающие проблемы с contention и конкурентностью.
Частое блокирование, особенно из-за I/O (а уж если у вас много мобильных клиентов, то совсем не быстрого I/O), заставляет наши многочисленные потоки просиживать штаны в ожидании данных, тратя драгоценные ресурсы на переключение контекста и всякое такое.
Параллелизация — это не волшебная палочка, решающая все проблемы. Это сложный инструмент, несущий свой оверхед.
Async && non-blocking
Эти термины легко найти, сложно понять и невозможно забыть. Но они часто фигурируют, когда речь идёт о реактивности, поэтому попробуем разобраться в них.
Из текста выше можно сделать вывод, что во всём виноват блокирующий код. Окей, давайте начнём писать неблокирующий. Что под этим подразумевается? Если мы ещё не готовы отдать результат, то вместо его ожидания мы отдаём какую-то ошибку, например, с просьбой повторить запрос позднее. Круто, конечно, но что нам с этой ошибкой делать? Так у нас появляется асинхронная обработка, чтобы позднее отреагировать на ответ: всё готово!
Получается, нужно писать код асинхронный и неблокирующий, и всё у нас станет хорошо? Нет, не станет. Но облегчить жизнь может. Для этого добрые и умные люди напридумывали всяких спецификаций (в т.ч. реактивных) и напилили библиотек, которые эти спецификации уважают.
Так вот, Reactor. Если очень коротко
По факту, Reactor (по-крайней мере его core-часть) — это имплементация спецификации Reactive Streams и части ReactiveX-операторов. Но об этом чуть позже.
Если вы знакомы или наслышаны о RxJava, то Reactor разделяет подход и философию RxJavа, но имеет ряд семантических отличий (которые растут из-за backward compatibility со стороны RxJava и особенностей Android-разработки).
Что же такое Reactive Streams в Java?
Если грубо, то это 4 интерфейса, которые представлены в библиотеке reactive-streams-jvm:
Их точные копии присутствуют в классе Flow из девятки.
Если ещё более грубо, то к ним всем выдвигаются примерно следующие требования:
Давайте взглянем на код класса Flow из JDK 9 (Javadoc-комментарии убраны для лаконичности):
Пока что это вся поддержка реактивности на уровне JDK. Где-то в модуле инкубатора зреет HTTP/2-клиент, в котором Flow активно используется. Других использований внутри JDK 9 я не обнаружил.
Интеграции
Reactor интегрирован в наши любимые приблуды Java 8, среди которых CompletableFuture, Stream, Duration. Поддерживает IPC-модули. У него есть адаптеры для Akka и RxJava, модули test (очевидно, для написания тестов) и extra (utility классы).
Для любителей Redis у клиентов lettuce/redisson есть реактивный API с поддержкой Reactor.
Для любителей MongoDB есть официальный реактивный драйвер, который имплементирует Reactive Streams, в связи с чем его легко подхватывает Reactor.
Отлично, а как всё это запустить?
Всё это можно запустить на JDK8 и выше. Однако, если вы используете Android и ваш (minSdk Если у вас Maven
BOM служит для обеспечения лучшей совместимости различных кусков Reactor. В Gradle нет нативной поддержки BOM, поэтому нужен плагин.
Примерчики
Так вот, нам нужно написать асинхронный и неблокирующий код. Другими словами, дать возможность текущему потоку выполнения не блокироваться и ждать, а переключиться на что-нибудь полезное, вернувшись к текущему процессу, когда асинхронная обработка будет завершена.
На солнечном острове под названием Java для это есть два основных способа:
Callbacks. В случае с колбэками у метода нет возвращаемого значения (void), но он принимает дополнительный параметр (лямбду, анонимный класс и т.п.), который вызывается после определённого события. В качестве примера можно привести EventListener из библиотеки Swing.
Это хорошо известные инструменты, но в какой-то момент их становится недостаточно.
Проблемы с колбэками
Колбэки плохо поддаются композиции и быстро превращаются в мешанину под названием «callback hell».
Разберём на примере
Нужно показать пользователю 5 топовых мемов, а если их нет, то сходить в сервис предложений и взять 5 мемов оттуда.
Итого задействовано 3 сервиса: первый отдаёт ID любимых мемов пользователя, второй фетчит сами мемы, а третий отдаёт предложения, если любимых мемов не имеется.
Выглядит как-то не круто.
Теперь посмотрим, как мы бы сделали это с Reactor
А что если мы вдруг захотели отваливаться по тайм-ауту в 800 мс и загружать кэшированные данные?
В Reactor мы просто добавляем в цепочку вызовов оператор timeout. Timeout выбрасывает исключение. Оператором onErrorResume мы указываем альтернативный (fallback) источник, из которого нужно взять данные в случае ошибки.
Колбэки в 20!8, у нас же есть CompletableFuture
У нас есть список ID, по которым мы хотим запросить имя и статистику, а затем скомбинировать в виде пар «ключ-значение», и всё это асинхронно.
Как мы можем сделать это с Reactor?
В итоге нам предоставляется высокоуровневый API, композируемый и читабельный (на самом деле изначально мы использовали Reactor именно для этого, т.к. нужен был способ писать асинхронный код в едином стиле), и прочие вкусности: ленивое выполнение, управление BackPressure, различные планировщики (Schedulers) и интеграции.
Окей, какие ещё Flux и Mono?
Flux и Mono — это две основные структуры данных Reactor.
Flux — это имплементация интерфейса Publisher, представляет из себя последовательность из 0..N элементов, которая может (но не обязательно) завершаться (в т.ч. и с ошибкой).
У последовательности Flux есть 3 допустимых значения: объект последовательности, сигнал завершения или сигнал ошибки (вызовы методов onNext, onComplete и onError соответственно).
Каждое из 3 значений опционально. К примеру, Flux может представлять из себя бесконечную пустую последовательность (ни один метод не вызывается). Или конечную пустую последовательность (вызывается только onComplete). Или бесконечную последовательность значений (вызывается только onNext). И т.д.
Выведет следующий текст:
Метод doOnEach(Consumer ) применяет сайд-эффект к каждому элементу в последовательности, что удобно для логирования.
Обратите внимание на blockLast(): т.к. последовательность бесконечная, поток, в котором происходит вызов, будет бесконечно ждать окончания.
Если вы знакомы с RxJava, то Flux очень похож на Observable
Mono — это имплементация интерфейса Publisher, представляет из себя какой-то асинхронный элемент или его отсутствие Mono.empty().
В отличии от Flux, Mono может вернуть не более 1 элемента. Вызовы onComplete() и onError(), как и в случае с Flux, опциональны.
Mono также может использоваться как какая-то асинхронная задача в стиле «выполнил и забыл», без возвращаемого результата (похоже на Runnable). Для этого можно объявить его как Mono и использовать оператор empty.
Если вы знакомы с RxJava, воспринимайте Mono как коктейль из Single + Maybe
К чему это разделение?
Разделение на Flux и Mono помогает улучшить семантику реактивного API, делая его достаточно выразительным, но не избыточным.
В идеале, просто посмотрев на возвращаемое значение, мы можем понять, что делает метод: какой-то вызов (Mono ), запрос-ответ (Mono ) или возвращает нам поток данных (Flux ).
Также у них есть уникальные операторы. Некоторые имеют смысл только при N элементах в последовательности (Flux) или, наоборот, актуальны только для одного значения. Например, у Mono есть or(Mono ), а у Flux есть операторы limit/take.
Ещё примерчики
Самый простой способ создать Flux/Mono — воспользоваться одним из массы фабричных методов, которые представлены в этих классах.
Русские Блоги
Анализ исходного кода Netty 2-Reactor
Еще статьи обратите внимание на: многопоточность / сбор / распределенный / Netty / NIO / RPC
Один: Netty, NIO, многопоточность?
Два: Реактор
1. Происхождение Reactor
2. Реактор и НИО
3. Другие концепции, связанные с реактором.
О блокировании и неблокировании, асинхронном и неасинхронном, а также о базовом механизме UNIX вы можете прочитать в этой статье.IO-Synchronous, Asynchronous, Blocking, Non-blocking (Средство устранения), И Тао Хуэй (автор книги «Углубленное понимание nginx»)«Программирование высокопроизводительных сетей»Серии.
Третий: начиная с Reactor, чтобы понять Netty
1. Реактор под многопоточность
Поговорив о связке Reactor, возвращаемся к Нетти. В «Масштабируемом вводе-выводе на Java» говорилось о многопоточном режиме Reactor. В этом режиме есть только один mainReactor, который отвечает за запросы клиентского соединения и устанавливает соединения. Он использует NIO Selector; может быть один или несколько субреакторов, и каждый субреактор будет выполняться в независимом потоке и поддерживать независимый NIO Selector.
Это преимущество очевидно, потому что subReactor также будет выполнять некоторые трудоемкие операции ввода-вывода, такие как чтение и запись сообщений, с использованием нескольких потоков для выполнения, что больше способствует вычислительной мощности ЦП и сокращает время ожидания ввода-вывода.
2. Reactor и NIO в Нетти
EventLoop Reactor в Netty 3.7 находится в AbstractNioSelector.run() В, это достигнуто Runnable интерфейс. Этот класс является ядром Netty NIO. Его логика очень сложна и также включает некоторую обработку ошибок JDK (например, rebuildSelector ), вам не нужно вдаваться в подробности при первом чтении. Я оптимизировал большую часть кода, сохранив основную часть кода следующим образом:
Разве это не классическое использование селектора, упомянутого во второй части?
После Netty 4.0 автор почувствовал NioSelector Это называется, и различают NioBoss с участием NioWorker Метод немного более громоздкий, поэтому я просто объединяю их в NioEventLoop С тех пор эти две роли не будут различаться. Думаю, новая версия будет изящнее.
3. Многопоточность в Netty
Как видите, это не подходит для бизнеса, который обрабатывает длинное событие, которое должно выполняться напрямую в ChannelHandler. Итак, как с этим бороться? Мы представим его в разделе «Обработчик».
1000 и 1 способ сесть на мель в Spring WebFlux при написании высоконагруженного сервиса
Источник изображения: Shutterstock.com/photowind
Добрый день, меня зовут Тараканов Анатолий, я senior java разработчик SberDevices. 2.5 года программирую на Java, до этого 6 лет писал на C# и 1 год на Scala. Хочу поделиться опытом создания сервиса-оркестратора Voice Processing Service. Он является точкой входа для пользователей семейства виртуальных ассистентов Салют. Через него также проходит часть трафика приложений SmartMarket, где любой разработчик может написать навык для наших виртуальных ассистентов Салют.
Одним словом, на сервис приходится немалая нагрузка. Давайте посмотрим, какие проблемы при его создании возникли и как мы их решали, а также сколько времени ушло на поиск причин. И всё это в контексте реактивного фреймворка Spring WebFlux.
Немного о сервисе
Начнем с обзора архитектуры нашего сервиса-оркестратора. Он управляет процессом обработки входящего трафика от пользователей, формированием и передачей ответа. Среди смежных систем, к которым он обращается, есть такие сервисы:
Сервис хостится в нескольких ЦОДах, в том числе в SberCloud, горизонтально масштабируется в OpenShift. Для передачи, поиска и хранения логов используется ELK-стек, для трассировки –Jaeger, для сбора метрик – Prometheus, а для их отображения – Grafana.
Каждый инстанс в секунду держит нагрузку примерно в 7000 пакетов (средний размер пакета 3000 байт). Это эквивалентно активности 400 пользователей, которые без перерыва обращаются к виртуальному ассистенту. С учётом взаимодействия нашего сервиса со смежными число пакетов увеличивается втрое – до 21 000.
Каждая виртуалка имеет 3 ядра и 8 Gb оперативной памяти.
Сервис создавался в реалиях стартапа, а значит неопределенности. Были такие вводные:
А ещё мы использовали Junit 5 и Mokito для тестирования и несколько библиотек – Nimbus JOSE + JWT, Google Guava, Lombok, vavr.io – для удобства в виде синтаксического сахара и автогенерации кода.
Оценив требования, мы решили втащить в наш технологический стек Spring WebFlux с Reactor и Netty под капотом.
Итак, поговорим о нюансах использования этого реактивного фреймворка.
Кастомизация Netty-сервера
Так вот, всё это можно сделать в компоненте, имплементирующем WebServerFactoryCustomizer. В его методе доступны как HttpServer, так и каждое клиентское подключение.
Reactor Netty: а жив ли клиент?
Пропущу этап создания сервиса и сразу перейду к его сдаче на стенд нагрузочного тестирования. В тот же день мы получили фидбэк о том, что с течением времени число незакрытых соединений растёт. Стали искать причину – анализировали tcp-дампы с помощью WireShark. Выяснилось, что клиент не присылал сигнал о закрытии соединения, а также, что в реакторе по умолчанию не инициализируются обработчики таймаутов на входящие/исходящие пакеты. Для исправления ситуации в вышеуказанный компонент был добавлен такой обработчик.
На просмотр логов, анализ ситуации со смежниками, сбор дампов и их анализ, исправление и тестирование у нас ушло 2 дня. Немало.
Reactor Netty: Спасибо за помощь
Фреймворк таким образом нам «помогает сэкономить» на хэндшейках, построении маршрута в сети, что, конечно, приятно, когда есть корреляция хотя бы по ttl между ним и настройками смежных сервисов и операционных систем в месте их хостинга.
Но всего этого не было, поэтому на время при взаимодействии с такими клиентами мы стали применять ConnectionProvider с отключенным пулом.
Поиск причины такого поведения съел 3 дня, это больно.
Spring WebFlux: большой размер fluent цепочек стоит дорого
Мы развивали наш сервис дальше, накручивали логику, сценарии становились всё сложнее – и вот, в один прекрасный день с нагрузочного тестирования пришла печальная весть: мы перестали держать ожидаемую нагрузку. Что обычно делают в таком случае – берут в руку JFR и профилируют. Так мы и поступили. Результат не заставил себя долго ждать. Мы обнаружили, что при написании fluent-цепочек вызовов методов Flux-ов о декомпозиции логики в функциональном стиле стоит забыть.
В приведенном фрагменте кода замеряется работа флакса из 100_000 элементов с 1 реактивным методом, во втором – с 6 методами. Тест проверяет, что первый метод работает вдвое быстрее второго, причем число итераций проверок не играет роли.
Кстати, на гитхабе много вопросов по этой теме. Если отвечать коротко, то стоит заглядывать вглубь каждого метода. Там может быть много интересного: от ограничений по размеру внутренней очереди, volatile чтений/записей, до порождения потенциально бесконечного числа очередей, которые сами собой не зафиналятся. Подробнее здесь.
Вот, собственно, простой тест с замиранием процессинга.
Как видно, последняя запись в логе – 255 элемент. Если заглянуть в документацию, то причина такого поведения станет очевидна, но кто её читает?) Особенно когда методы имеют такие говорящие и всем привычные названия.
С фреймворком Spring WebFlux нужно быть очень аккуратным. В том числе нужно следить за тем, какой паблишер возвращается методом. На какие-то можно подписываться неограниченное число раз (FluxReplay), но они имеют нюанс с размером буфера, другие возвращают один и тот же элемент каждому новому подписчику (MonoDefer).
Несколько эффективных и дешёвых оптимизаций
В качестве итогов
Reactor Netty – удобен, гибок и быстр. Что касается текущей реализации Spring WebFlux, то она позволяет добиться высокой производительности, даже если сервис процессит большой объем событий в единицу времени в рамках каждого подключения и содержит витиеватую логику с нелинейной обработкой и ветвлениями.
Но придётся следовать трём правилам:
— размеры очередей и буферов «под капотом» требуют тонкой настройки. Также нужно помнить, что использование фреймворка на каждом шагу порождает новый источник данных, который нужно закрывать;
— цепочки вызовов методов фреймворка должны быть короткими, а декомпозицией логики обработки лучше заниматься в своих методах, либо использовать Operators.lift и Sinks для создания своего реактивного оператора.
И повторюсь, читайте документацию и профилируйте. Этот кактус нужно научиться готовить прежде, чем есть, иначе в ходе трапезы он станет только больше.
Источник изображения: Shutterstock.com/SEE D JAN
Отдельного рассказа заслуживают нюансы применения сборщиков мусора (GC), инструментов JFR/JMC, особенности работы с буферами и очередями в Spring WebFlux, а также тонкости настройки Netty-сервера.
Русские Блоги
Интерпретация исходного кода Netty (4) режим Netty и Reactor
Оригинальный текст поступает из одновременной сети программирования, моего любимого веб-сайта технологий, пожалуйста, смотрите эту статью к параллельной сети программирования.
Интерпретация исходного кода Netty (4) режим Netty и Reactor
Один: Netty, Nio, Multi-Thread?
Я был обновлен снова в течение длительного времени! Было уже поздно, пока не поздно, потому что этого недостаточно, и начать сложнее. Новый год@ hw.Публиковать одинАнализ архитектуры Netty5.0 и интерпретация исходного кодаЭто также много урожая после прочтения. В предыдущей статье мы проанализировали структуру Netty. На этот раз мы пришли к анализу многопоточной части неправильной сложной части многопоточных и NIO-приложений.
Эта статья все еще предназначена для Netty 3.7, но из-за исходного кода Netty 5 он будет введен.
Два: реактор, реактор или атомная электростанция?
1, происхождение реактора
Итак, какой режим реактора? Это собирается начать с метода разработки событий, управляемых событиями. Мы знаем, что для сервера приложений основным законом является то, что скорость обработки процессора является гораздо быстрее, чем скорость IO. Если ЦП заблокирован, он, очевидно, не основан на операции IO (например, чтение данных из розетки ). Лучший способ разделен на мульти-процесс или нити, но это принесет несколько технологических переключающих накладных расходов. Представьте себе процесс для процесса, прочитанного 500 мс, а процесс переключается на него 3 раза, но ЦП не может ничего делать, просто переключаться, Это не стоит этого?
Хорошо, давайте посмотрим режим реактора сейчас. Существует проблема в примере предыдущего драйвера событий: как мы узнаем, что IO готов этого события, который действует как этот посредник? Ответ на режим реактора: сделать это по отдельному процессу (поток), который постоянно ждут и цикла, он принимает все регистрацию обработчика, и отвечает за первую операционную систему Query IO готов, а затем вызовите указанный обработчик Для обработки после готовности название этой роли называется реактор.
2, реактор и нио
Nio в Java может быть хорошо сочетается с режимом реактора. Об режиме реактора в Nio, я не думаю, что есть что-то больше, чем Дуг Лей! Не знаю Дага Ли? Посмотрите на автор пакета коллекции JDK и одновременно)《Scalable IO in Java》Интерпретация более лаконичная и всеобъемлющая. Ядро реактора в Nio Selector Я написал простой пример реактора, здесь я разместил ядро цикла реактора (эта структура петли называется EventLoop ) Оставшийся кодЗдесь。
3, другие концепции, связанные с реактором
Я упомянул режим Proactor раньше, что это? Просто в режиме реактора операционная система отвечает только за уведомление IO, а конкретная операция IO (например, чтение и запись) все еще будет заблокировать в бизнес-процессе, и режим Proactor еще больше, а операционная система будет ли Операция хорошая (например, чтение, вы будете читать данные непосредственно в буфере памяти), а обработчик отвечает только за обработку собственной логики и действительно выполнять IO и программную обработку асинхронного исполнения. Поэтому мы, как правило, говорим, что реактор синхронный IO, Proactor асинхронный IO.
Три: понять Netty от реактора
1, многоподобный реактор
Рассказывать кучу реактора, мы вернулись к Netty. Скажите многопоточный режим реактора в «Масштабируемом IO в Java». В этом режиме только один замечают только для реагирования на запрос на связь клиента и устанавливает соединение. Он использует селектор NIO; SubreaCtor может иметь один или несколько, каждый субреатор выполнен в отдельной резьбе и поддерживает отдельный поток Nio Selector.
Такие преимущества очевидны, поскольку SubreaCtor также выполняет некоторые трудоносные операции IO, такие как чтение и запись сообщений, используют несколько потоков для выполнения, более способствуют воспроизведению возможностей расчета CPU, уменьшая время ожидания IO.
2, реактор и Nio в Netty
Хорошо, я узнал о режиме реактора под многопоточным, давайте посмотрим на Netty (следующие разделы, в основном целевые NIO, OIO), простые, не очень простые введены). В Netty есть «босс», и роль соответствующего субреактора называется «работник». Босс несет ответственность за распределение запросов, работника несет ответственность за выполнение, кажется очень приятным! В качестве примера эти две соответствующие реализации TCP в качестве примера эти две соответствующие реализации NioServerBoss с участием NioWorker (Работник сервера и клиента не имеют значения, потому что после установления соединения обе стороны передаются.).
EventLoop реактора в Netty 3.7 AbstractNioSelector.run() Это поняла Runnable интерфейс. Этот класс является ядром раздела Netty Nio. Его логика очень сложная, включая некоторую обработку ошибок JDK (например, rebuildSelector ), Не нужно так углубить деталь, когда вы начнете читать. Я оптимизирую большую часть кода, держите назад следующим образом:
Где процесс является логикой основного события обработки, например AbstractNioWorker В середине логика обработки выглядит следующим образом:
Разве этот селектор классический использование упоминается во второй части?
После 4,0 автор чувствует NioSelector Это называется и отличает NioBoss с участием NioWorker Практика слегка громоздка, просто объединила эти NioEventLoop С тех пор эти два персонажа не будут выделены. Я чувствую, что новая версия будет более элегантной.
3, мульти-нить в Netty
Давайте посмотрим на многопоточную деталь Netty’s. Как только соответствующий босс или работник начинается, он будет назначен одному потоку. Соответствующая концепция BossPool с участием WorkerPool Отказ Для каждого NioServerSocketChannel У босса реактор имеет нить, а количество работника определяется размером пула рабочего нита, но по умолчанию не будет превышать CPU Core * 2, конечно, этот параметр может пройти NioServerSocketChannelFactory Параметры конструктора установлены.
Наконец, мы заботимся о проблеме, мы раньше ChannlePipeline Какой поток выполнен, в каком потоке находится в Channehandal? Ответ выполняется в рабочей нити и заблокирует EventLoop Workr. Например, NioWorker В середине, после прочтения сообщения, он будет вызвать MessageReceived Событие, это сделает обработчик в трубопроводе для выполнения.
Видно, что для длительного обслуживания не подходит, чтобы поставить его прямо в Chanelhandler. Так как вы справляетесь с этим? Мы введем в раздел обработчика.