Die Komponente TsgcGRPCClient bringt gRPC nach Delphi und C++Builder, ganz ohne externe Laufzeitumgebung. Sie ist Teil der sgcWebSockets Enterprise Edition und läuft unter Windows, macOS, Linux, iOS und Android. Diese Anleitung erklärt, wie der Client funktioniert, wie Sie ihn konfigurieren und wie Sie jeden der vier gRPC-Aufruftypen aus Delphi heraus durchführen.
So funktioniert es
gRPC sind Protocol-Buffers-Nachrichten, die über HTTP/2 gerahmt werden. Jede Nachricht wird als längen-präfigierte Nutzlast auf einem HTTP/2-Stream gesendet, die Anfrage trägt Header wie content-type: application/grpc und grpc-timeout, und der endgültige Status kommt als Trailer grpc-status und grpc-message an.
sgcWebSockets liefert bereits einen vollständigen HTTP/2-Stack mit, sodass TsgcGRPCClient auf einem TsgcHTTP2Client-Transport aufsetzt. Sie übergeben ihm Ihre serialisierten Anfrage-Bytes, er übernimmt das Framing, die Header- und Timeout-Arbeit, öffnet den HTTP/2-Stream und parst die Antwort und die Trailer zurück in eine typisierte TsgcGRPCResponse. Da der Client mit rohen TBytes arbeitet, können Sie ihn mit jeder Protocol-Buffers-Bibliothek kombinieren, die Sie bereits verwenden.
Den Client einrichten
Ein gRPC-Channel ist eine HTTP/2-Verbindung. Erstellen Sie einen TsgcHTTP2Client, richten Sie ihn auf Host und Port aus und weisen Sie ihn dann der Eigenschaft Client der gRPC-Komponente zu. Für TLS verwendet der HTTP/2-Client OpenSSL oder Windows SChannel; für einen lokalen Klartext-Server (h2c) setzen Sie TLS auf 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;
Den Channel konfigurieren
Channelweite Einstellungen befinden sich in ChannelOptions. Sie können die gzip-Komprimierung pro Nachricht aktivieren, den Wire-Content-Type wählen und die Größenlimits für Nachrichten und Metadaten anheben.
// 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;
Metadaten und Authentifizierung
Benutzerdefinierte Header werden als gRPC-Metadaten übertragen. Fügen Sie sie zu DefaultMetadata hinzu, um sie bei jedem Aufruf zu senden, was der übliche Ort für ein Autorisierungstoken oder einen Tracing-Header ist.
GRPC.DefaultMetadata.Add('authorization', 'Bearer eyJ...');
GRPC.DefaultMetadata.Add('x-api-key', 'my-api-key');
Deadlines und Abbruch
Ein Timeout pro Aufruf wird als der standardmäßige grpc-timeout-Header gesendet, sodass der Server im selben Moment aufgeben kann wie Ihr Client. Ein laufender Streaming-Aufruf kann jederzeit mit CancelCall gestoppt werden, indem Sie die Stream-ID übergeben, die beim Öffnen des Streams zurückgegeben wurde.
Unary-Aufrufe
Ein Unary-Aufruf sendet eine Anfrage und erhält eine Antwort. Call blockiert, bis die Antwort eintrifft, und gibt eine TsgcGRPCResponse mit dem StatusCode, der StatusMessage, den rohen Data-Bytes (oder DataString) und den Trailers zurück.
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;
Um die Benutzeroberfläche reaktionsfähig zu halten, verwenden Sie CallAsync. Es kehrt sofort zurück und liefert die Antwort über das Ereignis 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
Beim Server-Streaming senden Sie eine Anfrage und der Server gibt einen Strom von Nachrichten zurück. Jede Nachricht löst OnGRPCStreamMessage aus, und OnGRPCStreamEnd wird einmal mit dem endgültigen Status ausgelöst.
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
Client-Streaming ist das Spiegelbild: Sie senden einen Strom von Nachrichten und der Server antwortet einmal. Öffnen Sie den Stream, senden Sie jede Nachricht und schließen Sie ihn dann, um die einzelne Antwort zu lesen.
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;
Bidirektionales Streaming
Bidirektionales Streaming führt einen Vollduplex-Austausch über einen einzigen HTTP/2-Stream aus: beide Seiten senden, wann immer sie möchten. Öffnen Sie den Stream, senden Sie Nachrichten nach Bedarf, verarbeiten Sie eingehende Nachrichten in OnGRPCStreamMessage und schließen Sie ihn, wenn Sie fertig sind.
var
vStreamId: Integer;
begin
vStreamId := GRPC.OpenBidiStream('chat.Room', 'Connect');
GRPC.SendBidiMessage(vStreamId, EncodeMessage('hello'));
// ... incoming messages arrive on OnGRPCStreamMessage ...
GRPC.CloseBidiStream(vStreamId);
end;
Statuscodes und Fehlerbehandlung
Jede Antwort trägt einen typisierten StatusCode von grpcOK über das standardmäßige gRPC-Set (grpcNOT_FOUND, grpcUNAVAILABLE, grpcDEADLINE_EXCEEDED, grpcUNAUTHENTICATED und den Rest). Bei asynchronen und Streaming-Aufrufen meldet OnGRPCError einen gRPC-Status ungleich OK und OnGRPCException meldet einen Transport- oder Verbindungsfehler.
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;
Automatischer Retry
Der Client kann fehlgeschlagene Aufrufe für Sie wiederholen. Aktivieren Sie RetryPolicy, legen Sie die Anzahl der Versuche und das Backoff fest und listen Sie die Statuscodes auf, die einen Retry auslösen sollen. Dies ist die typische Konfiguration für vorübergehende grpcUNAVAILABLE-Fehler.
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];
Für übergreifende Logik wie Protokollierung oder das Aktualisieren eines Tokens fügen Sie einen Eintrag zur Interceptors-Kette hinzu, die jeden Aufruf an einer Stelle umschließt.
Wie es weitergeht
Aufbauend auf diesem generischen Client liefert sgcWebSockets typisierte Clients für die gRPC-Dienste von Google Cloud (Pub/Sub, Speech-to-Text, Translation, Vision, Natural Language, Cloud Storage, BigQuery und Vertex AI) mit, sodass Sie hochrangige Methoden aufrufen, anstatt Protobufs von Hand zusammenzubauen. Ein lauffähiges Beispiel finden Sie unter Demos\21.GRPC\01.GRPC_Client, und die vollständige Referenz finden Sie auf der gRPC-Client-Produktseite.
Fragen oder Hilfe beim Einstieg? Kontaktieren Sie uns. Sie erhalten eine Antwort von den Leuten, die den Code geschrieben haben.
