Transcodage JSON gRPC dans ASP.NET Core

Par James Newton-King

gRPC est un framework d’appel de procédure distante (RPC) très performant. gRPC utilise HTTP/2, la diffusion en continu, Protobuf et les contrats de message pour créer des services en temps réel hautes performances.

L’une des limitations de gRPC est que toutes les plateformes ne peuvent pas l’utiliser. Les navigateurs ne prennent pas entièrement en charge HTTP/2, ce qui fait des API REST et de JSON le moyen principal d’obtenir des données dans des applications de navigateur. Malgré les avantages qu’apporte gRPC, les API REST et JSON ont une place importante dans les applications modernes. La création d’API web gRPC etJSON ajoute une surcharge indésirable au développement d’applications.

Ce document explique comment créer des API web JSON à l’aide des services gRPC.

Vue d’ensemble

le transcodage JSON gRPC est une extension pour ASP.NET Core qui crée des API RESTful JSON pour les services gRPC. Une fois configuré, le transcodage permet aux applications d’appeler des services gRPC avec des concepts HTTP familiers :

  • Verbes HTTP
  • Liaison de paramètre d’URL
  • Requêtes/réponses JSON

gRPC peut toujours être utilisé pour appeler des services.

Notes

Le transcodage JSON gRPC remplace l’API HTTP gRPC, une extension expérimentale alternative.

Usage

  1. Ajoutez une référence de package à Microsoft.AspNetCore.Grpc.JsonTranscoding.

  2. Inscrivez le transcodage dans le code de démarrage du serveur en ajoutant AddJsonTranscoding : Dans le fichier Program.cs, remplacez builder.Services.AddGrpc(); par builder.Services.AddGrpc().AddJsonTranscoding();.

  3. Ajoutez <IncludeHttpRuleProtos>true</IncludeHttpRuleProtos> au groupe de propriétés dans le fichier projet (.csproj) :

    <Project Sdk="Microsoft.NET.Sdk.Web">
    
      <PropertyGroup>
        <TargetFramework>net8.0</TargetFramework>
        <Nullable>enable</Nullable>
        <ImplicitUsings>enable</ImplicitUsings>
        <InvariantGlobalization>true</InvariantGlobalization>
        <IncludeHttpRuleProtos>true</IncludeHttpRuleProtos>
      </PropertyGroup>
    
  4. Annotez les méthodes gRPC dans vos fichiers .proto avec des liaisons et des itinéraires HTTP :

    syntax = "proto3";
    
    option csharp_namespace = "GrpcServiceTranscoding";
    import "google/api/annotations.proto";
    
    package greet;
    
    // The greeting service definition.
    service Greeter {
      rpc SayHello (HelloRequest) returns (HelloReply) {
        option (google.api.http) = {
          get: "/v1/greeter/{name}"
        };
      }
    }
    
    // The request message containing the user's name.
    message HelloRequest {
      string name = 1;
    }
    
    // The response message containing the greetings.
    message HelloReply {
      string message = 1;
    }
    

La méthode gRPC SayHello peut maintenant être appelée en tant que gRPC et en tant qu’API web JSON :

  • Demande : GET /v1/greeter/world
  • Réponse : { "message": "Hello world" }

Si le serveur est configuré pour écrire des journaux pour chaque requête, les journaux du serveur indiquent qu’un service gRPC exécute l’appel HTTP. Le transcodage mappe la requête HTTP entrante à un message gRPC et convertit le message de réponse en JSON.

info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET https://localhost:5001/v1/greeter/world
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint 'gRPC - /v1/greeter/{name}'
info: Server.GreeterService[0]
      Sending hello to world
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint 'gRPC - /v1/greeter/{name}'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 1.996ms 200 application/json

Annoter les méthodes gRPC

Les méthodes gRPC doivent être annotées avec une règle HTTP avant de prendre en charge le transcodage. La règle HTTP inclut des informations sur l’appel de la méthode gRPC, comme la méthode HTTP et l’itinéraire.

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {
    option (google.api.http) = {
      get: "/v1/greeter/{name}"
    };
  }
}

L’exemple suivant :

  • Définit un service Greeter avec une méthode SayHello. La méthode a une règle HTTP spécifiée avec le nom google.api.http.
  • La méthode est accessible avec les requêtes GET et l’itinéraire /v1/greeter/{name}.
  • Le champ name du message de requête est lié à un paramètre de routage.

De nombreuses options sont disponibles pour personnaliser la façon dont une méthode gRPC est liée à une API RESTful. Pour plus d’informations sur l’annotation des méthodes gRPC et la personnalisation de JSON, consultez Configurer HTTP et JSON pour le transcodage JSON gRPC.

Méthodes de diffusion en continu

gRPC sur HTTP/2 traditionnel prend en charge la diffusion en continu dans toutes les directions. Le transcodage est limité à la diffusion en continu de serveur uniquement. Les méthodes de diffusion en continu client et de diffusion en continu bidirectionnelle ne sont pas prises en charge.

Les méthodes de diffusion en continu de serveur utilisent du JSON délimité par ligne. Chaque message écrit avec WriteAsync est sérialisé en JSON et suivi d’une nouvelle ligne.

La méthode de diffusion en continu de serveur suivante écrit trois messages :

public override async Task StreamingFromServer(ExampleRequest request,
    IServerStreamWriter<ExampleResponse> responseStream, ServerCallContext context)
{
    for (var i = 1; i <= 3; i++)
    {
        await responseStream.WriteAsync(new ExampleResponse { Text = $"Message {i}" });
        await Task.Delay(TimeSpan.FromSeconds(1));
    }
}

Le client reçoit trois objets JSON délimités par une ligne :

{"Text":"Message 1"}
{"Text":"Message 2"}
{"Text":"Message 3"}

Notez que le paramètre WriteIndentedJSON ne s’applique pas aux méthodes de diffusion en continu du serveur. L’impression en mode Pretty ajoute de nouvelles lignes et des espaces blancs au JSON, ce qui ne peut pas être utilisé avec du JSON délimité par ligne.

Affichez ou téléchargez un exemple d’application de transcodage et de diffusion en continu ASP.NET Core gPRC.

Protocole HTTP

Le modèle de services ASP.NET Core gRPC, inclus dans le kit SDK .NET, crée une application configurée uniquement pour HTTP/2. HTTP/2 est un bon choix par défaut lorsqu’une application prend uniquement en charge gRPC traditionnel sur HTTP/2. Toutefois, le transcodage fonctionne à la fois avec HTTP/1.1 et HTTP/2. Certaines plateformes, comme UWP ou Unity, ne peuvent pas utiliser HTTP/2. Pour prendre en charge toutes les applications clientes, configurez le serveur pour activer HTTP/1.1 et HTTP/2.

Mettez à jour le protocole par défaut dans appsettings.json :

{
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http1AndHttp2"
    }
  }
}

Vous pouvez également configurer des points de terminaison Kestrel dans le code de démarrage.

L’activation de HTTP/1.1 et HTTP/2 sur le même port nécessite TLS pour la négociation du protocole. Pour plus d’informations sur la configuration des protocoles HTTP dans une application gRPC, consultez Négociation de protocole gRPC ASP.NET Core.

Transcodage JSON gRPC et gRPC-Web

Le transcodage et gRPC-Web permettent tous deux d’appeler les services gRPC à partir d’un navigateur. Toutefois, la façon dont chacun effectue cela diffère :

  • gRPC-Web permet aux applications de navigateur d’appeler les services gRPC à partir du navigateur avec le client gRPC-Web et Protobuf. gRPC-Web nécessite l’application de navigateur pour générer un client gRPC et a l’avantage d’envoyer des messages Protobuf petits et rapides.
  • Le transcodage permet aux applications de navigateur d’appeler des services gRPC comme s’il s’agissait d’API RESTful avec JSON. L’application de navigateur n’a pas besoin de générer un client gRPC ou de savoir quoi que ce soit sur gRPC.

Le service Greeter précédent peut être appelé à l’aide des API JavaScript du navigateur :

var name = nameInput.value;

fetch('/v1/greeter/' + name)
  .then((response) => response.json())
  .then((result) => {
    console.log(result.message);
    // Hello world
  });

grpc-gateway

grpc-gateway est une autre technologie permettant de créer des API JSON RESTful à partir de services gRPC. Elle utilise les mêmes annotations .proto pour mapper les concepts HTTP aux services gRPC.

grpc-gateway utilise la génération de code pour créer un serveur proxy inverse. Le proxy inverse traduit les appels RESTful en gRPC+Protobuf et envoie les appels via HTTP/2 au service gRPC. L’avantage de cette approche est que le service gRPC ne sait rien des API JSON RESTful. N’importe quel serveur gRPC peut utiliser grpc-gateway.

Pendant ce temps, le transcodage JSON gRPC s’exécute à l’intérieur d’une application ASP.NET Core. Il désérialise le JSON en messages Protobuf, puis appelle directement le service gRPC. Le transcodage dans ASP.NET Core offre des avantages aux développeurs d’applications .NET :

  • Moins complexe : les services gRPC et l’API JSON RESTful mappée s’exécutent sur une application ASP.NET Core.
  • Meilleures performances : le transcodage désérialise les messages JSON en Protobuf et appelle directement le service gRPC. Il existe des avantages significatifs en matière de performances à faire cela In-process par rapport à un nouvel appel gRPC à un autre serveur.
  • Coût inférieur : moins de serveurs pour une facture d’hébergement mensuelle plus petite.

Pour l’installation et l’utilisation de grpc-gateway, consultez le fichier README de grpc-gateway.

Ressources supplémentaires

gRPC est un framework d’appel de procédure distante (RPC) très performant. gRPC utilise HTTP/2, la diffusion en continu, Protobuf et les contrats de message pour créer des services en temps réel hautes performances.

L’une des limitations de gRPC est que toutes les plateformes ne peuvent pas l’utiliser. Les navigateurs ne prennent pas entièrement en charge HTTP/2, ce qui fait des API REST et de JSON le moyen principal d’obtenir des données dans des applications de navigateur. Malgré les avantages qu’apporte gRPC, les API REST et JSON ont une place importante dans les applications modernes. La création d’API web gRPC etJSON ajoute une surcharge indésirable au développement d’applications.

Ce document explique comment créer des API web JSON à l’aide des services gRPC.

Vue d’ensemble

le transcodage JSON gRPC est une extension pour ASP.NET Core qui crée des API RESTful JSON pour les services gRPC. Une fois configuré, le transcodage permet aux applications d’appeler des services gRPC avec des concepts HTTP familiers :

  • Verbes HTTP
  • Liaison de paramètre d’URL
  • Requêtes/réponses JSON

gRPC peut toujours être utilisé pour appeler des services.

Notes

Le transcodage JSON gRPC remplace l’API HTTP gRPC, une extension expérimentale alternative.

Usage

  1. Ajoutez une référence de package à Microsoft.AspNetCore.Grpc.JsonTranscoding.
  2. Inscrivez le transcodage dans le code de démarrage du serveur en ajoutant AddJsonTranscoding : Dans le fichier Program.cs, remplacez builder.Services.AddGrpc(); par builder.Services.AddGrpc().AddJsonTranscoding();.
  3. Créez la structure de répertoires /google/api dans le répertoire du projet qui contient le fichier .csproj.
  4. Ajoutez des fichiers google/api/http.proto et google/api/annotations.proto au répertoire /google/api.
  5. Annotez les méthodes gRPC dans vos fichiers .proto avec des liaisons et des itinéraires HTTP :
syntax = "proto3";

option csharp_namespace = "GrpcServiceTranscoding";
import "google/api/annotations.proto";

package greet;

// The greeting service definition.
service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {
    option (google.api.http) = {
      get: "/v1/greeter/{name}"
    };
  }
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings.
message HelloReply {
  string message = 1;
}

La méthode gRPC SayHello peut maintenant être appelée en tant que gRPC et en tant qu’API web JSON :

  • Demande : GET /v1/greeter/world
  • Réponse : { "message": "Hello world" }

Si le serveur est configuré pour écrire des journaux pour chaque requête, les journaux du serveur indiquent qu’un service gRPC exécute l’appel HTTP. Le transcodage mappe la requête HTTP entrante à un message gRPC et convertit le message de réponse en JSON.

info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET https://localhost:5001/v1/greeter/world
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint 'gRPC - /v1/greeter/{name}'
info: Server.GreeterService[0]
      Sending hello to world
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint 'gRPC - /v1/greeter/{name}'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 1.996ms 200 application/json

Annoter les méthodes gRPC

Les méthodes gRPC doivent être annotées avec une règle HTTP avant de prendre en charge le transcodage. La règle HTTP inclut des informations sur l’appel de la méthode gRPC, comme la méthode HTTP et l’itinéraire.

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {
    option (google.api.http) = {
      get: "/v1/greeter/{name}"
    };
  }
}

L’exemple suivant :

  • Définit un service Greeter avec une méthode SayHello. La méthode a une règle HTTP spécifiée avec le nom google.api.http.
  • La méthode est accessible avec les requêtes GET et l’itinéraire /v1/greeter/{name}.
  • Le champ name du message de requête est lié à un paramètre de routage.

De nombreuses options sont disponibles pour personnaliser la façon dont une méthode gRPC est liée à une API RESTful. Pour plus d’informations sur l’annotation des méthodes gRPC et la personnalisation de JSON, consultez Configurer HTTP et JSON pour le transcodage JSON gRPC.

Méthodes de diffusion en continu

gRPC sur HTTP/2 traditionnel prend en charge la diffusion en continu dans toutes les directions. Le transcodage est limité à la diffusion en continu de serveur uniquement. Les méthodes de diffusion en continu client et de diffusion en continu bidirectionnelle ne sont pas prises en charge.

Les méthodes de diffusion en continu de serveur utilisent du JSON délimité par ligne. Chaque message écrit avec WriteAsync est sérialisé en JSON et suivi d’une nouvelle ligne.

La méthode de diffusion en continu de serveur suivante écrit trois messages :

public override async Task StreamingFromServer(ExampleRequest request,
    IServerStreamWriter<ExampleResponse> responseStream, ServerCallContext context)
{
    for (var i = 1; i <= 3; i++)
    {
        await responseStream.WriteAsync(new ExampleResponse { Text = $"Message {i}" });
        await Task.Delay(TimeSpan.FromSeconds(1));
    }
}

Le client reçoit trois objets JSON délimités par une ligne :

{"Text":"Message 1"}
{"Text":"Message 2"}
{"Text":"Message 3"}

Notez que le paramètre WriteIndentedJSON ne s’applique pas aux méthodes de diffusion en continu du serveur. L’impression en mode Pretty ajoute de nouvelles lignes et des espaces blancs au JSON, ce qui ne peut pas être utilisé avec du JSON délimité par ligne.

Affichez ou téléchargez un exemple d’application de transcodage et de diffusion en continu ASP.NET Core gPRC.

Protocole HTTP

Le modèle de services ASP.NET Core gRPC, inclus dans le kit SDK .NET, crée une application configurée uniquement pour HTTP/2. HTTP/2 est un bon choix par défaut lorsqu’une application prend uniquement en charge gRPC traditionnel sur HTTP/2. Toutefois, le transcodage fonctionne à la fois avec HTTP/1.1 et HTTP/2. Certaines plateformes, comme UWP ou Unity, ne peuvent pas utiliser HTTP/2. Pour prendre en charge toutes les applications clientes, configurez le serveur pour activer HTTP/1.1 et HTTP/2.

Mettez à jour le protocole par défaut dans appsettings.json :

{
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http1AndHttp2"
    }
  }
}

Vous pouvez également configurer des points de terminaison Kestrel dans le code de démarrage.

L’activation de HTTP/1.1 et HTTP/2 sur le même port nécessite TLS pour la négociation du protocole. Pour plus d’informations sur la configuration des protocoles HTTP dans une application gRPC, consultez Négociation de protocole gRPC ASP.NET Core.

Transcodage JSON gRPC et gRPC-Web

Le transcodage et gRPC-Web permettent tous deux d’appeler les services gRPC à partir d’un navigateur. Toutefois, la façon dont chacun effectue cela diffère :

  • gRPC-Web permet aux applications de navigateur d’appeler les services gRPC à partir du navigateur avec le client gRPC-Web et Protobuf. gRPC-Web nécessite l’application de navigateur pour générer un client gRPC et a l’avantage d’envoyer des messages Protobuf petits et rapides.
  • Le transcodage permet aux applications de navigateur d’appeler des services gRPC comme s’il s’agissait d’API RESTful avec JSON. L’application de navigateur n’a pas besoin de générer un client gRPC ou de savoir quoi que ce soit sur gRPC.

Le service Greeter précédent peut être appelé à l’aide des API JavaScript du navigateur :

var name = nameInput.value;

fetch('/v1/greeter/' + name)
  .then((response) => response.json())
  .then((result) => {
    console.log(result.message);
    // Hello world
  });

grpc-gateway

grpc-gateway est une autre technologie permettant de créer des API JSON RESTful à partir de services gRPC. Elle utilise les mêmes annotations .proto pour mapper les concepts HTTP aux services gRPC.

grpc-gateway utilise la génération de code pour créer un serveur proxy inverse. Le proxy inverse traduit les appels RESTful en gRPC+Protobuf et envoie les appels via HTTP/2 au service gRPC. L’avantage de cette approche est que le service gRPC ne sait rien des API JSON RESTful. N’importe quel serveur gRPC peut utiliser grpc-gateway.

Pendant ce temps, le transcodage JSON gRPC s’exécute à l’intérieur d’une application ASP.NET Core. Il désérialise le JSON en messages Protobuf, puis appelle directement le service gRPC. Le transcodage dans ASP.NET Core offre des avantages aux développeurs d’applications .NET :

  • Moins complexe : les services gRPC et l’API JSON RESTful mappée s’exécutent sur une application ASP.NET Core.
  • Meilleures performances : le transcodage désérialise les messages JSON en Protobuf et appelle directement le service gRPC. Il existe des avantages significatifs en matière de performances à faire cela In-process par rapport à un nouvel appel gRPC à un autre serveur.
  • Coût inférieur : moins de serveurs pour une facture d’hébergement mensuelle plus petite.

Pour l’installation et l’utilisation de grpc-gateway, consultez le fichier README de grpc-gateway.

Ressources supplémentaires