úterý 22. července 2008

Protocol Buffers - binární protokol nejen pro RPC

Ta zpráva působí tak nevině a přitom vyvolává tolik kontroverze. Jedná se přesně o oznámení vypuštění projektu Protocol Buffers, což je ve své podstatě binární formát vyvinutý a používaný Googlem pro efektivní výměnu dat. Stop, pokud vás napadá nějaká z následujících otázek.

  • Jak binární formát?
  • Jak výměna dat?
  • K čemu tu sakra máme XML?
  • Je to zabiják XML?

Dobrá, to všechno jsou přesně diskusní témata, která ono oznámení vyvolalo. Jak se říká, nic není tak horké, jak se upeče. Takže pěkně po pořádku. Protocol Buffers (dále PB) vycházejí z požadavků na co nejefektivnější formát pro výměnu dat. Google potřebuje takový formát dat, který by se dal rychle serializovat/deserializovat a zároveň byl co nejšetrnější co do objemu řídících dat. Na základě tohoto požadavku se ihned vyřadilo XML.

Protocol buffers have many advantages over XML for serializing structured data. Protocol buffers:

  • are simpler
  • are 3 to 10 times smaller
  • are 20 to 100 times faster
  • are less ambiguous
generate data access classes that are easier to use programmatically

Samozřejmě přímo s binárním protocolem nepracují ani inženýři v Google. Proto je součástí PB i generátor objektové reprezentace. Práce s PB je následující:

  • Pomocí speciálního jazyku (protocol buffer language) popíšete strukturu vašich dat - vytvoříte schéma zprávy
  • Pustíte kompilátor pro váš oblíbený jazyk (Java, C++, Python, Perl, Haskell), který vám vygeneruje objektovou reprezentaci pro data (z pohledu Javy je to klasická Java beana - settry/gettry, která má navíc metodu pro serializaci a deserializaci do/z pole bajtů)
  • V kódu pak pracujete s již vygenerovanou reprezentací.

Jednoduchá ukázka, kterou jsem vytáhnul z Java tutoriálu PB.

Popis struktury dat

   
package tutorial;

option java_package = "com.example.tutorial";
option java_outer_classname = "AddressBookProtos";

message Person {
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;

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

  message PhoneNumber {
    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }

  repeated PhoneNumber phone = 4;
}
   
  

Práce v Jave

   
Person john =
    Person.newBuilder()
    .setId(1234)
    .setName("John Doe")
    .setEmail("jdoe@example.com")
    .addPhone(
      Person.PhoneNumber.newBuilder()
        .setNumber("555-4321")
        .setType(Person.PhoneType.HOME))
    .build();

//serializace    
FileOutputStream output = new FileOutputStream("john.dat");
john.writeTo(output);

//deserilizace
john = Person.parseFrom(new FileInputStream("john.dat"));
   
  

Jednoduché že? Google prozradil, že PB používá v RPC systems and for persistent storage of data in a variety of storage systems a že Protocol buffers are now Google's lingua franca for data – at time of writing, there are 48,162 different message types defined in the Google code tree across 12,183 .proto files (.proto soubory slouží pro popis struktury).

Právě zmíňka o RPC se stala velkým prubířským kamenem pro všechny XML věrozvěsty. Kde kdo to nechal Googlu pěkně sežrat. Každopádně jak to tak bývá, pointa je trochu někde jinde. To že PB využívá Google pro RPC neznamená, že vy to musíte dělat také. Pěkně to napsal Ted Newrd v článku So You Say You Want to Kill XML....

In the end, if you want an endpoint that is loosely coupled and offers the maximum flexibility, stick with XML, either wrapped in a SOAP envelope or in a RESTful envelope as dictated by the underlying transport (which means HTTP, since REST over anything else has never really been defined clearly by the Restafarians). If you need a binary format, then Protocol Buffers are certainly one answer... but so is ICE, or even CORBA (though this is fast losing its appeal thanks to the slow decline of the players in this space). Don't lose sight of the technical advantages or disadvantages of each of those solutions just because something has the Google name on it.

Mimochodem PB nejsou svého druhu jediným řešením, protože je tu ještě Thrift (již v Apache inkubátoru). Pro zajímavost dávám k dobru srovnání jejich vlastností.

Zdroje: v článku bylo hojně čerpáno z informací přímo či nepřímo získaných z Google Introduces Binary Encoding Format: Protocol Buffers.