Sur cette page

Qt GRPC Présentation des intercepteurs

Présentation des intercepteurs

Les intercepteurs côté client offrent un mécanisme léger permettant de mettre en œuvre un comportement qui doit s'appliquer de manière cohérente à de nombreux appels RPC. Ils sont particulièrement utiles pour les préoccupations transversales indépendantes d'une méthode RPC spécifique, telles que :

  • Le traçage distribué
  • La journalisation
  • L'authentification et l'autorisation
  • Les métriques et l’observabilité
  • Application des politiques
  • Mise en cache côté client
  • Injection de défauts

Les intercepteurs sont installés sur un canal à l’aide d’une QGrpcInterceptorChain. Chaque intercepteur implémente une ou plusieurs interfaces d’intercepteur (par exemple QGrpcStartInterceptor et QGrpcFinishedInterceptor). Le canal Qt GRPC invoque l’interface correspondante chaque fois que cette étape d’un RPC est atteinte, en fournissant le contexte du RPC en cours.

Les intercepteurs opèrent au niveau des RPC individuels. Ils peuvent inspecter et modifier les métadonnées et les charges utiles des requêtes ou des réponses au fur et à mesure que le RPC progresse. Ils sont destinés à implémenter un comportement spécifique à chaque appel plutôt qu’à gérer la configuration du canal ou du transport.

Remarque : dans « Qt GRPC »,les intercepteurs sont installés sur un canal et s’appliquent à tous les RPC effectués via ce canal. La chaîne d’intercepteurs est fixée au moment de la construction et ne peut plus être modifiée par la suite. Pour modifier le comportement d’interception, créez un nouveau canal avec une chaîne d’intercepteurs différente.

Capacités et points d’accrochage

Chaque interface d’interception représente un point de raccordement au cours du cycle de vie du RPC. Une classe d’intercepteur peut implémenter plusieurs interfaces en utilisant l’héritage multiple.

Qt GRPC détecte les interfaces d’interception qu’un intercepteur implémente et les expose sous la forme d’ capabilities. Qt GRPC utilise ces capacités pour ne déclencher que les points d’accrochage qui sont effectivement implémentés.

InterfacePoint d’accrochageDirectionPeut modifier
QGrpcStartInterceptorAvant le lancement de l’appel RPCSortantObjet de message initial, options d'appel
QGrpcWriteMessageInterceptorAvant l'écriture d'un message sortantSortantObjet message
QGrpcWritesDoneInterceptorLorsque le client indique que les écritures sont terminéesSortant—
QGrpcCancelInterceptorLorsque le RPC est annuléSortant—
QGrpcInitialMetadataInterceptorÀ la réception des métadonnées initialesEntrantMétadonnées
QGrpcMessageReceivedInterceptorLors de la réception du contenu d’un messageEntrantDonnées de message sérialisées
QGrpcTrailingMetadataInterceptorÀ la réception des métadonnées de fin de messageEntrantMétadonnées
QGrpcFinishedInterceptorLorsque l'appel RPC est terminéEntrantStatut final

Tous les callbacks reçoivent un objet ` QGrpcInterceptionContext`, qui fournit des informations sur le RPC intercepté, telles que l’ RPC descriptor, l’ channel ou l’ callOptions en vigueur. L’objet `context` n’est valable que pendant la durée du callback et ne doit pas être utilisé par la suite.

Remarque : veillez à ce que la logique d’interceptionreste légère et évitez les opérations bloquantes dans les callbacks. Effectuez les tâches lentes (par exemple, les E/S ou l’actualisation des jetons) en dehors du callback et n’appliquez le résultat que dans le hook.

Direction et flux

Lorsque plusieurs intercepteurs sont utilisés, leur ordre est important. Il est utile de considérer les intercepteurs comme alignés entre l’application et le réseau. Les intercepteurs situés en amont dans la chaîne traitent d’abord le RPC et peuvent le modifier avant de le transmettre à l’intercepteur suivant. Les intercepteurs plus proches du réseau ont la dernière chance d’observer ou d’ajuster ce qui est effectivement envoyé.

Les intercepteurs sont ajoutés à une « QGrpcInterceptorChain » dans un ordre défini. QtGrpc parcourt la chaîne au fur et à mesure que le RPC circule :

  • Pour les étapes sortantes (application → réseau), les callbacks sont appelés dans l’ordre dans lequel les intercepteurs ont été ajoutés à la chaîne.
  • Pour les étapes entrantes (réseau → application), les callbacks sont appelés dans l’ordre inverse, de sorte que le dernier intercepteur, « le plus proche du réseau », voie en premier les données entrantes.

Deux schémas illustrant les directions des intercepteurs sortants et entrants

Les étapes sortantes correspondent aux opérations initiées par le client, telles que l’envoi d’un message ou la finalisation d’une séquence d’écriture (par exemple, writeMessage ou writesDone). Ces événements transitent de l’application vers le réseau en passant par la chaîne d’intercepteurs.

Les étapes entrantes correspondent aux événements générés par le RPC, tels que la réception d’un message ou la fin d’un appel (par exemple, messageReceived ou finished). Ces événements transitent du réseau vers l’application en passant par la chaîne d’intercepteurs.

Propriété et durée de vie

QGrpcInterceptorChain prend en charge deux modèles de durée de vie principaux :

  • Propriétaire: ajoutez des intercepteurs à l’aide de ` std::unique_ptr<T>()`. En cas de réussite, la chaîne en prend la propriété et détruit les intercepteurs lorsque la chaîne (et donc le canal) est détruite.
  • Non-owning: ajoutez des intercepteurs à l’aide de pointeurs bruts T*. La chaîne n’en prend pas la propriété. L’appelant doit s’assurer que les objets intercepteurs restent valides aussi longtemps que le canal est susceptible de les invoquer.

Ces deux modèles peuvent également être combinés au sein d’une même chaîne. Bien que cela soit pris en charge, le mélange d’intercepteurs avec prise en charge de la propriété et sans prise en charge de la propriété nécessite une attention particulière afin de garantir que les intercepteurs sans prise en charge de la propriété survivent à tous les canaux susceptibles de les utiliser.

Les intercepteurs sans propriété peuvent être partagés entre plusieurs canaux en ajoutant la même instance d’intercepteur à plusieurs chaînes. Cela s’avère utile pour la journalisation partagée ou la collecte partagée de métriques, mais nécessite une gestion rigoureuse de la durée de vie et des accès simultanés.

Sécurité inter-threads et état partagé

Les callbacks des intercepteurs s’exécutent dans le thread du canal propriétaire de la chaîne d’intercepteurs.

Les intercepteurs réentrants ne nécessitent aucune synchronisation.

La synchronisation n’est nécessaire que lorsque les intercepteurs accèdent à des données partagées susceptibles d’être utilisées par plusieurs threads. Cela peut se produire, par exemple, lorsqu’une même instance d’intercepteur est utilisée par des canaux résidant dans des threads différents, ou lorsque plusieurs instances d’intercepteur accèdent aux mêmes données partagées.

Lorsque des données partagées doivent être accessibles entre différents threads, privilégiez le fait de garder les instances d’intercepteurs locales au thread et de stocker les données partagées dans un objet synchronisé séparément.

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.