[Автор: Чен Цайхуа] В этой статье, основанной на Netty 4.1, представлены соответствующие теоретические модели, сценарии использования, основные компоненты и общая архитектура.знать это и знать это, я надеюсь предоставить читателям ссылку для обучения и практики.
1 Введение в Нетти
Netty — это среда асинхронных сетевых приложений, управляемая событиями, для быстрой разработки поддерживаемых высокопроизводительных протокольных серверов и клиентов.
Проблемы с собственными программами JDK NIO
JDK также изначально имеет набор API-интерфейсов сетевых приложений, но есть ряд проблем, в основном следующих:
- Библиотека классов и API NIO сложны и хлопотны в использовании.Вы должны хорошо разбираться в Selector, ServerSocketChannel, SocketChannel, ByteBuffer и т. д.
- Вам необходимо иметь другие дополнительные навыки, чтобы проложить путь, например, быть знакомым с многопоточным программированием на Java, поскольку программирование NIO включает режим Reactor, вы должны быть хорошо знакомы с многопоточным и сетевым программированием, чтобы писать высококачественные программы NIO.
- Возможности надежности дополняются, а рабочая нагрузка и сложность разработки очень велики. Например, клиент сталкивается с отключением и повторным подключением, отключением сетевой флэш-памяти, чтением и записью половины пакета, сбоем кэша, перегрузкой сети и ненормальной обработкой потока кода и т. д. Программирование NIO характеризуется относительно простой разработкой функций, но возможность надежности компенсирует для нагрузки.и очень сложно
- Ошибки JDK NIO, такие как печально известная ошибка epoll, из-за которой Selector очищает опросы, что в конечном итоге приводит к тому, что ЦП достигает 100%. Официальный сайт утверждает, что проблема была исправлена в обновлении 18 версии JDK1.6, но проблема все еще существует до версии JDK1.7, но вероятность появления бага немного снижена, и принципиально она не решена. .
Особенности Нетти
Netty инкапсулирует NIO API, который поставляется с JDK для решения вышеуказанных проблем.Основные функции:
- элегантный дизайн Унифицированный API для различных типов транспорта — блокирующие и неблокирующие сокеты На основе гибкой и расширяемой модели событий для четкого разделения задач Модель многопоточности с широкими возможностями настройки — один поток, один или несколько пулов потоков. Настоящая поддержка сокетов дейтаграмм без установления соединения (начиная с версии 3.1)
- легко использовать Хорошо документированный Javadoc, руководство пользователя и примеры Никаких других зависимостей, достаточно JDK 5 (Netty 3.x) или 6 (Netty 4.x).
- высокая производительность Более высокая пропускная способность и более низкая задержка Сокращение потребления ресурсов Минимизируйте ненужные копии памяти
- Безопасность Полная поддержка SSL/TLS и StartTLS
- Активное и постоянно обновляемое сообщество Сообщество активное, цикл итерации версии короткий, найденные ошибки можно вовремя исправить, одновременно будет добавлено больше новых функций.
Netty обычное использование
Общие сценарии использования Netty следующие:
- Интернет-индустрия В распределенной системе требуются удаленные вызовы служб между узлами, и необходима высокопроизводительная структура RPC.Netty, как асинхронная высокотехнологичная коммуникационная среда, часто используется этими средами RPC в качестве основного компонента связи. Типичными приложениями являются: Платформа распределенных служб Ali Платформа Dubbo RPC использует протокол Dubbo для связи между узлами, а протокол Dubbo по умолчанию использует Netty в качестве базового компонента связи для реализации внутренней связи между узлами процессов.
- игровая индустрия Будь то мобильный игровой сервер или крупномасштабная онлайн-игра, язык Java используется все шире. В качестве высокопроизводительного базового коммуникационного компонента Netty сама предоставляет стеки протоколов TCP/UDP и HTTP. Очень удобно настраивать и разрабатывать частные стеки протоколов, серверы входа в учетные записи и картографические серверы, которые могут легко выполнять высокопроизводительную связь через Netty.
- Поле больших данных Платформа RPC Avro, классический высокопроизводительный компонент Hadoop для связи и сериализации, по умолчанию использует Netty для трансграничной связи, а ее служба Netty реализована на основе вторичной инкапсуляции инфраструктуры Netty.
Заинтересованные читатели могут узнать, какие проекты с открытым исходным кодом в настоящее время используют Netty:Related projects
2 Высокопроизводительный дизайн Netty
Как асинхронная сеть, управляемая событиями, высокая производительность Netty в основном обусловлена ее моделью ввода-вывода и моделью обработки потоков.Первая решает, как отправлять и получать данные, а вторая решает, как обрабатывать данные.
Модель ввода/вывода
Какой канал используется для отправки данных другой стороне, BIO, NIO или AIO, модель ввода-вывода во многом определяет производительность фреймворка.
блокировка ввода/вывода
Традиционный блокирующий ввод/вывод (BIO) можно представить следующей схемой:
Функции
- Для каждого запроса требуется независимый поток для выполнения полных операций чтения данных, бизнес-обработки и записи данных.
проблема
- Когда количество параллелизма велико, необходимо создать большое количество потоков для обработки соединения, что требует большого количества системных ресурсов.
- После установления соединения, если у текущего потока нет данных для чтения в данный момент, поток будет заблокирован в операции чтения, что приведет к пустой трате ресурсов потока.
Модель мультиплексирования ввода/вывода
В модели мультиплексирования ввода-вывода будет использоваться select, и эта функция также будет блокировать процесс, но в отличие от блокировки ввода-вывода эти две функции могут одновременно блокировать несколько операций ввода-вывода, а также могут блокировать несколько операций ввода-вывода. O. Определяйте функции ввода-вывода нескольких операций чтения и нескольких операций записи и вызывайте функцию операции ввода-вывода только тогда, когда данные доступны для чтения или записи.
Ключ к реализации неблокирующего ввода-вывода Netty основан на модели мультиплексирования ввода-вывода, которая здесь представлена объектом Selector:
Поток ввода-вывода Netty NioEventLoop может одновременно обрабатывать сотни или тысячи клиентских подключений благодаря агрегации мультиплексора Selector. Когда поток читает и записывает данные из клиентского канала Socket, если данные недоступны, поток может выполнять другие задачи. Потоки обычно тратят время неблокирующего ввода-вывода на выполнение операций ввода-вывода на других каналах, поэтому один поток может управлять несколькими входными и выходными каналами.
Поскольку операции чтения и записи неблокируются, это может полностью повысить эффективность работы потоков ввода-вывода и избежать приостановки потока, вызванной частой блокировкой ввода-вывода.Один поток ввода-вывода может одновременно обрабатывать N клиентских подключений и операции чтения и записи. который принципиально решает традиционную синхронную блокировку модели потоков ввода-вывода и значительно повышает производительность, эластичную масштабируемость и надежность архитектуры.
на основе буфера
Традиционный ввод-вывод ориентирован на потоки байтов или потоки символов и считывает один или несколько байтов из потока последовательно в потоковом режиме, поэтому положение указателя чтения нельзя изменить произвольно.
В NIO от традиционного потока ввода-вывода отказываются, но вводятся концепции канала и буфера.В NIO данные могут быть прочитаны только из канала в буфер или данные из буфера данных могут быть записаны в канал.
В отличие от традиционных последовательных операций ввода-вывода, операции на основе буфера могут считывать данные из любого места в NIO по желанию.
резьбовая модель
Как читаются дейтаграммы? Поток, в котором выполняется кодек после чтения, способ отправки закодированных и декодированных сообщений и различные модели потоков оказывают большое влияние на производительность.
модель, управляемая событиями
Обычно мы разрабатываем программу с моделью обработки событий двумя способами.
- метод опроса Поток постоянно опрашивает и обращается к соответствующему источнику событий, чтобы узнать, есть ли событие, и когда событие происходит, вызывается логика обработки события.
- управляемый событиями Когда происходит событие, основной поток помещает событие в очередь событий, а другой поток непрерывно потребляет события в списке событий и вызывает логику обработки, соответствующую событию, для обработки события. Метод, управляемый событиями, также известен как метод уведомления о сообщениях, который на самом деле является шаблоном проектирования вШаблон наблюдателяидеи.
Возьмите логическую обработку GUI в качестве примера, чтобы проиллюстрировать разницу между двумя логиками:
- метод опроса Поток постоянно опрашивает, происходит ли событие нажатия кнопки, и если да, то вызывает логику обработки
- управляемый событиями Когда происходит событие щелчка, оно помещается в очередь событий, и связанная логика обработки событий вызывается в соответствии с типом события для событий в списке событий, используемых другими потоками.
Вот ссылка на книгу О'Рейли.Диаграмма объяснения управляемой событиями модели
В основном он включает 4 основных компонента:- Очередь события (очередь событий): входное устройство, получающее событие, данные хранения событий будут обработаны
- Распределитель (посредник событий): распределяет разные события по разным блокам бизнес-логики.
- Канал событий: канал связи между диспетчером и процессором.
- Обработчик событий: реализует бизнес-логику и генерирует события после обработки, чтобы инициировать следующую операцию.
Видно, что по сравнению с традиционным режимом опроса событийный режим имеет следующие преимущества:
- Хорошая масштабируемость, распределенная асинхронная архитектура, высокая степень развязки между процессорами событий, что позволяет легко расширять логику обработки событий.
- Высокая производительность на основе очереди для временного хранения событий, что может облегчить параллельную и асинхронную обработку событий.
Модель резьбы Reactor
Reactor означает реактор Модель Reactor относится к сервисному запросу, который одновременно передается сервисному процессору через один или несколько входов.обработка событий. Серверная программа обрабатывает входящие множественные запросы и отправляет их синхронно потоку обработки, соответствующему запросу.Режим Reactor также называется режимом Dispatcher, то есть событий мультиплексирования ввода-вывода и унифицированного мониторинга больше, и они распределяются после получение событий (диспетчеризация определенного процесса) — одна из необходимых технологий для написания высокопроизводительных сетевых серверов.
В модели Reactor есть 2 ключевых компонента:
-
Реактор Reactor работает в отдельном потоке и отвечает за прослушивание и отправку событий, отправку соответствующим обработчикам для реагирования на события ввода-вывода. Это как телефонный оператор для компании, он принимает звонки от клиентов и перенаправляет линию на соответствующий контакт
-
Обработчики Обработчик выполняет фактическое событие, которое должно быть выполнено событием ввода-вывода, аналогично фактическому сотруднику в компании, с которым хочет поговорить клиент. Reactor реагирует на события ввода-вывода, отправляя соответствующие обработчики, которые выполняют неблокирующие операции.
Существует 3 варианта модели Reactor в зависимости от количества Reactors и количества потоков Handler.
- Одиночный реактор Однопоточный
- Многопоточность с одним реактором
- Многопоточность Master-Slave Reactor
Таким образом, можно понять, что Reactor — это поток, выполняющий цикл while (true) { selector.select(); ...}, который будет непрерывно генерировать новые события, поэтому очень уместно назвать его реактором.
Из-за пространственного соотношения особенности, преимущества и недостатки Reactor здесь не будут подробно сравниваться, а заинтересованные читатели могут обратиться к моей предыдущей статье:«Понимание высокопроизводительных сетевых моделей»
Модель потоков Netty
Нетти МэйнМногопоточная модель на базе реакторов master-slave.(Как показано на рисунке ниже) были сделаны некоторые модификации, в которых многопоточная модель master-slave Reactor имеет несколько Reactor: MainReactor и SubReactor:
- MainReactor отвечает за запрос подключения клиента и перенаправляет запрос SubReactor.
- SubReactor отвечает за запросы чтения и записи IO соответствующего канала.
- Задачи, не являющиеся запросами ввода-вывода (специфическая логическая обработка), будут напрямую записываться в очередь и ожидать, пока рабочие потоки обработают их.
Вот реактор, представленный Дугом Ли Великим Богом:Scalable IO in JavaВнутри рисунка о многопоточной модели master-slave Reactor
Конкретно: Хотя модель многопоточности Netty основана на многопоточности master-slave Reactor и заимствует структуру MainReactor и SubReactor, в реальной реализации потоки SubReactor и Worker находятся в одном пуле потоков:
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap server = new ServerBootstrap();
server.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
BossGroup и workerGroup в приведенном выше коде — это два объекта, переданные в методе построения Bootstrap, оба из которых являются пулами потоков.
- Пул потоков bossGroup получает только один из потоков в качестве MainReactor после привязки порта и обрабатывает событие accept порта.Каждый порт соответствует потоку бобышки
- Пул потоков workerGroup будет полностью использоваться каждым SubReactor и рабочими потоками.
Асинхронная обработка
Концепция асинхронности противоположна синхронизации. При вызове асинхронной процедуры вызывающая сторона не может получить результат немедленно. Компонент, который фактически обрабатывает вызов, уведомляет вызывающего абонента о состоянии, уведомлении и обратном вызове, когда это делается.
Операции ввода-вывода в Netty являются асинхронными, включая привязку, запись, подключение и другие операции, которые просто возвращают ChannelFuture, вызывающая сторона не может получить результат немедленно, через механизм Future-Listener, пользователь может легко получить его активно или через механизм уведомления Получить результат операции ввода-вывода.
Когда будущий объект только что создан, он находится в незавершенном состоянии.Вызывающий может получить статус выполнения операции через возвращенный ChannelFuture и зарегистрировать функцию слушателя для выполнения завершенной операции.Обычные операции следующие:
- Используйте метод isDone, чтобы определить, завершена ли текущая операция.
- Используйте метод isSuccess, чтобы определить, успешно ли завершена текущая операция.
- Получить причину сбоя завершенной текущей операции через метод getCause
- Используйте метод isCancelled, чтобы определить, была ли отменена завершенная текущая операция.
- Зарегистрируйте слушателя с помощью метода addListener.По завершении операции (метод isDone возвращает завершение) указанный слушатель будет уведомлен, если будущий объект будет завершен, указанный слушатель будет уведомлен.
Например, в следующем коде порт привязки является асинхронной операцией.При обработке операции привязки будет вызвана соответствующая логика обработки прослушивателя.
serverBootstrap.bind(port).addListener(future -> {
if (future.isSuccess()) {
System.out.println(new Date() + ": 端口[" + port + "]绑定成功!");
} else {
System.err.println("端口[" + port + "]绑定失败!");
}
});
По сравнению с традиционным блокирующим вводом-выводом поток будет заблокирован после выполнения операции ввода-вывода до завершения операции; преимущество асинхронной обработки заключается в том, что поток не будет блокироваться, и поток может выполнять другие программы во время выполнения операции ввода-вывода. Операция /O Параллельная ситуация будет более стабильной и более высокой пропускной способности.
3 Дизайн архитектуры Netty
После введения некоторых теорий, связанных с Netty, ниже представлен дизайн архитектуры Netty с точки зрения функциональных характеристик, компонентов модуля и рабочего процесса.
Функции
- Служба передачи Поддержка БИО и НИО
- интеграция контейнеров Поддержка контейнеров OSGI, JBossMC, Spring, Guice.
- Поддержка протокола Поддерживается ряд распространенных протоколов, таких как HTTP, Protobuf, двоичный, текстовый и WebSocket. Также поддерживает реализацию пользовательских протоколов за счет реализации логики кодирования и декодирования.
- Основное ядро Расширяемая модель событий, общий API связи, буферный объект ByteBuf с нулевым копированием
Компоненты модуля
Bootstrap, серверBootstrap
Bootstrap означает загрузку.Приложение Netty обычно начинается с Bootstrap.Основная функция заключается в настройке всей программы Netty и подключении различных компонентов.Класс Bootstrap в Netty – это класс начальной загрузки клиентской программы, а ServerBootstrap – класс начальной загрузки сервера. .
Будущее, КаналБудущее
Как упоминалось ранее, все операции ввода-вывода в Netty являются асинхронными, и вы не можете сразу узнать, правильно ли обработано сообщение, но вы можете дождаться его завершения через некоторое время или зарегистрировать прослушиватель напрямую.Конкретная реализация осуществляется через Future и ChannelFutures, Они могут зарегистрировать прослушиватель, который автоматически запускает зарегистрированное событие прослушивателя при успешном или неудачном выполнении операции.
Channel
Компонент сетевой связи Netty, который можно использовать для выполнения сетевых операций ввода-вывода. Канал предоставляет пользователям:
- Статус канала для текущего сетевого подключения (например, открыт? Подключен?)
- Параметры конфигурации для сетевых подключений (например, размер приемного буфера)
- Обеспечивает асинхронные сетевые операции ввода-вывода (такие как установление соединений, чтение и запись, привязка портов), асинхронный вызов означает, что любой вызов ввода-вывода будет немедленно возвращен, и нет гарантии, что запрошенная операция ввода-вывода была выполнена. в конце разговора Готово. Вызов немедленно возвращает экземпляр ChannelFuture.Зарегистрировав прослушиватель в ChannelFuture, вызывающий может быть уведомлен обратным вызовом, когда операция ввода-вывода успешна, неудачна или отменена.
- Поддержка связывания операций ввода-вывода с соответствующими обработчиками
Соединения по разным протоколам и разным типам блокировки имеют разные типы каналов, соответствующие им Ниже приведены некоторые часто используемые типы каналов.
- NioSocketChannel, асинхронное клиентское подключение через сокет TCP
- NioServerSocketChannel, асинхронное соединение TCP Socket на стороне сервера
- NioDatagramChannel, асинхронное соединение UDP
- NioSctpChannel, асинхронное клиентское соединение Sctp
- NioSctpServerChannel, асинхронное соединение Sctp на стороне сервера Эти каналы охватывают сетевой ввод-вывод UDP и TCP, а также файловый ввод-вывод.
Selector
Netty реализует мультиплексирование ввода-вывода на основе объекта Selector. Через Selector поток может отслеживать события канала нескольких подключений. Когда канал зарегистрирован в Selector, внутренний механизм Selector может автоматически и непрерывно запрашивать (выбирать) эти Есть ли у зарегистрированного канала готовые события ввода-вывода (такие как чтение, запись, завершение сетевого подключения и т. д.), чтобы программа могла просто использовать один поток для эффективного управления несколькими каналами.
NioEventLoop
Поток и очередь задач поддерживается в NioEventLoop, который поддерживает асинхронную отправку и выполнение задач.Когда поток запускается, он вызывает метод запуска NioEventLoop для выполнения задач ввода-вывода и задач, не связанных с вводом-выводом:
- Задачи ввода/вывода То есть события готовности в selectionKey, такие как принятие, подключение, чтение, запись и т. д., инициируются методом processSelectedKeys.
- задачи, не связанные с вводом-выводом Задачи, добавленные в taskQueue, такие как register0, bind0 и другие задачи, запускаются методом runAllTasks.
Соотношение времени выполнения двух задач контролируется переменной ioRatio, которая по умолчанию равна 50, что означает, что время выполнения задачи без ввода-вывода равно времени выполнения задачи ввода-вывода.
NioEventLoopGroup
NioEventLoopGroup, который в основном управляет жизненным циклом eventLoop, можно понимать как пул потоков, внутри которого поддерживается набор потоков.Каждый поток (NioEventLoop) отвечает за обработку событий на нескольких каналах, а один канал соответствует только одному потоку.
ChannelHandler
ChannelHandler — это интерфейс, который обрабатывает события ввода-вывода или перехватывает операции ввода-вывода и перенаправляет их следующему обработчику в ChannelPipeline (цепочке бизнес-обработки).
Сам ChannelHandler не предоставляет много методов, потому что этот интерфейс имеет много методов, которые необходимо реализовать, и во время использования его подклассы могут наследоваться:
- ChannelInboundHandler для обработки входящих событий ввода-вывода
- ChannelOutboundHandler используется для обработки исходящих операций ввода-вывода.
Или используйте следующий класс адаптера:
- ChannelInboundHandlerAdapter для обработки входящих событий ввода-вывода.
- ChannelOutboundHandlerAdapter для обработки исходящих операций ввода-вывода.
- ChannelDuplexHandler для обработки входящих и исходящих событий
ChannelHandlerContext
Сохраните всю контекстную информацию, связанную с каналом, и одновременно свяжите объект ChannelHandler.
ChannelPipline
Содержит список обработчиков каналов для обработки или перехвата входящих событий канала и исходящих операций. ChannelPipeline реализует расширенную форму шаблона фильтра перехвата, который дает пользователю полный контроль над тем, как обрабатываются события и как отдельные ChannelHandlers в канале взаимодействуют друг с другом.
Следующий рисунок относится к описанию ChannelPipline в Netty Javadoc4.1, в котором описывается, как ChannelHandler в ChannelPipeline обычно обрабатывает события ввода-вывода. События ввода-вывода обрабатываются ChannelInboundHandler или ChannelOutboundHandler и перенаправляются к ближайшему обработчику путем вызова методов распространения событий, определенных в ChannelHandlerContext (таких как ChannelHandlerContext.fireChannelRead(Object) и ChannelOutboundInvoker.write(Object)).
I/O Request
via Channel or
ChannelHandlerContext
|
+---------------------------------------------------+---------------+
| ChannelPipeline | |
| \|/ |
| +---------------------+ +-----------+----------+ |
| | Inbound Handler N | | Outbound Handler 1 | |
| +----------+----------+ +-----------+----------+ |
| /|\ | |
| | \|/ |
| +----------+----------+ +-----------+----------+ |
| | Inbound Handler N-1 | | Outbound Handler 2 | |
| +----------+----------+ +-----------+----------+ |
| /|\ . |
| . . |
| ChannelHandlerContext.fireIN_EVT() ChannelHandlerContext.OUT_EVT()|
| [ method call] [method call] |
| . . |
| . \|/ |
| +----------+----------+ +-----------+----------+ |
| | Inbound Handler 2 | | Outbound Handler M-1 | |
| +----------+----------+ +-----------+----------+ |
| /|\ | |
| | \|/ |
| +----------+----------+ +-----------+----------+ |
| | Inbound Handler 1 | | Outbound Handler M | |
| +----------+----------+ +-----------+----------+ |
| /|\ | |
+---------------+-----------------------------------+---------------+
| \|/
+---------------+-----------------------------------+---------------+
| | | |
| [ Socket.read() ] [ Socket.write() ] |
| |
| Netty Internal I/O Threads (Transport Implementation) |
+-------------------------------------------------------------------+
Входящие события обрабатываются обработчиками входящих событий в восходящем направлении, как показано в левой части рисунка. Входящие обработчики обычно обрабатывают входящие данные, генерируемые потоками ввода-вывода в нижней части схемы. Входящие данные обычно считываются с удаленного устройства с помощью фактической операции ввода, такой как SocketChannel.read(ByteBuffer).
Исходящие события обрабатываются в направлении вверх и вниз, как показано в правой части рисунка. Обработчики исходящего трафика обычно генерируют или преобразовывают исходящие транспорты, такие как запросы на запись. Поток ввода-вывода обычно выполняет фактические операции вывода, такие как SocketChannel.write(ByteBuffer).
В Netty каждому каналу соответствует один и только один ChannelPipeline, и их композиционные отношения следующие:
Channel содержит ChannelPipeline, а ChannelPipeline поддерживает двусвязный список, состоящий из ChannelHandlerContext, и каждый ChannelHandlerContext связан с ChannelHandler. Входящие и исходящие события находятся в двусвязном списке. Входящие события будут перенаправляться из начала связанного списка в последний обработчик входящих событий, а исходящие события будут перенаправляться из хвоста связанного списка в первый обработчик исходящих событий. типы обработчиков не мешают друг другу.
Как это работает
Процесс инициализации и запуска сервера Netty выглядит следующим образом:
public static void main(String[] args) {
// 创建mainReactor
NioEventLoopGroup boosGroup = new NioEventLoopGroup();
// 创建工作线程组
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
final ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap
// 组装NioEventLoopGroup
.group(boosGroup, workerGroup)
// 设置channel类型为NIO类型
.channel(NioServerSocketChannel.class)
// 设置连接配置参数
.option(ChannelOption.SO_BACKLOG, 1024)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childOption(ChannelOption.TCP_NODELAY, true)
// 配置入站、出站事件handler
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel ch) {
// 配置入站、出站事件channel
ch.pipeline().addLast(...);
ch.pipeline().addLast(...);
}
});
// 绑定端口
int port = 8080;
serverBootstrap.bind(port).addListener(future -> {
if (future.isSuccess()) {
System.out.println(new Date() + ": 端口[" + port + "]绑定成功!");
} else {
System.err.println("端口[" + port + "]绑定失败!");
}
});
}
- Основной процесс выглядит следующим образом:
- 1 Инициализировать и создать 2 NioEventLoopGroups, из которых boosGroup используется для событий установления соединения Accetpt и отправки запросов, workerGroup используется для обработки событий чтения и записи ввода-вывода и бизнес-логики.
- 2 На основе ServerBootstrap (класс начальной загрузки сервера) настройте EventLoopGroup, тип канала, параметры подключения, настройте обработчики входящих и исходящих событий.
- 3 Привязать порт и начать работать
В сочетании с моделью Netty Reactor, представленной выше, мы представляем схему рабочей архитектуры Netty на стороне сервера:
Сторона сервера включает 1 Boss NioEventLoopGroup и 1 Worker NioEventLoopGroup.NioEventLoopGroup эквивалентна 1 группе цикла событий.Эта группа содержит несколько циклов событий NioEventLoop, и каждый NioEventLoop содержит 1 селектор и 1 поток цикла событий.
Задачи, которые выполняет каждый Boss NioEventLoop в цикле, состоят из 3 шагов:
- 1 опрос для принятия событий
- 2 Обработайте событие accept I/O, установите соединение с клиентом, сгенерируйте NioSocketChannel и зарегистрируйте NioSocketChannel с помощью Selector of a Worker NioEventLoop. *3 Обработка задач в очереди задач, runAllTasks. Задачи в очереди задач включают задачи, выполняемые пользователем, вызывающим eventloop.execute или schedule, или задачи, отправленные в цикл обработки событий другими потоками.
Задачи, выполняемые каждым циклом Worker NioEventLoop, включают 3 шага:
- 1 Опрос событий чтения и записи;
- 2 события ввода-вывода, а именно события чтения и записи, обрабатываются, когда происходят события чтения и записи NioSocketChannel
- 3 Обработайте задачи в очереди задач, запустите AllTasks.
Существует три типичных сценария использования задач в очереди задач.
- 1 Общие задачи, настраиваемые пользовательской программой
ctx.channel().eventLoop().execute(new Runnable() {
@Override
public void run() {
//...
}
});
-
2 Различные способы вызова канала нетекущим потоком реактора Например, в бизнес-потоке системы push в соответствии с идентификатором пользователя найдите соответствующую ссылку на канал, а затем вызовите метод класса записи, чтобы отправить сообщение пользователю, который войдет в этот сценарий. Окончательная запись будет отправлена в очередь задач и использована асинхронно.
-
3 пользовательских запланированных задания
ctx.channel().eventLoop().schedule(new Runnable() {
@Override
public void run() {
}
}, 60, TimeUnit.SECONDS);
4 Резюме
Основной версией, которая в настоящее время рекомендуется для стабильности, по-прежнему является Netty 4. В Netty 5 используется ForkJoinPool, что увеличивает сложность кода, но улучшение производительности не является очевидным, поэтому эта версия не рекомендуется, а официальный сайт не предоставляет ссылка для скачивания.
Порог входа в Netty относительно высок, на самом деле это потому, что в этой области меньше информации, а не из-за того, насколько это сложно, на самом деле, каждый может понять Netty, а также Spring. Перед обучением рекомендуется понять принципиальную структуру всего фреймворка и процесс работы, что позволит избежать многих обходных путей.
Ссылаться на
Начало работы с Netty: имитация системы обмена мгновенными сообщениями WeChat IM
Заметки об исследовании Netty 4.x — многопоточная модель
Понимание высокопроизводительных сетевых моделей
Введение в основные принципы Netty
software-architecture-patterns.pdf
Высокая производительность Нетти - Ли Линьфэн
"Нетти в действии"
Полное руководство по Netty