Альтернативные WebSockets для netty/java: удвоение пропускной способности небольших сообщений

RedDeveloper
03.01.2023 13:43
Альтернативные WebSockets для netty/java: удвоение пропускной способности небольших сообщений

Этот пост - краткая презентация netty-websocket-http1 - альтернативной netty/java реализации RFC6455 - протокола WebSocket.

Ее преимуществом является значительное повышение пропускной способности на ядро (1.8-2x) для небольших кадров по сравнению с готовыми websocket-кодеками netty, а также минимальное выделение кучи на пути к кадру. Библиотека также может быть объединена с netty-websocket-http2 .

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

Предварительная оценка производительности с помощью готового кодека netty показала всего ~1M 120-байтовых сообщений на ядро через соединение без TLS - очень скромно для этого простого формата передачи данных, что следует из опыта работы с другими протоколами .

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

Пример использования & область применения

  • Предназначена для эффективно закодированных, плотных двоичных данных: без поддержки расширений (сжатия) / исходящие текстовые фреймы / входящая проверка UTF8.
  • Библиотека предполагает небольшие фреймы - многие имеют полезную нагрузку <= 125 байт, большинство <1500, максимально поддерживается 65k (65535 байт).
  • Только кодек - фрагменты, пинги, закрытые кадры декодируются & только валидируются. Обработка кадров в соответствии с протоколом (сборка фрагментов кадра, постепенное закрытие, ответ на пинги) входит в обязанности пользовательского кода.
  • Специальный декодер для случая обмена крошечными сообщениями через TLS-соединение: только немаскированные кадры с <= 125 байтами полезной нагрузки для минимальных накладных расходов на состояние (память) каждого WebSocket.
  • Никаких выделений кучи для каждого кадра в WebSocket FrameFactory / декодере.
  • Однопоточные (транспортный IO event-loop) обратные вызовы / frame factory API: на практике пользовательский код имеет свои собственные типы сообщений для переноса данных, внешние средства (например, mpsc / spsc очереди) могут быть использованы для правильной публикации сообщений в потоке event-loop.

FrameFactory / Callbacks API

WebSocketFrameFactory для создания исходящих фреймов. Пользователь библиотеки несет ответственность за маскировку исходящего фрейма после записи полезной нагрузки: ByteBuf WebSocketFrameFactory.mask(ByteBuf)

public interface WebSocketFrameFactory {

  ByteBuf createBinaryFrame(ByteBufAllocator allocator, int binaryDataSize);
  // create*Frame are omitted for control frames, created in similar fashion

  ByteBuf mask(ByteBuf frame);
}

WebSocketFrameListener для получения входящих кадров

public interface WebSocketFrameListener {

  void onChannelRead(ChannelHandlerContext ctx, boolean finalFragment,
                     int rsv, int opcode, ByteBuf payload);
   
  // netty handler callbacks are omitted for brevity

  // lifecycle
  default void onOpen(ChannelHandlerContext ctx) {}

  default void onClose(ChannelHandlerContext ctx) {}

WebSocketCallbacksHandler для обмена WebSocketFrameListener на WebSocketFrameFactory при успешном WebSocket handshake

public interface WebSocketCallbacksHandler {

  WebSocketFrameListener exchange(
      ChannelHandlerContext ctx, WebSocketFrameFactory webSocketFrameFactory);
}

Производительность

Ниже приведено сравнение производительности на ядро с готовыми обработчиками WebSocket в netty: немаскированные кадры с 8, 64, 125, 1000 байт полезной нагрузки по шифрованному/нешифрованному соединению.

  • нешифрованное
  • зашифрованный
Ниже приведено сравнение производительности на ядро с готовыми обработчиками WebSocket в

Websocket-http2

Библиотека может быть объединена с jauntsdn/websocket-http2 с помощью http1 codec API. Для кадров полезной нагрузки 8, 125, 1000 байт через зашифрованное соединение результаты следующие:

Библиотека может быть объединена с jauntsdn/websocket-http2 с помощью http1 codec API Для

Примеры

Модуль тестирования производительности также служит хорошей демонстрацией API как для клиента , так и для сервера.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?

20.08.2023 18:21

Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в 2023-2024 годах? Или это полная лажа?".

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией

20.08.2023 17:46

В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.

Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox

19.08.2023 18:39

Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в частности, магию поплавков и гибкость flexbox.

Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest

19.08.2023 17:22

В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для чтения благодаря своей простоте. Кроме того, мы всегда хотим проверить самые последние возможности в наших проектах!

Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️

18.08.2023 20:33

Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий их языку и культуре.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL

14.08.2023 14:49

Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип предназначен для представления неделимого значения.