Qt GRPC Übersicht über Interceptoren
Übersicht über Interceptoren
Clientseitige Interceptoren bieten einen schlanken Mechanismus zur Implementierung von Verhalten, das konsistent über viele RPCs hinweg angewendet werden soll. Sie sind besonders nützlich für Querschnittsthemen, die unabhängig von einer bestimmten RPC-Methode sind, wie zum Beispiel:
- Verteilte Ablaufverfolgung
- Protokollierung
- Authentifizierung und Autorisierung
- Metriken und Beobachtbarkeit
- Durchsetzung von Richtlinien
- Clientseitiges Caching
- Fehlerinjektion
Interceptoren werden mithilfe eines „ QGrpcInterceptorChain “ auf einem Kanal installiert. Jeder Interceptor implementiert eine oder mehrere Interceptor-Schnittstellen (zum Beispiel „ QGrpcStartInterceptor “ und „ QGrpcFinishedInterceptor “). Der Kanal „ Qt GRPC “ ruft die entsprechende Schnittstelle auf, sobald diese Phase eines RPC erreicht ist, und stellt dabei den Kontext des aktuellen RPC bereit.
Interceptoren arbeiten auf der Ebene einzelner RPCs. Sie können Metadaten und Nutzdaten von Anfragen oder Antworten im Verlauf des RPCs überprüfen und ändern. Sie sind eher für die Implementierung von Verhalten pro Aufruf gedacht als für die Verwaltung von Kanal- oder Transportkonfigurationen.
Hinweis: Interceptoren in „ Qt GRPC “ werden auf einem Kanal installiert und gelten für alle über diesen Kanal durchgeführten RPCs. Die Interceptor-Kette wird bei der Erstellung festgelegt und kann danach nicht mehr geändert werden. Um das Interceptor-Verhalten zu ändern, erstellen Sie einen neuen Kanal mit einer anderen Interceptor-Kette.
Fähigkeiten und Hook-Punkte
Jede Interception-Schnittstelle stellt einen Hook-Punkt im Lebenszyklus eines RPC dar. Eine Interceptor-Klasse kann mithilfe von Mehrfachvererbung mehrere Schnittstellen implementieren.
Qt GRPC Ermittelt, welche Interception-Schnittstellen ein Interceptor implementiert, und macht diese als ` capabilities` zugänglich. ` Qt GRPC ` nutzt diese Fähigkeiten, um nur die tatsächlich implementierten Hooks zu versenden.
| Schnittstelle | Hook-Punkt | Richtung | Kann ändern |
|---|---|---|---|
| QGrpcStartInterceptor | Vor dem Start des RPC | Ausgehend | Ursprüngliches Nachrichtenobjekt, Aufrufoptionen |
| QGrpcWriteMessageInterceptor | Bevor eine ausgehende Nachricht geschrieben wird | Ausgehend | Nachrichtenobjekt |
| QGrpcWritesDoneInterceptor | Wenn der Client signalisiert, dass die Schreibvorgänge abgeschlossen sind | Ausgehend | — |
| QGrpcCancelInterceptor | Wenn der RPC abgebrochen wird | Ausgehend | — |
| QGrpcInitialMetadataInterceptor | Wenn die ersten Metadaten empfangen werden | Eingehend | Metadaten |
| QGrpcMessageReceivedInterceptor | Beim Empfang der Nutzdaten einer Nachricht | Eingehend | Serialisierte Nachrichtendaten |
| QGrpcTrailingMetadataInterceptor | Beim Empfang von nachgeschalteten Metadaten | Eingehend | Metadaten |
| QGrpcFinishedInterceptor | Wenn der RPC abgeschlossen ist | Eingehend | Endstatus |
Alle Callbacks erhalten ein ` QGrpcInterceptionContext`, das Informationen über den abgefangenen RPC bereitstellt, wie beispielsweise den ` RPC descriptor`, die ` channel ` oder die gültige ` callOptions `. Das Kontext-Objekt ist nur für die Dauer des Callbacks gültig und darf danach nicht mehr verwendet werden.
Hinweis: Halten Sie die Abfanglogik schlank und vermeiden Sie blockierende Operationen in Callbacks. Führen Sie rechenintensive Vorgänge (z. B. E/A oder Token-Aktualisierung) außerhalb des Callbacks durch und wenden Sie das Ergebnis erst im Hook an.
Richtung und Ablauf
Wenn mehrere Interceptoren verwendet werden, ist deren Reihenfolge von Bedeutung. Es ist hilfreich, sich die Interceptoren als in einer Reihe zwischen der Anwendung und dem Netzwerk angeordnet vorzustellen. Interceptoren, die in der Kette weiter vorne liegen, verarbeiten den RPC zuerst und können ihn möglicherweise ändern, bevor sie ihn an den nächsten Interceptor weitergeben. Interceptoren, die näher am Netzwerk liegen, haben die letzte Chance, zu beobachten oder anzupassen, was tatsächlich gesendet wird.
Interceptoren werden in einer festgelegten Reihenfolge zu einer „ QGrpcInterceptorChain “ hinzugefügt. „ QtGrpc “ durchläuft die Kette im Verlauf des RPC:
- Bei ausgehenden Phasen (Anwendung → Netzwerk) werden Callbacks in der Reihenfolge aufgerufen, in der die Interceptoren der Kette hinzugefügt wurden.
- Bei eingehenden Phasen (Netzwerk → Anwendung) werden die Callbacks in umgekehrter Reihenfolge aufgerufen, sodass der letzte Interceptor, der „dem Netzwerk am nächsten“ liegt, die eingehenden Daten als Erster sieht.

Ausgehende Phasen entsprechen vom Client initiierten Vorgängen, wie dem Senden einer Nachricht oder dem Abschluss einer Schreibsequenz (zum Beispiel writeMessage oder writesDone). Diese Ereignisse wandern von der Anwendung durch die Interceptor-Kette in Richtung Netzwerk.
Eingehende Phasen entsprechen von der RPC erzeugten Ereignissen, wie dem Empfang einer Nachricht oder dem Abschluss des Aufrufs (z. B. messageReceived oder finished). Diese Ereignisse wandern vom Netzwerk zurück durch die Interceptor-Kette in Richtung der Anwendung.
Eigentumsverhältnisse und Lebensdauer
QGrpcInterceptorChain unterstützt zwei primäre Lebensdauermodelle:
- Eigentümerschaft: Fügen Sie Interceptoren mit `
std::unique_ptr<T>()` hinzu. Bei Erfolg übernimmt die Kette die Eigentümerschaft und zerstört die Interceptoren, wenn die Kette (und damit der Kanal) zerstört wird. - Non-Owning: Fügen Sie Interceptoren mithilfe von Rohzeigern hinzu (
T*). Die Kette übernimmt keine Eigentümerschaft. Der Aufrufer muss sicherstellen, dass die Interceptor-Objekte so lange gültig bleiben, wie der Kanal sie aufrufen könnte.
Beide Modelle können auch innerhalb derselben Kette kombiniert werden. Die Kombination von Interceptoren mit und ohne Eigentumsübernahme wird zwar unterstützt, erfordert jedoch Sorgfalt, um sicherzustellen, dass Interceptoren ohne Eigentumsübernahme länger bestehen bleiben als alle Kanäle, die sie möglicherweise nutzen.
Interceptoren ohne Eigentumsübertragung können von mehreren Kanälen gemeinsam genutzt werden, indem dieselbe Interceptor-Instanz mehreren Ketten hinzugefügt wird. Dies ist nützlich für die gemeinsame Protokollierung oder die gemeinsame Erfassung von Metriken, erfordert jedoch eine sorgfältige Verwaltung der Lebensdauer und des parallelen Zugriffs.
Thread-Sicherheit und gemeinsam genutzter Zustand
Interceptor-Callbacks werden im Thread des Kanals ausgeführt, dem die Interceptor-Kette gehört.
Reentrante Interceptoren erfordern keine Synchronisation.
Eine Synchronisation ist nur erforderlich, wenn Interceptoren auf gemeinsam genutzte Daten zugreifen, die möglicherweise von mehreren Threads verwendet werden. Dies kann beispielsweise auftreten, wenn dieselbe Interceptor-Instanz von Kanälen verwendet wird, die in unterschiedlichen Threads laufen, oder wenn mehrere Interceptor-Instanzen auf dieselben gemeinsam genutzten Daten zugreifen.
Wenn auf gemeinsam genutzte Daten threadübergreifend zugegriffen werden muss, sollten Interceptor-Instanzen vorzugsweise threadlokal gehalten und die gemeinsam genutzten Daten in einem separat synchronisierten Objekt gespeichert werden.
struct SharedData
{
QReadWriteLock lock;
// shared data protected by lock
};
class MyInterceptor : public QGrpcStartInterceptor
{
public:
explicit MyInterceptor(std::shared_ptr<SharedData> data)
: m_sharedData(std::move(data)) {}
Continuation onStart(~~~) override; {
// access shared data here
}
private:
std::shared_ptr<SharedData> m_sharedData;
};
~~~
auto sharedData = std::make_shared<SharedData>();
bool ok = chain1.set(
std::make_unique<MyInterceptor>(sharedData),
std::make_unique<MyInterceptor>(sharedData)
);
// repeats for chain2
~~~
auto channelThread1 = std::make_shared<QGrpcHttp2Channel>(
QUrl("address:port"), std::move(chain1));
auto channelThread2 = std::make_shared<QGrpcHttp2Channel>(
QUrl("address:port"), std::move(chain2));© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.