Поделиться через


Рекомендации по кодировке сообщений

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

В этой статье описаны некоторые аспекты.

Потребности обмена сообщениями

Обмен сообщениями между производителем и потребителем требует:

  • Форма или структура, определяющая полезную нагрузку сообщения.
  • Формат кодирования для представления полезных данных.
  • Библиотеки сериализации для чтения и записи закодированного содержимого.

Производитель сообщения определяет фигуру сообщения на основе бизнес-логики и информации, которую он хочет отправить потребителям. Чтобы структурировать фигуру, разделите информацию на дискретные или связанные темы (поля). Определите характеристики значений для этих полей. Вам нужно рассмотреть следующие вопросы.

  • Какой наиболее эффективный тип данных?
  • Всегда ли нагрузка содержит определенные поля?
  • Имеют ли полезные данные одну запись или повторяющийся набор значений?

Затем выберите формат кодирования в зависимости от необходимости. Некоторые факторы включают возможность создавать высокоструктурированные данные, если это необходимо, время, затраченное на кодирование и передачу сообщения, а также возможность анализа полезных данных. В зависимости от формата кодирования выберите библиотеку сериализации, которая хорошо поддерживается.

Потребитель сообщения должен знать об этих решениях, чтобы он знал, как читать входящие сообщения.

Для передачи сообщений производитель сериализует сообщение в формат кодирования. На принимающей стороне потребитель десериализует полезную нагрузку для использования. Таким образом, обе сущности разделяют модель, и до тех пор, пока структура не изменяется, обмен сообщениями продолжается без проблем. При изменении контракта формат кодирования должен быть способен обрабатывать изменения без нарушения потребителя.

Некоторые форматы кодирования, такие как JSON, самоописываются, то есть их можно анализировать без ссылки на схему. Однако такие форматы, как правило, дают более крупные сообщения. С другими форматами данные могут не анализироваться так же легко, но сообщения сжимаются. В этой статье рассматриваются некоторые факторы, которые помогут выбрать формат.

Рекомендации по формату кодирования

Формат кодирования определяет, как набор структурированных данных представлен в виде байтов. Тип сообщения может повлиять на выбор формата. Сообщения, связанные с бизнес-транзакциями, скорее всего, содержат структурированные данные. Кроме того, может потребоваться получить его позже для целей аудита. Для потока событий может потребоваться как можно быстрее прочитать последовательность записей и сохранить ее для статистического анализа.

Ниже приведены некоторые моменты, которые следует учитывать при выборе формата кодирования.

Читаемость для человека

Кодировка сообщений может быть широко разделена на текстовые и двоичные форматы.

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

Недостатком является то, что полезная нагрузка, по большей части, больше. Размер полезных данных часто может быть сокращен с помощью процесса минификации, если он может быть изменен для удобочитаемости человека при необходимости. Распространенные текстовые форматы — JSON и YAML.

Шифрование

Если в сообщениях есть конфиденциальные данные, рассмотрите, следует ли шифровать эти сообщения в полном объеме, как описано в этой инструкции по шифрованию данных Azure Service Bus в состоянии покоя. Кроме того, если для этого необходимо зашифровать только определенные поля, и вы предпочитаете сократить затраты на облако, рассмотрите возможность использования библиотеки, такой как NServiceBus.

Размер кодировки

Размер сообщения влияет на производительность ввода-вывода сети. Двоичные форматы являются более компактными, чем текстовые форматы. Двоичные форматы требуют библиотек сериализации и десериализации. Полезные данные не могут быть прочитаны, если они не расшифрованы.

Используйте двоичный формат, если вы хотите сократить объем проводных операций и ускорить передачу сообщений. Эта категория формата рекомендуется в сценариях, когда хранилище или пропускная способность сети является проблемой. Варианты двоичных форматов включают Apache Avro, буферы протокола Google (protobuf), MessagePack и краткое представление двоичного объекта (CBOR). Преимущества и минусы этих форматов описаны далее в разделе Выбор форматов кодирования.

Недостатком является то, что полезная нагрузка нечитаема для человека. Большинство двоичных форматов используют сложные системы, которые могут быть дорогостоящими для обслуживания. Кроме того, им нужны специализированные библиотеки для декодирования, которые могут не поддерживаться, если требуется получить архивные данные.

Применение процесса минификации для удаления технически ненужных пробелов и символов в небинарных форматах, при сохранении соответствия спецификациям формата, может помочь уменьшить размер кодировки. Оцените возможности вашего кодировщика для установки минификации по умолчанию. Например, JsonSerializerOptions.WriteIndented из System.Text.Json.JsonSerializer .NET управляет автоматическим сжатием при создании JSON-документа.

Понимание полезной нагрузки

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

Тегированные метаданные. В некоторых кодировках, в частности JSON, поля помечены типом данных и идентификатором в тексте сообщения. Эти форматы самоописательные, так как их можно разобрать в формате словаря значений без ссылки на схему. Одним из способов понимания полей является запрос ожидаемых значений. Например, производитель отправляет полезные данные в ФОРМАТЕ JSON. Потребитель разбирает JSON-файл в словарь и проверяет наличие полей, чтобы понять передаваемое сообщение. Другой способ заключается в том, чтобы потребитель применял модель данных, общую производителем. Например, если вы используете статически типизированный язык, многие библиотеки сериализации JSON могут анализировать строку JSON в типизированном классе.

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

  • Сохраните схему в виде преамбла или заголовка в сообщении, но отдельно от полезных данных.

  • Сохраните схему в внешнем хранилище.

Некоторые форматы кодирования определяют схему и используют средства, которые создают классы из схемы. Производитель и потребитель используют эти классы и библиотеки для сериализации и десериализации данных. Библиотеки также обеспечивают проверки совместимости между схемой записи и считывания. И protobuf, и Apache Avro следуют этому подходу. Ключевым отличием является то, что protobuf имеет определение схемы, не зависящего от языка, но Avro использует компактный JSON. Другое различие заключается в том, что оба формата обеспечивают проверки совместимости между схемами чтения и записи.

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

Прежде чем выбрать подход, определите, что более важно: размер передаваемых данных или возможность анализа архивированных данных позже.

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

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

Управление версиями схемы

С изменением бизнес-требований структура, вероятно, изменится, и схема будет развиваться. Управление версиями позволяет производителю указывать обновления схемы, которые могут включать новые функции. Существует два аспекта управления версиями:

  • Потребитель должен знать об изменениях.

    Один из способов заключается в том, чтобы потребитель проверял все поля, чтобы определить, изменилась ли схема. Другой способ заключается в том, чтобы производитель опубликовал номер версии схемы с сообщением. Когда схема развивается, производитель увеличивает версию.

  • Изменения не должны влиять или нарушать бизнес-логику потребителей.

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

    Форматы кодирования, такие как Avro, предлагают возможность определять значения по умолчанию. В предыдущем примере, если поле добавляется со значением по умолчанию, отсутствующее поле заполняется значением по умолчанию. Другие форматы, такие как protobuf, предоставляют аналогичные функции с помощью обязательных и необязательных полей.

Структура полезных данных

Рассмотрим способ упорядочения данных в нагрузке. Это последовательность записей или одиночный элемент? Структура полезной нагрузки может быть классифицирована как одна из следующих моделей.

  • Массив/словарь/значение: определяет записи, которые содержат значения в одном или многомерном массиве. Записи содержат уникальные пары ключ-значение. Его можно расширить для представления сложных структур. К некоторым примерам относятся JSON, Apache Avro и MessagePack.

    Этот макет подходит, если сообщения закодированы различными схемами. Если у вас несколько записей, полезные данные могут оказаться чрезмерно избыточными, что приводит к превышению полезных данных.

  • Табличные данные: информация делится на строки и столбцы. Каждый столбец указывает поле или тему информации, а каждая строка содержит значения для этих полей. Этот макет эффективен для повторяющегося набора сведений, таких как данные временных рядов.

    CSV — это один из самых простых текстовых форматов. Он представляет данные в виде последовательности записей с общим заголовком. Для двоичной кодировки Apache Avro имеет преамблирование, похожее на заголовок CSV, но создает компактный размер кодирования.

Поддержка библиотеки

Следует использовать известные форматы вместо собственной модели. Известные форматы поддерживаются через библиотеки, которые поддерживаются сообществом. В специализированных форматах требуются определенные библиотеки. Бизнес-логика может обойти некоторые варианты проектирования API, предоставляемые библиотеками.

Для формата на основе схемы выберите библиотеку кодирования, которая проверяет совместимость между схемой чтения и записи. Некоторые библиотеки кодирования, такие как Apache Avro, ожидают, что пользователь укажет как схему записи, так и схему чтения перед десериализацией сообщения. Эта проверка гарантирует, что потребитель осведомлён о версиях схемы.

Взаимодействие

Выбор форматов может зависеть от конкретной рабочей нагрузки или экосистемы технологий.

Например:

  • Azure Stream Analytics имеет встроенную поддержку JSON, CSV и Avro. Когда рабочая нагрузка использует Stream Analytics, имеет смысл выбрать один из этих форматов.

  • JSON — это стандартный формат обмена для REST API HTTP. Если приложение получает полезные данные JSON от клиентов, а затем помещает их в очередь сообщений для асинхронной обработки, может потребоваться использовать JSON для обмена сообщениями, а не повторно кодировать их в другой формат.

Это всего два примера рекомендаций по взаимодействию. Как правило, стандартизованные форматы являются более совместимыми, чем пользовательские форматы. В текстовых опциях JSON является одним из наиболее совместимых.

Выбор форматов кодирования

Ниже приведены некоторые популярные форматы кодирования. Учитывайте аспекты перед тем как выбрать формат.

JSON

JSON — это открытый стандарт (IETF RFC8259). Это текстовый формат, который следует модели массива, словаря или значения.

JSON можно использовать для тегов метаданных, и вы можете проанализировать полезные данные без схемы. JSON поддерживает параметр для указания необязательных полей, которые помогают обеспечить прямую и обратную совместимость.

Самое большое преимущество заключается в том, что она доступна везде. Он наиболее совместим и формат кодировки по умолчанию для многих служб обмена сообщениями.

Будучи текстовым форматом, он неэффективен при передаче данных и не является идеальным выбором в случаях, когда важна экономия места. Используйте методы минификации, где это возможно. Если вы возвращаете кэшированные элементы непосредственно клиенту через HTTP, сохранение данных в формате JSON может сократить затраты на десериализацию из другого формата, а затем сериализацию в JSON.

Используйте JSON для сообщений с одной записью или для последовательности сообщений, в которых каждое сообщение имеет другую схему. Избегайте использования JSON для последовательности записей, например для данных временных рядов.

Существуют и другие варианты JSON, такие как двоичный json (BSON), который является двоичной кодировкой, выровненной для работы с MongoDB.

значения Comma-Separated (CSV)

CSV — это текстовый табличный формат. Заголовок таблицы указывает поля. Это предпочтительный выбор, где сообщение содержит набор записей.

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

Буферы протокола (protobuf)

Protocol Buffers (или protobuf) — это формат сериализации, использующий строго типизированные файлы определения типов для определения схем в парах "ключ-значение". Затем эти файлы определения компилируются в классы, относящиеся к языку, которые используются для сериализации и десериализации сообщений.

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

Apache Avro

Apache Avro — это формат двоичной сериализации, который использует файл определения, аналогичный protobuf, но нет шага компиляции. Вместо этого сериализованные данные всегда включают предварительную схему.

Предварительная строка может содержать заголовок или идентификатор схемы. Из-за меньшего размера кодировки Avro рекомендуется для потоковых данных. Кроме того, поскольку он имеет заголовок, который применяется к набору записей, это хороший вариант для табличных данных.

Apache Parquet

Apache Parquet — это формат файла хранилища столбцов, который обычно связан с Apache Hadoop и связанными платформами обработки данных.

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

MessagePack

MessagePack — это формат двоичной сериализации, предназначенный для сжатия передачи по проводу. Нет схем сообщений или проверки типа сообщения. Этот формат не рекомендуется для массового хранения.

CBOR

краткое представление двоичного объекта (CBOR) (спецификация) — это двоичный формат, который предлагает небольшой размер кодировки. Преимущество CBOR над MessagePack заключается в том, что он соответствует IETF в RFC7049.

Дальнейшие действия