Методики

Описывает некоторые часто используемые шаблоны проектирования для работы с Protocol Buffers.

Вы также можете отправлять вопросы по проектированию и использованию в группу обсуждения Protocol Buffers.

Общие суффиксы имен файлов

Довольно часто сообщения записываются в файлы в нескольких различных форматах. Мы рекомендуем использовать следующие расширения файлов для этих файлов.

СодержимоеРасширение
Текстовый формат.txtpb
Формат передачи (Wire).binpb
Формат JSON.json

Для Текстового формата конкретно .textproto также довольно распространено, но мы рекомендуем .txtpb за его краткость.

Потоковая передача нескольких сообщений

Если вы хотите записать несколько сообщений в один файл или поток, вам нужно самостоятельно отслеживать, где заканчивается одно сообщение и начинается следующее. Формат передачи Protocol Buffer не является самодостотаточным (self-delimiting), поэтому парсеры protocol buffer не могут определить, где сообщение заканчивается, самостоятельно. Самый простой способ решить эту проблему - записать размер каждого сообщения перед записью самого сообщения. Когда вы читаете сообщения обратно, вы читаете размер, затем читаете байты в отдельный буфер, затем разбираете из этого буфера. (Если вы хотите избежать копирования байтов в отдельный буфер, ознакомьтесь с классом CodedInputStream (в C++ и Java), которому можно указать ограничить чтение определенным количеством байтов.)

Большие наборы данных

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

Тем не менее, Protocol Buffers отлично подходят для обработки отдельных сообщений внутри большого набора данных. Обычно большие наборы данных представляют собой коллекцию небольших частей, где каждая маленькая часть - это структурированные данные. Хотя Protocol Buffers не могут обработать весь набор сразу, использование Protocol Buffers для кодирования каждой части значительно упрощает вашу проблему: теперь все, что вам нужно, - это обработать набор байтовых строк, а не набор структур.

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

Самоописывающиеся сообщения

Protocol Buffers не содержат описаний своих собственных типов. Таким образом, имея только сырое сообщение без соответствующего файла .proto, определяющего его тип, трудно извлечь какие-либо полезные данные.

Однако содержимое файла .proto само может быть представлено с использованием protocol buffers. Файл src/google/protobuf/descriptor.proto в пакете исходного кода определяет involved типы сообщений. protoc может вывести FileDescriptorSet— который представляет набор файлов .proto — используя опцию --descriptor_set_out. С этим вы можете определить самоописывающееся сообщение protocol следующим образом:

syntax = "proto3";

import "google/protobuf/any.proto";
import "google/protobuf/descriptor.proto";

message SelfDescribingMessage {
  // Набор FileDescriptorProtos, которые описывают тип и его зависимости.
  google.protobuf.FileDescriptorSet descriptor_set = 1;

  // Сообщение и его тип, закодированные как сообщение Any.
  google.protobuf.Any message = 2;
}

Используя такие классы, как DynamicMessage (доступный в C++ и Java), вы можете затем писать инструменты, которые могут манипулировать SelfDescribingMessage.

При всем этом, причина, по которой эта функциональность не включена в библиотеку Protocol Buffer, заключается в том, что у нас внутри Google никогда не было необходимости в ней.

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