Разница между написанием ByteBuf и обычными объектами Java

#netty #netty4

#netty #netty4

Вопрос:

Я заметил, что при использовании Netty можно записывать другие данные, которые являются экземпляром ByteBuff или простыми объектами Java.

Как видно из HAProxyClient

В этом файле у вас есть

 HAProxyMessage message = new HAProxyMessage(
                    HAProxyProtocolVersion.V2, 
                    HAProxyCommand.PROXY, HAProxyProxiedProtocol.TCP4,
                    "127.0.0.1", 
                    "127.0.0.2", 
                    8000, 
                    9000
);

ch.writeAndFlush(message).sync();
 

Где обычный объект Java, HAProxyMessage был записан в контекст. Все еще в том же файле у вас есть:

 ch.writeAndFlush(Unpooled.copiedBuffer("Hello World!", CharsetUtil.US_ASCII)).sync();
 

Где Unpooled.copiedBuffer используется для создания данных, подлежащих записи. Этот метод возвращает a ByteBuf .

Тогда возникает вопрос: какова существенная разница (если таковая имеется) между записью (или чтением) объекта plan Java и ByteBuf

Ответ №1:

Когда вы пишете ByteBuf, сообщение не нуждается в каком-либо преобразовании. Когда это объект Java, вам нужен кодировщик / декодер. Здесь у вас есть следующее:

Они преобразуют объект Java в ByteBuf (кодировщик) или наоборот (декодер).

Способ, которым вы хотите использовать тот или иной, зависит от вашего текущего случая:

  • управляете ли вы объектом Java? Вероятно, наличие кодека (Encoder / Decodec) — хороший способ.
  • управляете ли вы простыми данными (байтовым потоком, простыми значениями …)? Вероятно, прямое управление ByteBuf — хороший способ. Это не единственные актуальные вопросы, которые нужно решать для того или другого.

Но, наконец, в Netty все является ByteBuf.

Комментарии:

1. Я понимаю. Следовательно, если мне нужно сказать, напишите что-то вроде новой строки. Вероятно, было бы эффективнее превратить это в массив byte[], чем обернуть его в ByteBuf? или нет?

2. Огромным преимуществом ByteBuf является его способность накапливать различные источники. Например, из массива байтов, используя обернутый ByteBuf, и для добавления нескольких байтов, используя составной ByteBuf, или reverseley для создания ByteBuf с вероятным конечным размером и записи всего в него. Основная идея состоит в том, чтобы ограничить как можно большее копирование памяти, поэтому, в общем, обертывание и использование композиции ByteBufs являются лучшими. Но, как правило, это означает, что, конечно, есть исключения. Внутренне Netty нуждается в ByteBuf, поэтому какой бы объект Java вы ни использовали (даже массив байтов), в конечном итоге придется обратиться к ByteBuf.

3. Спасибо за ответ. Я знаю, что существуют разные реализации ByteBuf. Вы случайно не знаете, какой по умолчанию использует Netty internally…so пример в случае, когда записывается что-то такое простое, как byte[] ?

4. Это действительно зависит от протокола. Например, когда размер уже известен и сообщение создается из разных источников, ByteBuf выделяется один раз и записывается из разных источников (это, как правило, имеет непрерывный внутренний массив байтов, поэтому более эффективно, но ценой нескольких копий). Другой пример — когда исходный код ограничен массивом в один байт (или более, как в вашем примере), для предотвращения копирования мы используем wrappedBuffers(array1, array2, array3), который, как правило, ограничивает копирование по цене, не связанной с непрерывным доступом к памяти. Однако, наконец, все должно быть ByteBuf.

5. Кроме того, Netty использует мощный и эффективный алгоритм для выделения памяти, повторного использования, буферизации, поэтому причина ByteBuf. Если у вас есть только один байтовый массив (или 2, один для реальных данных, другой, фиксированный, для » n».getBytes() , вы можете использовать wrappedBuffers . Но если у вас есть возможность встроить этот массив байтов непосредственно в ByteBuf, это может быть даже лучше, поскольку «ваш» массив байтов, следовательно, не управляется пулом памяти Netty при его переносе.