OBSERVAÇÃO:este site foi descontinuado. O site será desativado após 31 de janeiro de 2023, e o tráfego será redirecionado para o novo site em https://protobuf.dev. Enquanto isso, as atualizações serão feitas apenas para protobuf.dev.

Visão geral

Mantenha tudo organizado com as coleções Salve e categorize o conteúdo com base nas suas preferências.

Os buffers de protocolo fornecem um mecanismo extensível que é neutro em relação à linguagem e à plataforma, para serializar dados estruturados de maneira compatível com versões futuras e versões anteriores. Ele é como JSON, mas é menor e mais rápido e gera vinculações de idioma nativo.

Buffers de protocolo são uma combinação da linguagem de definição (criada nos arquivos .proto), do código gerado pelo compilador proto para a interface com os dados, bibliotecas de execução de linguagens específicas e o formato de serialização para dados gravados em um arquivo (ou enviados por uma conexão de rede).

Quais problemas os buffers de protocolo resolvem?

Os buffers de protocolo fornecem um formato de serialização para pacotes de dados estruturados e digitados de até alguns megabytes de tamanho. O formato é adequado para tráfego de rede temporário e armazenamento de dados de longo prazo. Os buffers de protocolo podem ser estendidos com novas informações sem invalidar os dados existentes ou exigir que o código seja atualizado.

Os buffers de protocolo são o formato de dados mais usado no Google. Eles são usados extensivamente em comunicações entre servidores, bem como para arquivamento de dados em disco. As mensagens e os serviços do buffer de protocolo são descritos por arquivos .proto criados por engenheiros. Veja a seguir um exemplo de message:

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

O compilador proto é invocado no momento da compilação em arquivos .proto para gerar código em várias linguagens de programação, que serão abordadas em Compatibilidade entre linguagens mais adiante neste tópico, para manipular o buffer de protocolo correspondente. Cada classe gerada contém acessadores simples para cada campo e métodos para serializar e analisar toda a estrutura de e para bytes brutos. Veja abaixo um exemplo que usa esses métodos gerados:

Person john = Person.newBuilder()
    .setId(1234)
    .setName("John Doe")
    .setEmail("jdoe@example.com")
    .build();
output = new FileOutputStream(args[0]);
john.writeTo(output);

Como os buffers de protocolo são amplamente usados em todos os tipos de serviços no Google, os dados neles podem permanecer por algum tempo, e por isso, é essencial manter a compatibilidade com versões anteriores. Os buffers de protocolo permitem o suporte contínuo a mudanças, incluindo a adição de novos campos e a exclusão de campos existentes, para qualquer buffer de protocolo sem interromper os serviços atuais. Para saber mais sobre esse tópico, consulte Como atualizar definições proto sem atualizar o código.

Quais são os benefícios de usar buffers de protocolo?

Os buffers de protocolo são ideais para qualquer situação em que você precise serializar dados estruturados, semelhantes a registros, de maneira neutra em termos de linguagem, de plataforma e extensíveis. Eles são mais usados para definir protocolos de comunicação (junto com o gRPC) e para armazenamento de dados.

Algumas das vantagens de usar buffers de protocolo incluem:

  • Armazenamento de dados compacto
  • Análise rápida
  • Disponibilidade em muitas linguagens de programação
  • Funcionalidade otimizada por meio de classes geradas automaticamente

Compatibilidade entre linguagens

As mesmas mensagens podem ser lidas por código escrito em qualquer linguagem de programação compatível. É possível fazer com que um programa Java em uma plataforma capture dados de um sistema de software, serialize-o com base em uma definição .proto e extraia valores específicos desses dados serializados em um aplicativo Python separado em execução em outra plataforma.

As seguintes linguagens têm suporte direto no compilador de buffers de protocolo, o protoc:

As linguagens abaixo são aceitas pelo Google, mas o código-fonte dos projetos está nos repositórios do GitHub. O compilador protoc usa plug-ins para as seguintes linguagens:

Outras linguagens não são diretamente compatíveis com o Google, mas com outros projetos do GitHub. Esses idiomas são abordados em Complementos de terceiros para buffers de protocolo.

Suporte entre projetos

É possível usar buffers de protocolo entre projetos definindo tipos message em arquivos .proto que residem fora da base de código de um projeto específico. Se estiver definindo tipos message ou enumerações que você acha que vão ser amplamente usados fora da sua equipe imediata, é possível os colocar em um arquivo próprio sem dependências.

Alguns exemplos de definições de protótipos amplamente usados no Google são timestamp.proto e status.proto.

Como atualizar definições proto sem atualizar o código

Os produtos de software são compatíveis com versões anteriores, mas é menos comum que eles sejam compatíveis. Contanto que você siga algumas práticas simples ao atualizar as definições de .proto, o código antigo vai ler novas mensagens sem problemas, ignorando todos os campos recém-adicionados. Para o código antigo, os campos excluídos terão o valor padrão, e os campos repetidos excluídos ficarão vazios. Para informações sobre o que são campos "repetidos", consulte Sintaxe de definição de buffers de protocolo mais adiante neste tópico.

O novo código também vai ler as mensagens antigas de forma transparente. Novos campos não estarão presentes nas mensagens antigas. Nesses casos, os buffers de protocolo fornecem um valor padrão razoável.

Quando os buffers de protocolo não são adequados?

Os buffers de protocolo não se encaixam em todos os dados. Especificamente, faça o seguinte:

  • Os buffers de protocolo tendem a presumir que mensagens inteiras podem ser carregadas na memória de uma só vez e não são maiores que um gráfico de objetos. Para dados que excedem alguns megabytes, considere uma solução diferente. Ao trabalhar com dados maiores, é possível que você acabe tendo várias cópias dos dados devido às cópias serializadas, o que pode causar picos surpreendentes no uso da memória.
  • Quando os buffers de protocolo são serializados, os mesmos dados podem ter muitas serializações binárias diferentes. Não é possível comparar duas mensagens por igualdade sem analisá-las totalmente.
  • As mensagens não são compactadas. Embora as mensagens possam ser compactadas ou compactadas com gzip como qualquer outro arquivo, algoritmos de compactação com finalidade específica, como os usados por JPEG e PNG, produzirão arquivos muito menores para dados do tipo apropriado.
  • As mensagens de buffer de protocolo são menos eficientes tanto em tamanho quanto velocidade para muitos usos científicos e de engenharia que envolvem grandes matrizes multidimensionais com números de pontos flutuantes. Para esses aplicativos, os FITS e formatos semelhantes têm menos sobrecarga.
  • Os buffers de protocolo não são bem aceitos em linguagens não orientadas a objetos, conhecidas pela computação científica, como Fortran e IDL.
  • As mensagens do buffer de protocolo não descrevem automaticamente os dados deles, mas têm um esquema totalmente reflexivo que pode ser usado para implementar a autodescrição. Ou seja, não é possível interpretar totalmente um objeto sem acesso ao arquivo .proto correspondente.
  • Buffers de protocolo não são um padrão formal de nenhuma organização. Por isso, eles não são adequados para uso em ambientes com requisitos legais ou de outros tipos que são criados com base em padrões.

Quem usa buffers de protocolo?

Muitos projetos disponíveis externamente usam buffers de protocolo, incluindo:

Como os buffers de protocolo funcionam?

O diagrama a seguir mostra como usar buffers de protocolo para trabalhar com dados.


Figura 1. Fluxo de trabalho de buffers de protocolo

O código gerado por buffers de protocolo fornece métodos utilitários para recuperar dados de arquivos e streams, extrair valores individuais dos dados, verificar se existem, serializar dados de volta em um arquivo ou stream e outras funções úteis.

As amostras de código a seguir mostram um exemplo desse fluxo em Java. Conforme mostrado anteriormente, esta é uma definição de .proto:

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

A compilação desse arquivo .proto cria uma classe Builder que pode ser usada para criar novas instâncias, como no código Java a seguir:

Person john = Person.newBuilder()
    .setId(1234)
    .setName("John Doe")
    .setEmail("jdoe@example.com")
    .build();
output = new FileOutputStream(args[0]);
john.writeTo(output);

Em seguida, é possível desserializar dados usando os métodos de buffer de protocolo criados em outras linguagens, como C++:

Person john;
fstream input(argv[1], ios::in | ios::binary);
john.ParseFromIstream(&input);
int id = john.id();
std::string name = john.name();
std::string email = john.email();

Sintaxe de definição de buffers de protocolo

Ao definir arquivos .proto, é possível especificar que um campo seja optional ou repeated (proto2 e proto3) ou singular (proto3). A opção para definir um campo como required está ausente no proto3 e não é recomendado no proto2. Para saber mais sobre isso, consulte "Obrigatório para sempre" em Como especificar regras de campo.

Depois de definir a opcionalidade/repetição de um campo, especifique o tipo de dados. Os buffers de protocolo aceitam os tipos de dados primitivos comuns, como números inteiros, booleanos e flutuantes. Para ver a lista completa, consulte Tipos de valores de escalonamento.

Um campo também pode ser de:

  • Um tipo message, para que você possa aninhar partes da definição, como para repetir conjuntos de dados.
  • Um tipo enum, para que você possa especificar um conjunto de valores.
  • Um tipo oneof, que pode ser usado quando uma mensagem tem muitos campos opcionais e, no máximo, um campo será definido ao mesmo tempo.
  • Um tipo map para adicionar pares de chave-valor à definição.

No proto2, as mensagens podem permitir que extensões definam campos fora da própria mensagem. Por exemplo, o esquema de mensagens internas da biblioteca protobuf permite extensões para opções personalizadas e específicas do uso.

Para mais informações sobre as opções disponíveis, consulte o guia de linguagem de proto2 ou proto3.

Depois de definir a opcionalidade e o tipo de campo, atribua um número de campo. Os números de campo não podem ser reutilizados ou reutilizados. Se você excluir um campo, reserve o número dele para evitar que alguém o reutilize acidentalmente.

Suporte adicional a tipos de dados

Os buffers de protocolo aceitam muitos tipos de valores escalares, incluindo números inteiros que usam codificação de comprimento variável e tamanhos fixos. Também é possível criar seus próprios tipos de dados compostos definindo mensagens que, por sua vez, podem ser atribuídas a um campo. Além dos tipos de valor simples e composto, vários tipos comuns são publicados.

Tipos comuns

  • Duration é um período assinado de duração fixa, como 42 segundos.
  • Timestamp é um ponto no tempo independente de fusos horários ou agendas, como 2017-01-15T01:30:15.01Z.
  • Interval é um intervalo de tempo independente do fuso horário ou da agenda, como 2017-01-15T01:30:15.01Z - 2017-01-16T02:30:15.01Z.
  • Date é uma data inteira, como 19/09/2025.
  • DayOfWeek é um dia da semana, como segunda-feira.
  • TimeOfDay é uma hora do dia, como 10:42:23.
  • LatLng é um par de latitude/longitude, como 37,386051 e -122,083855.
  • Money é um valor com o tipo de moeda, como 42 BRL.
  • PostalAddress é um endereço postal, como 1600 Amphitheatre Parkway, Mountain View, CA 94043 EUA.
  • Color é uma cor no espaço de cores RGBA.
  • Month é um mês do ano, como abril.

Filosofia de código aberto de buffers de protocolo

Os buffers de protocolo foram de código aberto em 2008 como uma forma de fornecer aos desenvolvedores fora do Google os mesmos benefícios que temos para eles internamente. Apoiamos a comunidade de código aberto com atualizações regulares na linguagem à medida que fazemos essas mudanças para atender aos requisitos internos. Embora aceitemos solicitações de envio selecionadas de desenvolvedores externos, nem sempre podemos priorizar solicitações de recursos e correções de bugs que não estão em conformidade com as necessidades específicas do Google.

Outros recursos