Le composant TsgcGRPCClient apporte gRPC à Delphi et C++Builder sans aucun runtime externe. Il fait partie de l'édition sgcWebSockets Enterprise et fonctionne sur Windows, macOS, Linux, iOS et Android. Ce guide explique comment le client fonctionne, comment le configurer et comment effectuer chacun des quatre types d'appels gRPC depuis Delphi.
Comment ça fonctionne
gRPC, ce sont des messages Protocol Buffers encadrés sur HTTP/2. Chaque message est envoyé sous forme de charge utile préfixée par sa longueur sur un flux HTTP/2, la requête transporte des en-têtes tels que content-type: application/grpc et grpc-timeout, et le statut final arrive sous forme des trailers grpc-status et grpc-message.
sgcWebSockets embarque déjà une pile HTTP/2 complète, donc TsgcGRPCClient repose sur un transport TsgcHTTP2Client. Vous lui fournissez les octets de votre requête sérialisée, il se charge de l'encadrement, des en-têtes et du timeout, ouvre le flux HTTP/2, et analyse la réponse et les trailers pour produire une TsgcGRPCResponse typée. Comme le client travaille avec des TBytes bruts, vous pouvez l'associer à n'importe quelle bibliothèque Protocol Buffers que vous utilisez déjà.
Mise en place du client
Un canal gRPC est une connexion HTTP/2. Créez un TsgcHTTP2Client, dirigez-le vers l'hôte et le port, puis affectez-le à la propriété Client du composant gRPC. Pour TLS, le client HTTP/2 utilise OpenSSL ou Windows SChannel ; pour un serveur local en clair (h2c), réglez TLS sur 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;
Configuration du canal
Les paramètres applicables à l'ensemble du canal se trouvent dans ChannelOptions. Vous pouvez activer la compression gzip par message, choisir le type de contenu transmis, et augmenter les limites de taille des messages et des métadonnées.
// 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;
Métadonnées et authentification
Les en-têtes personnalisés circulent en tant que métadonnées gRPC. Ajoutez-les à DefaultMetadata pour les envoyer à chaque appel, ce qui est l'endroit habituel pour un jeton d'autorisation ou un en-tête de traçage.
GRPC.DefaultMetadata.Add('authorization', 'Bearer eyJ...');
GRPC.DefaultMetadata.Add('x-api-key', 'my-api-key');
Délais et annulation
Un timeout par appel est envoyé sous forme de l'en-tête standard grpc-timeout, afin que le serveur puisse abandonner au même moment que votre client. Un appel en streaming en cours peut être arrêté à tout moment avec CancelCall, en passant l'identifiant du flux retourné lors de son ouverture.
Appels unaires
Un appel unaire envoie une requête et reçoit une réponse. Call bloque jusqu'à l'arrivée de la réponse et retourne une TsgcGRPCResponse avec le StatusCode, le StatusMessage, les octets bruts Data (ou DataString) et les 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;
Pour garder l'interface réactive, utilisez CallAsync. Elle retourne immédiatement et livre la réponse via l'événement 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 serveur
Avec le streaming serveur, vous envoyez une requête et le serveur retourne un flux de messages. Chaque message déclenche OnGRPCStreamMessage, et OnGRPCStreamEnd se déclenche une fois avec le statut 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 client
Le streaming client est l'image miroir : vous poussez un flux de messages et le serveur répond une seule fois. Ouvrez le flux, envoyez chaque message, puis fermez-le pour lire la réponse unique.
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 bidirectionnel
Le streaming bidirectionnel exécute un échange en duplex intégral sur un unique flux HTTP/2 : les deux côtés envoient quand ils le souhaitent. Ouvrez le flux, envoyez des messages selon vos besoins, traitez les messages entrants dans OnGRPCStreamMessage, et fermez une fois terminé.
var
vStreamId: Integer;
begin
vStreamId := GRPC.OpenBidiStream('chat.Room', 'Connect');
GRPC.SendBidiMessage(vStreamId, EncodeMessage('hello'));
// ... incoming messages arrive on OnGRPCStreamMessage ...
GRPC.CloseBidiStream(vStreamId);
end;
Codes de statut et gestion des erreurs
Chaque réponse transporte un StatusCode typé, de grpcOK à l'ensemble standard gRPC (grpcNOT_FOUND, grpcUNAVAILABLE, grpcDEADLINE_EXCEEDED, grpcUNAUTHENTICATED et les autres). Pour les appels asynchrones et en streaming, OnGRPCError signale un statut gRPC non-OK et OnGRPCException signale une défaillance de transport ou de connexion.
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;
Nouvelle tentative automatique
Le client peut réessayer les appels échoués à votre place. Activez RetryPolicy, définissez le nombre de tentatives et le backoff, et listez les codes de statut qui doivent déclencher une nouvelle tentative. C'est la configuration typique pour les défaillances grpcUNAVAILABLE transitoires.
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];
Pour une logique transversale telle que la journalisation ou le renouvellement d'un jeton, ajoutez une entrée à la chaîne Interceptors, qui enveloppe chaque appel en un seul endroit.
Pour aller plus loin
Au-dessus de ce client générique, sgcWebSockets fournit des clients typés pour les services gRPC de Google Cloud (Pub/Sub, Speech-to-Text, Translation, Vision, Natural Language, Cloud Storage, BigQuery et Vertex AI), de sorte que vous appelez des méthodes de haut niveau au lieu d'assembler des protobufs à la main. Un exemple prêt à l'emploi se trouve dans Demos\21.GRPC\01.GRPC_Client, et la référence complète est sur la page produit du client gRPC.
Des questions ou besoin d'aide pour démarrer ? Contactez-nous. Vous obtiendrez une réponse des personnes qui ont écrit le code.
