Protocol Buffers ( Protobuf ) — это бесплатный и открытый кроссплатформенный формат данных, используемый для сериализации структурированных данных. Он полезен при разработке программ, которые взаимодействуют друг с другом по сети, или для хранения данных. Метод включает в себя язык описания интерфейса , который описывает структуру некоторых данных, и программу, которая генерирует исходный код из этого описания для генерации или анализа потока байтов, представляющего структурированные данные.
Компания Google разработала Protocol Buffers для внутреннего использования и предоставила генератор кода для нескольких языков по лицензии с открытым исходным кодом .
Цели проектирования Protocol Buffers подчеркивали простоту и производительность. В частности, он был разработан так, чтобы быть меньше и быстрее, чем XML . [3]
Protocol Buffers широко используется в Google для хранения и обмена всеми видами структурированной информации. Метод служит основой для пользовательской системы удаленного вызова процедур (RPC), которая используется почти для всех межмашинных коммуникаций в Google. [4]
Protocol Buffers похож на протоколы Apache Thrift , Ion и Microsoft Bond, предлагая конкретный стек протоколов RPC для использования в определенных службах , называемых gRPC . [5]
Схемы структур данных (называемые сообщениями ) и службы описаны в файле определения proto ( .proto
) и скомпилированы с помощью protoc
. Эта компиляция генерирует код, который может быть вызван отправителем или получателем этих структур данных. Например, example.pb.cc
и example.pb.h
генерируются из example.proto
. Они определяют классы C++ для каждого сообщения и службы в example.proto
.
Канонически сообщения сериализуются в двоичный формат проводов , который является компактным, совместимым вперед и назад , но не самоописываемым (то есть, нет способа определить имена, значение или полные типы данных полей без внешней спецификации). Не существует определенного способа включения или ссылки на такую внешнюю спецификацию (схему) в файле Protocol Buffers. Официально поддерживаемая реализация включает формат сериализации ASCII, [6] но этот формат — хотя и самоописываемый — теряет поведение прямой и обратной совместимости и, таким образом, не является хорошим выбором для приложений, отличных от редактирования и отладки человеком. [7]
Хотя основной целью буферов протоколов является обеспечение сетевой связи, их простота и скорость делают буферы протоколов альтернативой классам и структурам C++, ориентированным на данные, особенно там, где в будущем может потребоваться взаимодействие с другими языками или системами.
Protobuf не имеет единой спецификации. [8] Формат лучше всего подходит для небольших фрагментов данных, которые не превышают нескольких мегабайт и могут быть загружены/отправлены в память немедленно, поэтому не является потоковым форматом. [9] Библиотека не обеспечивает сжатие из коробки. Формат также не очень хорошо поддерживается в необъектно-ориентированных языках (например, Fortran ). [10]
Схема для конкретного использования буферов протокола связывает типы данных с именами полей, используя целые числа для идентификации каждого поля. (Данные буфера протокола содержат только числа, а не имена полей, что обеспечивает некоторую экономию полосы пропускания/хранилища по сравнению с системами, которые включают имена полей в данные.)
// синтаксис polyline.proto = "proto2" ; сообщение Point { обязательно int32 x = 1 ; обязательно int32 y = 2 ; необязательно строка label = 3 ; } Строка сообщения { обязательное начало точки = 1 ; обязательное окончание точки = 2 ; необязательная строковая метка = 3 ; } сообщение Полилиния { повторяющаяся точка точка = 1 ; необязательная строка метка = 2 ; }
Сообщение "Point" определяет два обязательных элемента данных, x и y . Метка элемента данных необязательна. Каждый элемент данных имеет тег. Тег определяется после знака равенства. Например, x имеет тег 1.
Сообщения "Line" и "Polyline", которые оба используют Point, демонстрируют, как композиция работает в Protocol Buffers. Polyline имеет повторяющееся поле, и поэтому Polyline ведет себя как набор точек (неопределенного количества).
Эта схема может быть впоследствии скомпилирована для использования одним или несколькими языками программирования. Google предоставляет компилятор protoc
, который может производить вывод для C++, Java или Python. Другие компиляторы схем доступны из других источников для создания зависящего от языка вывода для более чем 20 других языков. [11]
Например, после создания C++-версии схемы буфера протокола, приведенной выше, файл исходного кода C++, polyline.cpp, может использовать объекты сообщений следующим образом:
// polyline.cpp #include "polyline.pb.h" // сгенерировано путем вызова "protoc polyline.proto" Строка * createNewLine ( const std :: string & name ) { // создаем строку от (10, 20) до (30, 40) Строка * строка = new Строка ; строка -> mutable_start () -> set_x ( 10 ); строка -> mutable_start () -> set_y ( 20 ); строка -> mutable_end () -> set_x ( 30 ); строка -> mutable_end () -> set_y ( 40 ); строка -> set_label ( name ); return строка ; } Polyline * createNewPolyline () { // создаем полилинию с точками в точках (10,10) и (20,20) Polyline * polyline = new Polyline ; Point * point1 = polyline -> add_point (); point1 -> set_x ( 10 ); point1 -> set_y ( 10 ); Point * point2 = polyline -> add_point (); point2 -> set_x ( 20 ); point2 -> set_y ( 20 ); return polyline ; }
Protobuf 2.0 предоставляет генератор кода для C++ , Java , C# , [12] и Python . [13]
Protobuf 3.0 предоставляет генератор кода для C++ , Java (включая JavaNano, диалект, предназначенный для сред с низкими ресурсами ), Python , Go , Ruby , Objective-C , C# . [14] Он также поддерживает JavaScript, начиная с версии 3.0.0-beta-2. [15]
Также доступны сторонние реализации для Ballerina , [16] C , [17] [18] C++ , [19] Dart , Elixir , [20] [21] Erlang , [22] Haskell , [23] JavaScript , [24] Julia , [25] Nim , [26] Perl , PHP , Prolog , [27] [28] R , [29] Rust , [30] [31] [32] Scala , [33] и Swift . [34]