O componente TsgcGRPCClient traz o gRPC para o Delphi e o C++Builder sem nenhum runtime externo. Ele faz parte da edição Enterprise do sgcWebSockets e roda em Windows, macOS, Linux, iOS e Android. Este guia explica como o cliente funciona, como configurá-lo e como fazer cada um dos quatro tipos de chamada gRPC a partir do Delphi.
Como funciona
O gRPC são mensagens Protocol Buffers enquadradas sobre HTTP/2. Cada mensagem é enviada como um payload prefixado por tamanho em um stream HTTP/2, a requisição carrega headers como content-type: application/grpc e grpc-timeout, e o status final chega como os trailers grpc-status e grpc-message.
O sgcWebSockets já inclui uma pilha HTTP/2 completa, portanto o TsgcGRPCClient fica sobre um transporte TsgcHTTP2Client. Você fornece os bytes da requisição serializada, ele faz o enquadramento, os headers e o trabalho de timeout, abre o stream HTTP/2 e analisa a resposta e os trailers de volta em um TsgcGRPCResponse tipado. Como o cliente trabalha com TBytes brutos, você pode combiná-lo com qualquer biblioteca de Protocol Buffers que já utilize.
Configurando o cliente
Um canal gRPC é uma conexão HTTP/2. Crie um TsgcHTTP2Client, aponte-o para o host e a porta, e em seguida atribua-o à propriedade Client do componente gRPC. Para TLS, o cliente HTTP/2 usa OpenSSL ou o SChannel do Windows; para um servidor local em texto puro (h2c), defina TLS como False.
uses
sgcHTTP2, sgcGRPC_Client, sgcGRPC_Classes, sgcGRPC_Types;
var
HTTP2: TsgcHTTP2Client;
GRPC: TsgcGRPCClient;
begin
HTTP2 := TsgcHTTP2Client.Create(nil);
HTTP2.Host := 'grpc.example.com';
HTTP2.Port := 443;
HTTP2.TLS := True; // False for a local h2c server
HTTP2.TLSOptions.IOHandler := iohOpenSSL; // or iohSChannel on Windows
GRPC := TsgcGRPCClient.Create(nil);
GRPC.Client := HTTP2;
end;
Configurando o canal
As configurações que valem para todo o canal ficam em ChannelOptions. Você pode ativar a compressão gzip por mensagem, escolher o content type da transmissão e elevar os limites de tamanho de mensagem e de metadata.
// gzip-compress outgoing messages
GRPC.ChannelOptions.Compression := grpcGzip; // grpcNoCompression, grpcGzip, grpcDeflate, grpcSnappy
// application/grpc+proto (default) or application/grpc+json
GRPC.ChannelOptions.ContentType := grpcProto; // or grpcJSON
// raise the limits for large messages
GRPC.ChannelOptions.MaxMessageSize := 16 * 1024 * 1024;
GRPC.ChannelOptions.MaxMetadataSize := 64 * 1024;
Metadata e autenticação
Headers personalizados viajam como metadata do gRPC. Adicione-os a DefaultMetadata para enviá-los em todas as chamadas, que é o lugar habitual para um token de autorização ou um header de rastreamento.
GRPC.DefaultMetadata.Add('authorization', 'Bearer eyJ...');
GRPC.DefaultMetadata.Add('x-api-key', 'my-api-key');
Deadlines e cancelamento
Um timeout por chamada é enviado como o header padrão grpc-timeout, de modo que o servidor possa desistir no mesmo momento que o seu cliente. Uma chamada de streaming em andamento pode ser interrompida a qualquer momento com CancelCall, passando o id do stream retornado quando o stream foi aberto.
Chamadas unárias
Uma chamada unária envia uma requisição e recebe uma resposta. Call bloqueia até a resposta chegar e retorna um TsgcGRPCResponse com o StatusCode, o StatusMessage, os bytes brutos de Data (ou DataString) e os Trailers.
var
oResponse: TsgcGRPCResponse;
begin
oResponse := GRPC.Call('helloworld.Greeter', 'SayHello', RequestBytes);
if oResponse.StatusCode = grpcOK then
Memo1.Text := oResponse.DataString
else
ShowMessage('gRPC error ' + oResponse.StatusMessage);
end;
Para manter a interface responsiva, use CallAsync. Ele retorna de imediato e entrega a resposta por meio do evento OnGRPCResponse.
GRPC.OnGRPCResponse := GRPCResponse;
GRPC.CallAsync('helloworld.Greeter', 'SayHello', RequestBytes);
procedure TForm1.GRPCResponse(Sender: TObject; const Response: TsgcGRPCResponse);
begin
if Response.StatusCode = grpcOK then
Memo1.Text := Response.DataString;
end;
Server streaming
Com o server streaming você envia uma requisição e o servidor retorna um stream de mensagens. Cada mensagem dispara OnGRPCStreamMessage, e OnGRPCStreamEnd dispara uma vez com o status final.
GRPC.OnGRPCStreamMessage := GRPCStreamMessage;
GRPC.OnGRPCStreamEnd := GRPCStreamEnd;
GRPC.ServerStreamingCall('chat.Feed', 'Subscribe', RequestBytes);
procedure TForm1.GRPCStreamMessage(Sender: TObject; aStreamId: Integer;
const aData: TBytes);
begin
Memo1.Lines.Add(DecodeMessage(aData));
end;
Client streaming
O client streaming é a imagem espelhada: você envia um stream de mensagens e o servidor responde uma vez. Abra o stream, envie cada mensagem e em seguida feche-o para ler a resposta única.
var
vStreamId: Integer;
oResponse: TsgcGRPCResponse;
begin
vStreamId := GRPC.OpenClientStream('upload.Service', 'Send');
GRPC.SendStreamMessage(vStreamId, ChunkBytes1);
GRPC.SendStreamMessage(vStreamId, ChunkBytes2);
oResponse := GRPC.CloseClientStream(vStreamId);
if oResponse.StatusCode = grpcOK then
ShowMessage('Upload accepted');
end;
Streaming bidirecional
O streaming bidirecional executa uma troca full-duplex sobre um único stream HTTP/2: ambos os lados enviam quando quiserem. Abra o stream, envie mensagens conforme necessário, trate as mensagens recebidas em OnGRPCStreamMessage e feche ao terminar.
var
vStreamId: Integer;
begin
vStreamId := GRPC.OpenBidiStream('chat.Room', 'Connect');
GRPC.SendBidiMessage(vStreamId, EncodeMessage('hello'));
// ... incoming messages arrive on OnGRPCStreamMessage ...
GRPC.CloseBidiStream(vStreamId);
end;
Códigos de status e tratamento de erros
Toda resposta carrega um StatusCode tipado, de grpcOK ao longo do conjunto padrão do gRPC (grpcNOT_FOUND, grpcUNAVAILABLE, grpcDEADLINE_EXCEEDED, grpcUNAUTHENTICATED e os demais). Para chamadas assíncronas e de streaming, OnGRPCError reporta um status gRPC diferente de OK e OnGRPCException reporta uma falha de transporte ou de conexão.
GRPC.OnGRPCError := GRPCError;
procedure TForm1.GRPCError(Sender: TObject; aStreamId: Integer;
aStatusCode: TsgcGRPCStatusCode; const aStatusMessage: string);
begin
Memo1.Lines.Add(Format('gRPC error %d: %s', [Ord(aStatusCode), aStatusMessage]));
end;
Retry automático
O cliente pode repetir chamadas que falharam por você. Ative RetryPolicy, defina a quantidade de tentativas e o backoff, e liste os códigos de status que devem disparar um retry. Esta é a configuração típica para falhas transitórias de grpcUNAVAILABLE.
GRPC.RetryPolicy.Enabled := True;
GRPC.RetryPolicy.MaxAttempts := 4;
GRPC.RetryPolicy.InitialBackoff := 200; // ms
GRPC.RetryPolicy.BackoffMultiplier := 2.0;
GRPC.RetryPolicy.RetryableStatusCodes :=
GRPC.RetryPolicy.RetryableStatusCodes + [grpcUNAVAILABLE, grpcRESOURCE_EXHAUSTED];
Para lógica transversal, como logging ou renovação de um token, adicione uma entrada à cadeia de Interceptors, que envolve cada chamada em um único lugar.
Por onde seguir
Sobre este cliente genérico, o sgcWebSockets inclui clientes tipados para os serviços gRPC do Google Cloud (Pub/Sub, Speech-to-Text, Translation, Vision, Natural Language, Cloud Storage, BigQuery e Vertex AI), de modo que você chama métodos de alto nível em vez de montar protobufs manualmente. Um exemplo pronto para executar está em Demos\21.GRPC\01.GRPC_Client, e a referência completa está na página do produto Cliente gRPC.
Dúvidas ou ajuda para começar? Entre em contato. Você receberá uma resposta das pessoas que escreveram o código.
