Что такое Protocol Buffers (protobuf)?

«Что такое Protocol Buffers (protobuf)?» — вопрос из категории Архитектура, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Protocol Buffers (protobuf) — это механизм сериализации структурированных данных от Google, ориентированный на высокую производительность и компактность. Это бинарный формат, используемый для межсервисного взаимодействия (особенно с gRPC) и хранения данных.

Ключевые преимущества:

  • Компактный размер: Бинарное кодирование значительно меньше текстовых форматов (JSON/XML).
  • Высокая скорость: Парсинг и сериализация очень быстры.
  • Строгая типизация и схема: Структура данных определяется в файле .proto, что исключает ошибки несоответствия типов.
  • Кросс-языковая поддержка: Генерация классов для Java, C++, Python, Go и многих других.
  • Обратная и прямая совместимость: Поля можно добавлять и делать опциональными, сохраняя совместимость старых и новых клиентов.

Пример схемы (person.proto):

syntax = "proto3";

package example;

message Person {
  string name = 1;          // Уникальный номер поля (tag)
  int32 id = 2;
  optional string email = 3; // Опциональное поле (proto3)
  repeated string phones = 4; // Поле-список

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    string number = 1;
    PhoneType type = 2;
  }

  repeated PhoneNumber phone_numbers = 5;
}

Использование в Java:

// Создание объекта
Person person = Person.newBuilder()
    .setId(1234)
    .setName("John Doe")
    .setEmail("jdoe@example.com")
    .addPhones("+7-123-456-7890")
    .addPhoneNumbers(
        Person.PhoneNumber.newBuilder()
            .setNumber("+1-234-567-8901")
            .setType(Person.PhoneType.WORK)
            .build()
    )
    .build();

// Сериализация в массив байт
byte[] data = person.toByteArray();

// Десериализация из массива байт
Person parsedPerson = Person.parseFrom(data);
System.out.println(parsedPerson.getName()); // John Doe

Типичное применение: Микросервисная архитектура (gRPC), конфигурационные файлы, высоконагруженные бэкенды, где критичны производительность и размер данных.