El componente TsgcGRPCClient lleva gRPC a Delphi y C++Builder sin ningún runtime externo. Forma parte de la edición Enterprise de sgcWebSockets y se ejecuta en Windows, macOS, Linux, iOS y Android. Esta guía explica cómo funciona el cliente, cómo configurarlo y cómo realizar cada uno de los cuatro tipos de llamada gRPC desde Delphi.
Cómo funciona
gRPC son mensajes de Protocol Buffers enmarcados sobre HTTP/2. Cada mensaje se envía como una carga útil con prefijo de longitud en un stream HTTP/2, la solicitud lleva cabeceras como content-type: application/grpc y grpc-timeout, y el estado final llega como los trailers grpc-status y grpc-message.
sgcWebSockets ya incluye una pila HTTP/2 completa, por lo que TsgcGRPCClient se asienta sobre un transporte TsgcHTTP2Client. Le proporcionas los bytes de tu solicitud serializada, este se encarga del enmarcado, las cabeceras y el tiempo de espera, abre el stream HTTP/2 y analiza la respuesta y los trailers de vuelta en un TsgcGRPCResponse tipado. Como el cliente trabaja con TBytes en bruto, puedes combinarlo con cualquier librería de Protocol Buffers que ya utilices.
Configurar el cliente
Un canal gRPC es una conexión HTTP/2. Crea un TsgcHTTP2Client, apúntalo al host y al puerto, y luego asígnalo a la propiedad Client del componente gRPC. Para TLS, el cliente HTTP/2 usa OpenSSL o Windows SChannel; para un servidor local en texto plano (h2c), establece TLS en 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;
Configurar el canal
Los ajustes que afectan a todo el canal están en ChannelOptions. Puedes activar la compresión gzip por mensaje, elegir el tipo de contenido del protocolo y aumentar los límites de tamaño de mensaje y de metadatos.
// 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;
Metadatos y autenticación
Las cabeceras personalizadas viajan como metadatos de gRPC. Añádelas a DefaultMetadata para enviarlas en cada llamada, que es el lugar habitual para un token de autorización o una cabecera de trazado.
GRPC.DefaultMetadata.Add('authorization', 'Bearer eyJ...');
GRPC.DefaultMetadata.Add('x-api-key', 'my-api-key');
Plazos y cancelación
El tiempo de espera por llamada se envía como la cabecera estándar grpc-timeout, de modo que el servidor puede abandonar en el mismo momento que lo hace tu cliente. Una llamada de streaming en curso puede detenerse en cualquier momento con CancelCall, pasando el identificador de stream devuelto cuando se abrió el stream.
Llamadas unarias
Una llamada unaria envía una solicitud y obtiene una respuesta. Call se bloquea hasta que llega la respuesta y devuelve un TsgcGRPCResponse con el StatusCode, el StatusMessage, los bytes de Data en bruto (o DataString) y los 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 mantener la interfaz de usuario receptiva, usa CallAsync. Devuelve de inmediato y entrega la respuesta a través del 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;
Streaming de servidor
Con el streaming de servidor envías una solicitud y el servidor devuelve un stream de mensajes. Cada mensaje genera OnGRPCStreamMessage, y OnGRPCStreamEnd se dispara una vez con el estado 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;
Streaming de cliente
El streaming de cliente es la imagen reflejada: envías un stream de mensajes y el servidor responde una vez. Abre el stream, envía cada mensaje y luego ciérralo para leer la única respuesta.
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 bidireccional
El streaming bidireccional ejecuta un intercambio full-duplex sobre un único stream HTTP/2: ambos lados envían cuando quieren. Abre el stream, envía mensajes según sea necesario, gestiona los mensajes entrantes en OnGRPCStreamMessage y ciérralo al 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 estado y gestión de errores
Cada respuesta lleva un StatusCode tipado, desde grpcOK a través del conjunto estándar de gRPC (grpcNOT_FOUND, grpcUNAVAILABLE, grpcDEADLINE_EXCEEDED, grpcUNAUTHENTICATED y el resto). Para las llamadas asíncronas y de streaming, OnGRPCError informa de un estado gRPC distinto de OK y OnGRPCException informa de un fallo de transporte o de conexión.
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;
Reintento automático
El cliente puede reintentar por ti las llamadas fallidas. Habilita RetryPolicy, establece el número de intentos y el backoff, y enumera los códigos de estado que deben desencadenar un reintento. Esta es la configuración típica para fallos transitorios 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 el registro o la renovación de un token, añade una entrada a la cadena Interceptors, que envuelve cada llamada en un solo lugar.
Qué hacer a continuación
Sobre este cliente genérico, sgcWebSockets incluye clientes tipados para los servicios gRPC de Google Cloud (Pub/Sub, Speech-to-Text, Translation, Vision, Natural Language, Cloud Storage, BigQuery y Vertex AI), de modo que llamas a métodos de alto nivel en lugar de ensamblar protobufs a mano. Hay un ejemplo listo para ejecutar en Demos\21.GRPC\01.GRPC_Client, y la referencia completa está en la página del producto gRPC Client.
¿Preguntas o ayuda para empezar? Ponte en contacto. Recibirás una respuesta de las personas que escribieron el código.
