Плюсы и минусы протокола MessagePack¶
MessagePack1 — это бинарный протокол сериализации данных. Строго говоря, он может использоваться не только в связке с SignalR, но и сам по себе. Обладает схоже с JSON структурой, но в отличие от JSON сериализованный таким образом объект не будет “человекочитаемым”. С другой стороны, сериализованные объекты, в силу бинарной природы протокола, будут меньше, следовательно, будут передаваться быстрее.
Включаем MessagePack на сервере¶
MessagePack поставляется в виде отдельного NuGet пакета, поэтому прежде всего его нужно установить:
Затем, в файле Program.cs пишем юзинг:
Далее либо заменим вызов
AddJsonProtocol, либо добавим после него следующее2:.AddMessagePackProtocol(options => {
options.SerializerOptions = MessagePackSerializerOptions.Standard
.WithSecurity(MessagePackSecurity.UntrustedData)
.WithCompression(MessagePackCompression.Lz4Block)
.WithAllowAssemblyVersionMismatch(true)
.WithOldSpec()
.WithOmitAssemblyVersion(true);
});
Этот код демонстрирует некоторые (не все) настройки, которые можно изменять при инициализации3.
SerializerOptions— объект настроек типаMessagePackSerializerOptions;WithSecurity— так как нет никакого способа проверить валидность данных до начала десериализации, это может быть возможным вектором атаки. Задавая свойства объекта классаMessagePackSecurityможно тонко настраивать поведение десериализатора с точки зрения безопасности. Также есть два предустановленных объекта —TrustedDataдля абсолютно доверенных данных иUntrustedDataдля сомнительных;WithCompression— сериализованные данные можно сжать алгоритмом LZ4 для большей компактности. Возможные варианты:None,Lz4BlockиLz4BlockArray. Последний вариант является предпочтительным. Подробнее разница между вариантами освещена в документации;WithAllowAssemblyVersionMismatch— можно отключить проверку совпадения версий сборки на клиенте (если версия указана в сообщении) и сервере, или включить, если требуется точное совпадение;WithOldSpec— позволяет использовать старые спецификации (?);WithOmitAssemblyVersion— отключает указание версии сборки в сообщении.
Включаем MessagePack в JavaScript клиенте¶
На момент написания книги библиотека MessagePack была доступна только при инсталляции через npm:
после установки копируем из папки
node_modules/@microsoft/signalr-protocol-msgpack/dist/browser файл signalr-protocol-msgpack.js или signalr-protocol-msgpack.min.js в папку SignalRServer/wwwroot/lib/signalr (если такой папки нет - её надо создать). Пусть мы выбрали signalr-protocol-msgpack.min.js. Добавляем его в файл _Layout.cshtml следующей строчкой после подключения библиотеки SignalR:И наконец, в файле site.js, в месте, где создаётся объект
connection, перед вызовом метода build() вставляемВключаем MessagePack в .NET клиенте¶
добавляем юзинг
и добавляем в блок инициализации
hubConnection перед вызовом метода Build() следующее:.AddMessagePackProtocol(options =>
{
options.SerializerOptions = MessagePackSerializerOptions.Standard
.WithSecurity(MessagePackSecurity.UntrustedData)
.WithCompression(MessagePackCompression.Lz4Block)
.WithAllowAssemblyVersionMismatch(true)
.WithOldSpec()
.WithOmitAssemblyVersion(true);
})
Как мы видим, настройки идентичны настройкам на сервере.
Включаем MessagePack в Java клиенте¶
Пакеты SignalR MessagePack для Java могут быть найдены в репозитории Maven здесь. Выбираем нужную нам версию пакета и следуем инструкции для используемой нами системы сборки.
После этого добавляем метод withHubProtocol() с указанием объекта протокола MessagePack, вот таким образом:
HubConnection hubConnection = HubConnectionBuilder.create(input)
.withHubProtocol(new MessagePackHubProtocol())
.build();
Недостатки протокола MessagePack¶
Первым недостатком протокола будет то, что он недоступен “из коробки”. Для его использования необходимо устанавливать дополнительные пакеты.
Другим недостатком будет то, что этот протокол является регистрозависимым, в отличие от JSON. Это может стать значительной проблемой в случае, когда клиент и сервер написаны на разных языках: в разных языках существуют разные соглашения относительно регистров именования переменных. В .NET это чаще всего PascalCase, а, к примеру, в javaScript это camelCase. Обойти это можно, используя атрибуты для присвоения camelCase-имён свойствам C#-объектов. Подробнее о том, как работает маппинг полей см. в документации3.
-
Напомню, что похожим образом можно подключить NewtonsoftJson в качестве протокола сериализации. ↩
Дата создания : 10 февраля 2023 г.