Серия Netty: подробное объяснение канала в netty

Java Netty

Это пятый день моего участия в августовском испытании обновлений, подробности о мероприятии:Испытание августовского обновления

Введение

Канал — это мост, соединяющий ByteBuf и Event. Канал в netty предоставляет унифицированный API. Благодаря этому унифицированному API netty может легко подключаться к различным типам передачи, таким как OIO, NIO и т. д. Сегодня эта статья познакомит вас с использованием канала и некоторыми понятиями, связанными с каналом.

Сведения о канале

Что такое канал? Канал — это мост между сетевым вводом и обработкой ввода-вывода. Вы можете использовать канал для оценки текущего состояния, независимо от того, открыт он или подключен, а также для оценки операций ввода-вывода, поддерживаемых текущим каналом.Вы также можете использовать ChannelPipeline для обработки сообщений в канале.

Сначала посмотрите на определение канала:

public interface Channel extends AttributeMap, ChannelOutboundInvoker, Comparable<Channel> {

Вы можете видеть, что Channel — это интерфейс, который наследует три класса: AttributeMap, ChannelOutboundInvoker и Comparable. Comparable указывает, что этот класс можно использовать для сравнения. AttributeMap используется для хранения различных атрибутов канала. ChannelOutboundInvoker в основном отвечает за соединение и запись между Channel и внешним SocketAddress.

Взгляните на методы, определенные в канале:

Видно, что в канале определены различные методы, каковы характеристики этих методов? Далее я объясню вам один за другим.

Асинхронный IO и Cannelfuture

Все операции ввода-вывода в netty являются асинхронными операциями ввода-вывода, что означает, что все операции ввода-вывода возвращаются немедленно. При возврате операции ввода-вывода могут не закончиться, поэтому необходимо вернуть ChannelFuture. Когда операция ввода-вывода имеет результат, ChannelFuture будет уведомлен, чтобы Результат можно забрать.

ChannelFuture — подкласс java.util.concurrent.Future, который помимо получения результата выполнения потока еще и расширяет его, добавляя функции оценки текущего состояния задачи, ожидания выполнения задачи и добавления слушателей.

Другие функции хорошо изучены.Его прорыв заключается в возможности добавления слушателей в ChannelFuture.Перечислим способ добавления слушателей:

Future<V> addListeners(GenericFutureListener<? extends Future<? super V>>... listeners);

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

ChannelFuture имеет два состояния: незавершенное или завершенное, которые соответственно представляют состояние выполнения задачи.

Когда IO только начинается, возвращается объект ChannelFuture, и начальное состояние этого объекта не завершено. Обратите внимание, что IO в этом состоянии — это состояние, которое еще не начало работать. Когда ввод-вывод завершится, будь он успешным, неудачным или отмененным, состояние ChannelFuture будет преобразовано в завершенное.

На следующем рисунке показана соответствующая диаграмма состояния ChannelFuture и состояния ввода-вывода:

Если вы хотите отслеживать состояние ввода-вывода, вы можете использовать метод addListener, о котором мы упоминали выше, чтобы добавить ChannelFutureListener в ChannelFuture.

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

Напротив, addListener(GenericFutureListener) — это неблокирующий асинхронный метод, который добавит ChannelFutureListener в ChannelFuture и автоматически уведомит ChannelFutureListener о завершении ввода-вывода, что очень полезно.

Для ChannelHandler, который обрабатывает операции ввода-вывода, чтобы избежать блокировки ввода-вывода, вы не должны вызывать await() в методе ввода-вывода ChannelHandler, что может привести к снижению производительности ChannelHandler из-за блокировки ввода-вывода.

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

   // 错误操作
    @Override
   public void channelRead(ChannelHandlerContext ctx, Object msg) {
       ChannelFuture future = ctx.channel().close();
       future.awaitUninterruptibly();
       // 调用其他逻辑
   }

   // 正确操作
    @Override
   public void channelRead(ChannelHandlerContext ctx, Object msg) {
       ChannelFuture future = ctx.channel().close();
       future.addListener(new ChannelFutureListener() {
           public void operationComplete(ChannelFuture future) {
               // 调用其他逻辑
           }
       });
   }

Вы можете сравнить разницу между двумя вышеуказанными способами письма.

Также обратите внимание, что они ждут метода Channerfuture в таком виде как: ждут (долго), ждут (долго, timeunit), awantuniNebraphebraphibe (длинный), или a aboutuniNebraph for (долго, timeunit) может сделать срок годности, следует отметить, что это истек Время выполнения - это время исполнения, а не время ожидания IO, то есть, когда awaque Timeout, IO не может быть выполнен, что приводит к следующим возможным кодам ошибок:

   Bootstrap b = ...;
   ChannelFuture f = b.connect(...);
   f.awaitUninterruptibly(10, TimeUnit.SECONDS);
   if (f.isCancelled()) {
       // 用户取消了Channel
   } else if (!f.isSuccess()) {
       // 这里可能会报异常,因为底层的IO可能还没有执行完成
       f.cause().printStackTrace();
   } else {
       // 成功建立连接
   }

Приведенный выше код можно изменить на следующий пример:

  Bootstrap b = ...;
   // 配置连接timeout的时间
   b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000);
   ChannelFuture f = b.connect(...);
   f.awaitUninterruptibly();

   // 等待直到底层IO执行完毕
   assert f.isDone();

   if (f.isCancelled()) {
       // 用户手动取消Channel
   } else if (!f.isSuccess()) {
       f.cause().printStackTrace();
   } else {
       // 成功建立连接
   }

Иерархия каналов

Каналы в netty имеют иерархическую структуру, которую можно получить через свойство parent. Объект, полученный родителем, связан с тем, как был создан канал. Например, если это SocketChannel, принятый ServerSocketChannel, то его родителем является ServerSocketChannel.

освободить ресурсы

Как и все операции ввода-вывода, канал должен быть освобожден после того, как он будет использован, и необходимо вызвать метод close() или close(ChannelPromise).

обработка событий

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

Мы подробно объясним взаимосвязь между ChannelEvent, Channelhandler и ChannelPipeline в следующей главе, так что следите за обновлениями.

Суммировать

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

Эта статья была включена вWoohoo Floyd Press.com/04-Netty-eat…

Самая популярная интерпретация, самая глубокая галантерея, самые краткие уроки и множество трюков, о которых вы не знаете, ждут вас!

Добро пожаловать, чтобы обратить внимание на мой официальный аккаунт: «Программируйте эти вещи», разбирайтесь в технологиях, лучше поймите себя!